@acpaas-ui/ngx-forms 6.1.10 → 6.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +27 -6
- package/.eslintrc.json +0 -42
- package/LICENSE.md +0 -21
- package/dist/README.md +0 -23
- package/dist/package.json +0 -44
- package/karma.conf.js +0 -38
- package/ng-package.json +0 -8
- package/src/lib/auto-complete/README.md +0 -148
- package/src/lib/auto-complete/auto-complete.module.ts +0 -15
- package/src/lib/auto-complete/components/auto-complete/auto-complete.component.html +0 -51
- package/src/lib/auto-complete/components/auto-complete/auto-complete.component.scss +0 -4
- package/src/lib/auto-complete/components/auto-complete/auto-complete.component.spec.ts +0 -378
- package/src/lib/auto-complete/components/auto-complete/auto-complete.component.ts +0 -281
- package/src/lib/auto-complete/public-api.ts +0 -2
- package/src/lib/datepicker/README.md +0 -110
- package/src/lib/datepicker/components/datepicker/datepicker.component.html +0 -47
- package/src/lib/datepicker/components/datepicker/datepicker.component.scss +0 -13
- package/src/lib/datepicker/components/datepicker/datepicker.component.spec.ts +0 -204
- package/src/lib/datepicker/components/datepicker/datepicker.component.ts +0 -251
- package/src/lib/datepicker/datepicker.conf.ts +0 -11
- package/src/lib/datepicker/datepicker.module.ts +0 -50
- package/src/lib/datepicker/public-api.ts +0 -8
- package/src/lib/datepicker/types/datepicker.types.ts +0 -8
- package/src/lib/range-slider/README.md +0 -56
- package/src/lib/range-slider/components/range-slider/range-slider.component.html +0 -46
- package/src/lib/range-slider/components/range-slider/range-slider.component.scss +0 -12
- package/src/lib/range-slider/components/range-slider/range-slider.component.spec.ts +0 -216
- package/src/lib/range-slider/components/range-slider/range-slider.component.ts +0 -301
- package/src/lib/range-slider/public-api.ts +0 -3
- package/src/lib/range-slider/range-slider.module.ts +0 -11
- package/src/lib/range-slider/types/range-slider.types.ts +0 -4
- package/src/lib/search-filter/README.md +0 -86
- package/src/lib/search-filter/components/search-filter/search-filter.component.html +0 -66
- package/src/lib/search-filter/components/search-filter/search-filter.component.scss +0 -23
- package/src/lib/search-filter/components/search-filter/search-filter.component.spec.ts +0 -264
- package/src/lib/search-filter/components/search-filter/search-filter.component.ts +0 -140
- package/src/lib/search-filter/public-api.ts +0 -3
- package/src/lib/search-filter/search-filter.module.ts +0 -13
- package/src/lib/search-filter/types/search-filter.types.ts +0 -4
- package/src/lib/shared/services/search.service.spec.ts +0 -78
- package/src/lib/shared/services/search.service.ts +0 -32
- package/src/lib/shared/types/search.types.ts +0 -6
- package/src/lib/timepicker/README.md +0 -84
- package/src/lib/timepicker/classes/timepicker.validators.spec.ts +0 -54
- package/src/lib/timepicker/classes/timepicker.validators.ts +0 -61
- package/src/lib/timepicker/components/timepicker/timepicker.component.html +0 -37
- package/src/lib/timepicker/components/timepicker/timepicker.component.scss +0 -3
- package/src/lib/timepicker/components/timepicker/timepicker.component.spec.ts +0 -161
- package/src/lib/timepicker/components/timepicker/timepicker.component.ts +0 -128
- package/src/lib/timepicker/public-api.ts +0 -4
- package/src/lib/timepicker/timepicker.module.ts +0 -13
- package/src/lib/timepicker/types/timepicker.types.ts +0 -5
- package/src/lib/upload/README.md +0 -283
- package/src/lib/upload/classes/uploader.class.spec.ts +0 -100
- package/src/lib/upload/classes/uploader.class.ts +0 -144
- package/src/lib/upload/components/upload/upload.component.html +0 -28
- package/src/lib/upload/components/upload/upload.component.scss +0 -3
- package/src/lib/upload/components/upload/upload.component.spec.ts +0 -117
- package/src/lib/upload/components/upload/upload.component.ts +0 -50
- package/src/lib/upload/components/upload-input/upload-input.component.html +0 -11
- package/src/lib/upload/components/upload-input/upload-input.component.spec.ts +0 -55
- package/src/lib/upload/components/upload-input/upload-input.component.ts +0 -35
- package/src/lib/upload/components/upload-queue/upload-queue.component.html +0 -16
- package/src/lib/upload/components/upload-queue/upload-queue.component.spec.ts +0 -99
- package/src/lib/upload/components/upload-queue/upload-queue.component.ts +0 -36
- package/src/lib/upload/components/upload-zone/upload-zone.component.html +0 -55
- package/src/lib/upload/components/upload-zone/upload-zone.component.scss +0 -3
- package/src/lib/upload/components/upload-zone/upload-zone.component.spec.ts +0 -144
- package/src/lib/upload/components/upload-zone/upload-zone.component.ts +0 -142
- package/src/lib/upload/components/validation-list/validation-list.component.html +0 -15
- package/src/lib/upload/components/validation-list/validation-list.component.spec.ts +0 -57
- package/src/lib/upload/components/validation-list/validation-list.component.ts +0 -29
- package/src/lib/upload/public-api.ts +0 -10
- package/src/lib/upload/services/validation-messages.service.spec.ts +0 -66
- package/src/lib/upload/services/validation-messages.service.ts +0 -27
- package/src/lib/upload/types/upload.types.ts +0 -20
- package/src/lib/upload/upload.conf.ts +0 -15
- package/src/lib/upload/upload.module.ts +0 -34
- package/src/public-api.ts +0 -6
- package/src/test.ts +0 -9
- package/tsconfig.lib.json +0 -26
- package/tsconfig.spec.json +0 -17
- /package/{dist/esm2020 → esm2020}/acpaas-ui-ngx-forms.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/auto-complete/auto-complete.module.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/auto-complete/components/auto-complete/auto-complete.component.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/auto-complete/public-api.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/datepicker/components/datepicker/datepicker.component.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/datepicker/datepicker.conf.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/datepicker/datepicker.module.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/datepicker/public-api.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/datepicker/types/datepicker.types.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/range-slider/components/range-slider/range-slider.component.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/range-slider/public-api.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/range-slider/range-slider.module.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/range-slider/types/range-slider.types.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/search-filter/components/search-filter/search-filter.component.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/search-filter/public-api.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/search-filter/search-filter.module.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/search-filter/types/search-filter.types.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/shared/services/search.service.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/shared/types/search.types.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/timepicker/classes/timepicker.validators.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/timepicker/components/timepicker/timepicker.component.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/timepicker/public-api.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/timepicker/timepicker.module.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/timepicker/types/timepicker.types.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/upload/classes/uploader.class.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/upload/components/upload/upload.component.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/upload/components/upload-input/upload-input.component.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/upload/components/upload-queue/upload-queue.component.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/upload/components/upload-zone/upload-zone.component.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/upload/components/validation-list/validation-list.component.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/upload/public-api.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/upload/services/validation-messages.service.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/upload/types/upload.types.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/upload/upload.conf.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/lib/upload/upload.module.mjs +0 -0
- /package/{dist/esm2020 → esm2020}/public-api.mjs +0 -0
- /package/{dist/fesm2015 → fesm2015}/acpaas-ui-ngx-forms.mjs +0 -0
- /package/{dist/fesm2015 → fesm2015}/acpaas-ui-ngx-forms.mjs.map +0 -0
- /package/{dist/fesm2020 → fesm2020}/acpaas-ui-ngx-forms.mjs +0 -0
- /package/{dist/fesm2020 → fesm2020}/acpaas-ui-ngx-forms.mjs.map +0 -0
- /package/{dist/index.d.ts → index.d.ts} +0 -0
- /package/{dist/lib → lib}/auto-complete/auto-complete.module.d.ts +0 -0
- /package/{dist/lib → lib}/auto-complete/components/auto-complete/auto-complete.component.d.ts +0 -0
- /package/{dist/lib → lib}/auto-complete/public-api.d.ts +0 -0
- /package/{dist/lib → lib}/datepicker/components/datepicker/datepicker.component.d.ts +0 -0
- /package/{dist/lib → lib}/datepicker/datepicker.conf.d.ts +0 -0
- /package/{dist/lib → lib}/datepicker/datepicker.module.d.ts +0 -0
- /package/{dist/lib → lib}/datepicker/public-api.d.ts +0 -0
- /package/{dist/lib → lib}/datepicker/types/datepicker.types.d.ts +0 -0
- /package/{dist/lib → lib}/range-slider/components/range-slider/range-slider.component.d.ts +0 -0
- /package/{dist/lib → lib}/range-slider/public-api.d.ts +0 -0
- /package/{dist/lib → lib}/range-slider/range-slider.module.d.ts +0 -0
- /package/{dist/lib → lib}/range-slider/types/range-slider.types.d.ts +0 -0
- /package/{dist/lib → lib}/search-filter/components/search-filter/search-filter.component.d.ts +0 -0
- /package/{dist/lib → lib}/search-filter/public-api.d.ts +0 -0
- /package/{dist/lib → lib}/search-filter/search-filter.module.d.ts +0 -0
- /package/{dist/lib → lib}/search-filter/types/search-filter.types.d.ts +0 -0
- /package/{dist/lib → lib}/shared/services/search.service.d.ts +0 -0
- /package/{dist/lib → lib}/shared/types/search.types.d.ts +0 -0
- /package/{dist/lib → lib}/timepicker/classes/timepicker.validators.d.ts +0 -0
- /package/{dist/lib → lib}/timepicker/components/timepicker/timepicker.component.d.ts +0 -0
- /package/{dist/lib → lib}/timepicker/public-api.d.ts +0 -0
- /package/{dist/lib → lib}/timepicker/timepicker.module.d.ts +0 -0
- /package/{dist/lib → lib}/timepicker/types/timepicker.types.d.ts +0 -0
- /package/{dist/lib → lib}/upload/classes/uploader.class.d.ts +0 -0
- /package/{dist/lib → lib}/upload/components/upload/upload.component.d.ts +0 -0
- /package/{dist/lib → lib}/upload/components/upload-input/upload-input.component.d.ts +0 -0
- /package/{dist/lib → lib}/upload/components/upload-queue/upload-queue.component.d.ts +0 -0
- /package/{dist/lib → lib}/upload/components/upload-zone/upload-zone.component.d.ts +0 -0
- /package/{dist/lib → lib}/upload/components/validation-list/validation-list.component.d.ts +0 -0
- /package/{dist/lib → lib}/upload/public-api.d.ts +0 -0
- /package/{dist/lib → lib}/upload/services/validation-messages.service.d.ts +0 -0
- /package/{dist/lib → lib}/upload/types/upload.types.d.ts +0 -0
- /package/{dist/lib → lib}/upload/upload.conf.d.ts +0 -0
- /package/{dist/lib → lib}/upload/upload.module.d.ts +0 -0
- /package/{dist/public-api.d.ts → public-api.d.ts} +0 -0
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
# @acpaas-ui/ngx-forms
|
|
2
|
-
|
|
3
|
-
The searchfilter is a JIRA-like filter component with remote search capabilities.
|
|
4
|
-
|
|
5
|
-
## Usage
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
import { SearchFilterModule } from '@acpaas-ui/ngx-forms'`;
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Documentation
|
|
12
|
-
|
|
13
|
-
Visit our [documentation site](https://antwerp-ui.digipolis.be/) for full how-to docs and guidelines
|
|
14
|
-
|
|
15
|
-
### API
|
|
16
|
-
|
|
17
|
-
| Name | Default value | Description |
|
|
18
|
-
| ----------------------------------------- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
19
|
-
| `@Input() id: string;` | - | Field id. |
|
|
20
|
-
| `@Input() name: string;` | - | Field name. |
|
|
21
|
-
| `@Input() flyoutSize: enum;` | `FlyoutSize.Small` | Passed along to [`auiFlyout`](https://github.com/digipolisantwerp/antwerp-ui_angular/tree/master/packages/flyout/lib/src/flyout). |
|
|
22
|
-
| `@Input() flyoutAlign: string;` | `'left'` | Passed along to [`auiFlyout`](https://github.com/digipolisantwerp/antwerp-ui_angular/tree/master/packages/flyout/lib/src/flyout). |
|
|
23
|
-
| `@Input() label: string;` | `'Filter'` | Field label. |
|
|
24
|
-
| `@Input() labelDeselect: string;` | `'Alles deselecteren'` | Clear button text. |
|
|
25
|
-
| `@Input() labelResults: string;` | `'Resultaten'` | Result list header text. |
|
|
26
|
-
| `@Input() labelNoResults: string;` | `'Geen resultaten gevonden.'` | Text shown when no results are found. |
|
|
27
|
-
| `@Input() choices: SearchFilterChoice[];` | - | Available choices. |
|
|
28
|
-
| `@Input() remote: boolean;` | `false` | Enable remote searching. |
|
|
29
|
-
| `@Input() description: string;` | `'Zoeken'` | Search field description text. |
|
|
30
|
-
| `@Input() inputDelay: number;` | `150` | Delay the search callback on the input field. |
|
|
31
|
-
| `@Input() showAllByDefault: boolean;` | `false` | Show all items on init, will trigger a search when `remote` is `true`. |
|
|
32
|
-
| `@Output() search: Event<string>;` | - | Callback triggered when `remote` is true. |
|
|
33
|
-
|
|
34
|
-
### Example
|
|
35
|
-
|
|
36
|
-
```typescript
|
|
37
|
-
import { SearchFilterModule } from '@acpaas-ui/ngx-forms';
|
|
38
|
-
|
|
39
|
-
@NgModule({
|
|
40
|
-
imports: [
|
|
41
|
-
SearchFilterModule,
|
|
42
|
-
]
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
export class AppModule {};
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
#### Basic
|
|
49
|
-
|
|
50
|
-
```typescript
|
|
51
|
-
import { SearchFilterChoice } from '@acpaas-ui/ngx-forms';
|
|
52
|
-
|
|
53
|
-
public stuff: SearchFilterChoice[] = [{
|
|
54
|
-
label: "First item",
|
|
55
|
-
value: "one",
|
|
56
|
-
}, {
|
|
57
|
-
label: "Second item",
|
|
58
|
-
value: "two",
|
|
59
|
-
}, {
|
|
60
|
-
label: "Third item",
|
|
61
|
-
value: "three",
|
|
62
|
-
}, {
|
|
63
|
-
label: "Fourth item",
|
|
64
|
-
value: "four",
|
|
65
|
-
}];
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
```html
|
|
69
|
-
<aui-search-filter
|
|
70
|
-
id="test"
|
|
71
|
-
name="test"
|
|
72
|
-
label="Find stuff"
|
|
73
|
-
labelDeselect="Clear stuff"
|
|
74
|
-
labelResults=""
|
|
75
|
-
labelNoResults="Couldn't find stuff!"
|
|
76
|
-
description="Look for stuff"
|
|
77
|
-
inputDelay="0"
|
|
78
|
-
[choices]="stuff"
|
|
79
|
-
[showAllByDefault]="true"
|
|
80
|
-
>
|
|
81
|
-
</aui-search-filter>
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## Contributing
|
|
85
|
-
|
|
86
|
-
Visit our [Contribution Guidelines](../../../../../CONTRIBUTING.md) for more information on how to contribute.
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
<div [align]="flyoutAlign" [size]="flyoutSize" aria-haspopup="listbox" auiFlyout class="m-search-filter">
|
|
2
|
-
<div
|
|
3
|
-
class="a-input"
|
|
4
|
-
[ngClass]="{
|
|
5
|
-
'a-input--l': size === 'large',
|
|
6
|
-
'a-input--s': size === 'small',
|
|
7
|
-
'has-icon-right': hasClose
|
|
8
|
-
}"
|
|
9
|
-
>
|
|
10
|
-
<label class="a-input__label" for="{{ id + '-search' }}">{{ label }}</label>
|
|
11
|
-
<small class="a-input__description" id="{{ id + '-description' }}">{{ description }}</small>
|
|
12
|
-
<div class="m-search-filter__input">
|
|
13
|
-
<input
|
|
14
|
-
(input)="filterDataFromSearch()"
|
|
15
|
-
[(ngModel)]="query"
|
|
16
|
-
[attr.aria-labelledby]="id + '-label'"
|
|
17
|
-
[attr.disabled]="isDisabled ? '' : null"
|
|
18
|
-
aria-autocomplete="list"
|
|
19
|
-
id="{{ id + '-search' }}"
|
|
20
|
-
name="{{ name + '-search' }}"
|
|
21
|
-
value="{{ getSelectedLabels() }}"
|
|
22
|
-
type="text"
|
|
23
|
-
auiFlyoutAction
|
|
24
|
-
/>
|
|
25
|
-
<button
|
|
26
|
-
*ngIf="hasClose"
|
|
27
|
-
[ngClass]="{
|
|
28
|
-
'a-button--l': size === 'large',
|
|
29
|
-
'a-button--s': size === 'small'
|
|
30
|
-
}"
|
|
31
|
-
class="a-button a-button--outlined has-icon m-search-filter__button a-button--danger"
|
|
32
|
-
aria-label="Zoekopdracht wissen"
|
|
33
|
-
type="button"
|
|
34
|
-
(click)="clear()"
|
|
35
|
-
[attr.disabled]="isDisabled || closeDisabled ? '' : null"
|
|
36
|
-
>
|
|
37
|
-
<aui-icon name="ai-close"></aui-icon>
|
|
38
|
-
</button>
|
|
39
|
-
<aui-icon *ngIf="!hasClose" name="ai-close"></aui-icon>
|
|
40
|
-
</div>
|
|
41
|
-
</div>
|
|
42
|
-
<div auiFlyoutZone class="m-search-filter__search m-search-filter__search--scroll">
|
|
43
|
-
<p *ngIf="labelResults" class="h6 m-search-filter__results-title u-margin-bottom-xs">{{ labelResults }}</p>
|
|
44
|
-
<div *ngIf="loading" class="u-text-center u-padding a-spinner"></div>
|
|
45
|
-
<ul *ngIf="!loading" class="a-checkbox-list a-checkbox-list--flushed">
|
|
46
|
-
<li *ngIf="!filteredChoices.length" class="a-checkbox-list__item">
|
|
47
|
-
<p class="u-margin-xs">{{ labelNoResults }}</p>
|
|
48
|
-
</li>
|
|
49
|
-
<li *ngFor="let choice of filteredChoices; index as i" class="a-checkbox-list__item">
|
|
50
|
-
<div class="a-input a-checkbox-list__checkbox">
|
|
51
|
-
<div class="a-input__checkbox">
|
|
52
|
-
<input
|
|
53
|
-
(change)="toggleSelected(choice.label)"
|
|
54
|
-
[attr.disabled]="isDisabled ? true : null"
|
|
55
|
-
[checked]="selectedItems.indexOf(choice.label) >= 0"
|
|
56
|
-
id="{{ 'checkbox--' + i + '--' + id }}"
|
|
57
|
-
name="{{ 'checkbox--' + i + '--' + id }}"
|
|
58
|
-
type="checkbox"
|
|
59
|
-
/>
|
|
60
|
-
<label for="{{ 'checkbox--' + i + '--' + id }}">{{ choice.label }}</label>
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
63
|
-
</li>
|
|
64
|
-
</ul>
|
|
65
|
-
</div>
|
|
66
|
-
</div>
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
.m-search-filter {
|
|
2
|
-
display: block;
|
|
3
|
-
&__input {
|
|
4
|
-
display: flex;
|
|
5
|
-
padding: 0;
|
|
6
|
-
|
|
7
|
-
input {
|
|
8
|
-
border-right: none;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
&__button {
|
|
12
|
-
display: inline-block;
|
|
13
|
-
padding: 0;
|
|
14
|
-
position: relative;
|
|
15
|
-
vertical-align: middle;
|
|
16
|
-
|
|
17
|
-
.ai {
|
|
18
|
-
position: relative;
|
|
19
|
-
transform: none !important;
|
|
20
|
-
top: 0;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
}
|
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
-
import { By } from '@angular/platform-browser';
|
|
3
|
-
import { DebugElement } from '@angular/core';
|
|
4
|
-
import { FormsModule } from '@angular/forms';
|
|
5
|
-
import { FlyoutModule } from '@acpaas-ui/ngx-flyout';
|
|
6
|
-
import { IconModule } from '@acpaas-ui/ngx-icon';
|
|
7
|
-
|
|
8
|
-
import { SearchFilterComponent } from './search-filter.component';
|
|
9
|
-
|
|
10
|
-
describe('The SearchFilter Component', () => {
|
|
11
|
-
let comp: SearchFilterComponent;
|
|
12
|
-
let fixture: ComponentFixture<SearchFilterComponent>;
|
|
13
|
-
let de: DebugElement;
|
|
14
|
-
let el: HTMLElement;
|
|
15
|
-
|
|
16
|
-
// waitForAsync beforeEach
|
|
17
|
-
beforeEach(waitForAsync(() => {
|
|
18
|
-
TestBed.configureTestingModule({
|
|
19
|
-
imports: [FormsModule, FlyoutModule, IconModule],
|
|
20
|
-
declarations: [SearchFilterComponent],
|
|
21
|
-
}).compileComponents();
|
|
22
|
-
}));
|
|
23
|
-
|
|
24
|
-
// synchronous beforeEach
|
|
25
|
-
beforeEach(() => {
|
|
26
|
-
fixture = TestBed.createComponent(SearchFilterComponent);
|
|
27
|
-
|
|
28
|
-
comp = fixture.componentInstance;
|
|
29
|
-
|
|
30
|
-
de = fixture.debugElement.query(By.css('.m-search-filter'));
|
|
31
|
-
el = de.nativeElement;
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('should show a spinner when loading results', () => {
|
|
35
|
-
comp.loading = true;
|
|
36
|
-
|
|
37
|
-
fixture.detectChanges();
|
|
38
|
-
|
|
39
|
-
expect(el.querySelector('.a-list')).toBeNull();
|
|
40
|
-
expect(el.querySelector('a-spinner')).toBeDefined();
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('should show the noResults label when not loading and missing results', () => {
|
|
44
|
-
comp.labelNoResults = 'test-noResults';
|
|
45
|
-
|
|
46
|
-
fixture.detectChanges();
|
|
47
|
-
|
|
48
|
-
expect(el.querySelectorAll('.a-checkbox-list').length).toBe(1);
|
|
49
|
-
expect(el.querySelector('.u-margin-xs')?.textContent).toContain('test-noResults');
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('should show the clear button when there are selected items', () => {
|
|
53
|
-
comp.selectedItems = ['one'];
|
|
54
|
-
|
|
55
|
-
fixture.detectChanges();
|
|
56
|
-
|
|
57
|
-
expect(el.querySelector('.ai-close')).toBeDefined();
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('should show the available choices', () => {
|
|
61
|
-
spyOn(comp, 'getSelectedLabels').and.stub();
|
|
62
|
-
comp.selectedItems = ['2'];
|
|
63
|
-
comp.filteredChoices = [
|
|
64
|
-
{
|
|
65
|
-
label: 'one',
|
|
66
|
-
value: '1',
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
label: 'two',
|
|
70
|
-
value: '2',
|
|
71
|
-
},
|
|
72
|
-
];
|
|
73
|
-
|
|
74
|
-
fixture.detectChanges();
|
|
75
|
-
|
|
76
|
-
expect(el.querySelectorAll('.a-input__checkbox').length).toBe(2);
|
|
77
|
-
|
|
78
|
-
const items = Array.from(el.querySelectorAll('.a-input__checkbox'));
|
|
79
|
-
|
|
80
|
-
expect(items[0].querySelector('label').textContent).toBe('one');
|
|
81
|
-
expect(items[1].querySelector('label').textContent).toBe('two');
|
|
82
|
-
expect(comp.getSelectedLabels).toHaveBeenCalled();
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it('should update the selectedItems if a valid value is provided', () => {
|
|
86
|
-
comp.writeValue(['two']);
|
|
87
|
-
|
|
88
|
-
expect(comp.selectedItems).toEqual(['two']);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('should clear the selectedItems if an invalid value is provided', () => {
|
|
92
|
-
comp.selectedItems = ['one'];
|
|
93
|
-
|
|
94
|
-
expect(comp.selectedItems).toEqual(['one']);
|
|
95
|
-
|
|
96
|
-
comp.writeValue('test' as any);
|
|
97
|
-
|
|
98
|
-
expect(comp.selectedItems).toEqual([]);
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it('should update the filteredChoices OnChange if remote is true', () => {
|
|
102
|
-
comp.filteredChoices = [];
|
|
103
|
-
comp.remote = true;
|
|
104
|
-
comp.loading = true;
|
|
105
|
-
|
|
106
|
-
fixture.detectChanges();
|
|
107
|
-
|
|
108
|
-
comp.ngOnChanges({
|
|
109
|
-
choices: {
|
|
110
|
-
currentValue: [
|
|
111
|
-
{
|
|
112
|
-
label: 'one',
|
|
113
|
-
value: '1',
|
|
114
|
-
},
|
|
115
|
-
],
|
|
116
|
-
},
|
|
117
|
-
} as any);
|
|
118
|
-
|
|
119
|
-
expect(comp.filteredChoices).toEqual([
|
|
120
|
-
{
|
|
121
|
-
label: 'one',
|
|
122
|
-
value: '1',
|
|
123
|
-
},
|
|
124
|
-
]);
|
|
125
|
-
expect(comp.loading).toBeFalsy();
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it('should refilter the choices OnChange if remote is false', () => {
|
|
129
|
-
spyOn(comp, 'filterData').and.stub();
|
|
130
|
-
|
|
131
|
-
fixture.detectChanges();
|
|
132
|
-
|
|
133
|
-
comp.ngOnChanges({
|
|
134
|
-
choices: {
|
|
135
|
-
currentValue: [
|
|
136
|
-
{
|
|
137
|
-
label: 'one',
|
|
138
|
-
value: '1',
|
|
139
|
-
},
|
|
140
|
-
],
|
|
141
|
-
},
|
|
142
|
-
} as any);
|
|
143
|
-
|
|
144
|
-
expect(comp.filterData).toHaveBeenCalled();
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it('should do nothing OnChange if the choices were not updated', () => {
|
|
148
|
-
spyOn(comp, 'filterData').and.stub();
|
|
149
|
-
|
|
150
|
-
fixture.detectChanges();
|
|
151
|
-
|
|
152
|
-
comp.ngOnChanges({} as any);
|
|
153
|
-
|
|
154
|
-
expect(comp.filterData).not.toHaveBeenCalled();
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it('should emit a search if filterData is called when remote is true', () => {
|
|
158
|
-
comp.remote = true;
|
|
159
|
-
comp.query = 'test';
|
|
160
|
-
|
|
161
|
-
spyOn(comp.search, 'emit').and.stub();
|
|
162
|
-
|
|
163
|
-
fixture.detectChanges();
|
|
164
|
-
|
|
165
|
-
comp.filterData();
|
|
166
|
-
|
|
167
|
-
expect(comp.loading).toBeTruthy();
|
|
168
|
-
expect(comp.search.emit).toHaveBeenCalledWith('test');
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
it('should call filterChoices if filterData is called when remote is false', () => {
|
|
172
|
-
spyOn(comp.search, 'emit').and.stub();
|
|
173
|
-
spyOn(comp as any, 'filterChoices').and.stub();
|
|
174
|
-
|
|
175
|
-
fixture.detectChanges();
|
|
176
|
-
|
|
177
|
-
comp.filterData();
|
|
178
|
-
|
|
179
|
-
expect(comp.loading).toBeFalsy();
|
|
180
|
-
expect(comp.search.emit).not.toHaveBeenCalled();
|
|
181
|
-
expect((comp as any).filterChoices).toHaveBeenCalled();
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
it('should clear the selectedItems and query, filter the data and update the model on clear', () => {
|
|
185
|
-
comp.selectedItems = ['one'];
|
|
186
|
-
comp.query = 'on';
|
|
187
|
-
|
|
188
|
-
spyOn(comp, 'filterData').and.stub();
|
|
189
|
-
spyOn(comp, 'updateModel').and.stub();
|
|
190
|
-
spyOn(comp, 'onClear').and.stub();
|
|
191
|
-
|
|
192
|
-
fixture.detectChanges();
|
|
193
|
-
|
|
194
|
-
comp.clear();
|
|
195
|
-
|
|
196
|
-
expect(comp.selectedItems.length).toBe(0);
|
|
197
|
-
expect(comp.query.length).toBe(0);
|
|
198
|
-
expect(comp.filterData).toHaveBeenCalled();
|
|
199
|
-
expect(comp.updateModel).toHaveBeenCalledWith([]);
|
|
200
|
-
expect(comp.onClear).toHaveBeenCalled();
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it('should add the selected item if it was not in the selectedItems array and update the model value', () => {
|
|
204
|
-
comp.selectedItems = ['one'];
|
|
205
|
-
|
|
206
|
-
spyOn(comp, 'updateModel').and.stub();
|
|
207
|
-
|
|
208
|
-
fixture.detectChanges();
|
|
209
|
-
|
|
210
|
-
comp.toggleSelected('two');
|
|
211
|
-
|
|
212
|
-
expect(comp.selectedItems).toEqual(['one', 'two']);
|
|
213
|
-
expect(comp.updateModel).toHaveBeenCalledWith(['one', 'two']);
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
it('should remove the selected item if it was present in the selectedItems array and update the model value', () => {
|
|
217
|
-
comp.selectedItems = ['one', 'two', 'three'];
|
|
218
|
-
|
|
219
|
-
spyOn(comp, 'updateModel').and.stub();
|
|
220
|
-
|
|
221
|
-
fixture.detectChanges();
|
|
222
|
-
|
|
223
|
-
comp.toggleSelected('two');
|
|
224
|
-
|
|
225
|
-
expect(comp.selectedItems).toEqual(['one', 'three']);
|
|
226
|
-
expect(comp.updateModel).toHaveBeenCalledWith(['one', 'three']);
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
it('should update the filteredChoices with choices that match the query', () => {
|
|
230
|
-
comp.choices = [
|
|
231
|
-
{
|
|
232
|
-
label: 'First item',
|
|
233
|
-
value: 'one',
|
|
234
|
-
},
|
|
235
|
-
{
|
|
236
|
-
label: 'Second item',
|
|
237
|
-
value: 'two',
|
|
238
|
-
},
|
|
239
|
-
{
|
|
240
|
-
label: 'Third item',
|
|
241
|
-
value: 'three',
|
|
242
|
-
},
|
|
243
|
-
{
|
|
244
|
-
label: 'Fourth item',
|
|
245
|
-
value: 'four',
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
label: 'Fifth item',
|
|
249
|
-
value: 'five',
|
|
250
|
-
},
|
|
251
|
-
];
|
|
252
|
-
comp.query = 'fi';
|
|
253
|
-
|
|
254
|
-
fixture.detectChanges();
|
|
255
|
-
|
|
256
|
-
(comp as any).filterChoices();
|
|
257
|
-
expect(comp.filteredChoices.length).toBe(2);
|
|
258
|
-
|
|
259
|
-
comp.query = 'item';
|
|
260
|
-
|
|
261
|
-
(comp as any).filterChoices();
|
|
262
|
-
expect(comp.filteredChoices.length).toBe(5);
|
|
263
|
-
});
|
|
264
|
-
});
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { Component, EventEmitter, forwardRef, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
|
|
2
|
-
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
3
|
-
import { debounce, get } from 'lodash-es';
|
|
4
|
-
|
|
5
|
-
import { FlyoutSize } from '@acpaas-ui/ngx-flyout';
|
|
6
|
-
|
|
7
|
-
import { SearchFilterChoice } from '../../types/search-filter.types';
|
|
8
|
-
|
|
9
|
-
@Component({
|
|
10
|
-
selector: 'aui-search-filter',
|
|
11
|
-
templateUrl: './search-filter.component.html',
|
|
12
|
-
styleUrls: ['./search-filter.component.scss'],
|
|
13
|
-
providers: [
|
|
14
|
-
{
|
|
15
|
-
provide: NG_VALUE_ACCESSOR,
|
|
16
|
-
useExisting: forwardRef(() => SearchFilterComponent), // eslint-disable-line @angular-eslint/no-forward-ref
|
|
17
|
-
multi: true,
|
|
18
|
-
},
|
|
19
|
-
],
|
|
20
|
-
})
|
|
21
|
-
export class SearchFilterComponent implements OnChanges, ControlValueAccessor {
|
|
22
|
-
@Input() public id: string;
|
|
23
|
-
@Input() public name: string;
|
|
24
|
-
@Input() public flyoutSize = FlyoutSize.Small;
|
|
25
|
-
@Input() public flyoutAlign;
|
|
26
|
-
@Input() public label: string;
|
|
27
|
-
@Input() public description: string;
|
|
28
|
-
@Input() public labelDeselect = 'Alles deselecteren';
|
|
29
|
-
@Input() public labelResults = 'Resultaten';
|
|
30
|
-
@Input() public labelNoResults = 'Geen resultaten gevonden.';
|
|
31
|
-
@Input() public choices: SearchFilterChoice[] = [];
|
|
32
|
-
@Input() public remote: boolean;
|
|
33
|
-
@Input() public inputDelay = 150;
|
|
34
|
-
@Input() public onSelect: () => void = () => {};
|
|
35
|
-
@Input() public onClear: () => void = () => {};
|
|
36
|
-
@Input() public size: 'large' | 'default' | 'small' | 'tiny' = 'default';
|
|
37
|
-
|
|
38
|
-
@Output() public search: EventEmitter<string> = new EventEmitter<string>();
|
|
39
|
-
|
|
40
|
-
public query = '';
|
|
41
|
-
public selectedItems: string[] = [];
|
|
42
|
-
public filteredChoices: SearchFilterChoice[] = [];
|
|
43
|
-
public loading = false;
|
|
44
|
-
public isDisabled = false;
|
|
45
|
-
public closeDisabled = false;
|
|
46
|
-
|
|
47
|
-
public filterDataFromSearch: () => {};
|
|
48
|
-
|
|
49
|
-
constructor() {
|
|
50
|
-
this.filterDataFromSearch = debounce(this.filterData.bind(this), this.inputDelay);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
public updateModel: (_) => any = () => {};
|
|
54
|
-
|
|
55
|
-
public writeValue(value: string[]): void {
|
|
56
|
-
this.selectedItems = Array.isArray(value) ? value : [];
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
public registerOnChange(onChange: (_) => any): void {
|
|
60
|
-
this.updateModel = onChange;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
public registerOnTouched(): void {}
|
|
64
|
-
|
|
65
|
-
public setDisabledState(isDisabled: boolean): void {
|
|
66
|
-
this.isDisabled = isDisabled;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
public ngOnChanges(changes: SimpleChanges): void {
|
|
70
|
-
const choices = get(changes, 'choices.currentValue', null);
|
|
71
|
-
|
|
72
|
-
if (!choices) {
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (this.remote) {
|
|
77
|
-
this.filteredChoices = [...choices];
|
|
78
|
-
this.loading = false;
|
|
79
|
-
} else {
|
|
80
|
-
this.filterData();
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
public filterData(): void {
|
|
85
|
-
if (this.remote) {
|
|
86
|
-
this.loading = true;
|
|
87
|
-
|
|
88
|
-
return this.search.emit(this.query);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
this.filterChoices();
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
public clear(): void {
|
|
95
|
-
this.selectedItems = [];
|
|
96
|
-
this.query = '';
|
|
97
|
-
this.filterData();
|
|
98
|
-
this.updateModel(this.selectedItems);
|
|
99
|
-
this.onClear();
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
public toggleSelected(choice: string): void {
|
|
103
|
-
const selected = this.selectedItems.indexOf(choice);
|
|
104
|
-
|
|
105
|
-
if (selected < 0) {
|
|
106
|
-
this.selectedItems = this.selectedItems.concat(choice);
|
|
107
|
-
} else {
|
|
108
|
-
this.selectedItems = [...this.selectedItems.slice(0, selected), ...this.selectedItems.slice(selected + 1)];
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
this.updateModel(this.selectedItems);
|
|
112
|
-
this.onSelect();
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
private filterChoices(): void {
|
|
116
|
-
this.filteredChoices = this.choices.filter((choice: SearchFilterChoice) => {
|
|
117
|
-
return (
|
|
118
|
-
this.selectedItems.indexOf(choice.value) < 0 &&
|
|
119
|
-
choice.label.toLowerCase().indexOf(this.query.toLowerCase()) >= 0
|
|
120
|
-
);
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
public hasClose(): boolean {
|
|
125
|
-
return this.filteredChoices?.length && this.query?.length > 1;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
public getSelectedLabels(): string {
|
|
129
|
-
if (!this.selectedItems.length) {
|
|
130
|
-
this.closeDisabled = true;
|
|
131
|
-
return null
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
else {
|
|
135
|
-
this.closeDisabled = false;
|
|
136
|
-
return this.selectedItems.map((el) => el).join(', ')
|
|
137
|
-
}}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { NgModule } from '@angular/core';
|
|
2
|
-
import { FormsModule } from '@angular/forms';
|
|
3
|
-
import { CommonModule } from '@angular/common';
|
|
4
|
-
import { FlyoutModule } from '@acpaas-ui/ngx-flyout';
|
|
5
|
-
import { IconModule } from '@acpaas-ui/ngx-icon';
|
|
6
|
-
import { SearchFilterComponent } from './components/search-filter/search-filter.component';
|
|
7
|
-
|
|
8
|
-
@NgModule({
|
|
9
|
-
imports: [CommonModule, FlyoutModule, FormsModule, IconModule],
|
|
10
|
-
declarations: [SearchFilterComponent],
|
|
11
|
-
exports: [SearchFilterComponent],
|
|
12
|
-
})
|
|
13
|
-
export class SearchFilterModule {}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { waitForAsync, inject, TestBed } from '@angular/core/testing';
|
|
2
|
-
|
|
3
|
-
import { SearchService } from './search.service';
|
|
4
|
-
|
|
5
|
-
const injectService = (cb) =>
|
|
6
|
-
inject([SearchService], (searchService: SearchService) => cb(searchService));
|
|
7
|
-
|
|
8
|
-
describe('The Search Service', () => {
|
|
9
|
-
let data = [];
|
|
10
|
-
|
|
11
|
-
beforeEach(waitForAsync(() => {
|
|
12
|
-
TestBed.configureTestingModule({
|
|
13
|
-
providers: [SearchService],
|
|
14
|
-
}).compileComponents();
|
|
15
|
-
}));
|
|
16
|
-
|
|
17
|
-
beforeEach(() => {
|
|
18
|
-
data = [
|
|
19
|
-
{ id: 2, name: 'spiderman' },
|
|
20
|
-
{ id: 3, name: 'wolverine' },
|
|
21
|
-
];
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it(
|
|
25
|
-
'should return an all items if no search options were provided',
|
|
26
|
-
injectService((searchService: SearchService) => {
|
|
27
|
-
expect(searchService.search(data)).toEqual(data);
|
|
28
|
-
})
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
it(
|
|
32
|
-
'should return all items when showAllByDefault is true and the query is empty',
|
|
33
|
-
injectService((searchService: SearchService) => {
|
|
34
|
-
expect(
|
|
35
|
-
searchService.search(data, { query: '', showAllByDefault: true })
|
|
36
|
-
).toEqual(data);
|
|
37
|
-
})
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
it(
|
|
41
|
-
'should return all items if the query does not meet the minLength in the options',
|
|
42
|
-
injectService((searchService: SearchService) => {
|
|
43
|
-
expect(searchService.search(data, { minLength: 1, query: '' })).toEqual(
|
|
44
|
-
data
|
|
45
|
-
);
|
|
46
|
-
})
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
it(
|
|
50
|
-
'should match elements for the provided searchstring',
|
|
51
|
-
injectService((searchService: SearchService) => {
|
|
52
|
-
expect(searchService.search(data, { query: 'er', key: 'name' })).toEqual([
|
|
53
|
-
{ id: 2, name: 'spiderman' },
|
|
54
|
-
{ id: 3, name: 'wolverine' },
|
|
55
|
-
]);
|
|
56
|
-
})
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
it(
|
|
60
|
-
'should match elements in a flat array',
|
|
61
|
-
injectService((searchService: SearchService) => {
|
|
62
|
-
expect(
|
|
63
|
-
searchService.search(['one', 'two', 'three'], { query: 't' })
|
|
64
|
-
).toEqual(['two', 'three']);
|
|
65
|
-
})
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
it(
|
|
69
|
-
'should log an error for invalid items',
|
|
70
|
-
injectService((searchService: SearchService) => {
|
|
71
|
-
spyOn(console, 'error');
|
|
72
|
-
|
|
73
|
-
searchService.search(data, { query: 'er', key: 'test' });
|
|
74
|
-
|
|
75
|
-
expect(console.error).toHaveBeenCalled();
|
|
76
|
-
})
|
|
77
|
-
);
|
|
78
|
-
});
|