@falcon-ng/tailwind 0.0.2
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/README.md +71 -0
- package/ng-package.json +7 -0
- package/package.json +11 -0
- package/src/lib/base-control.ts +142 -0
- package/src/lib/base-form-component.ts +363 -0
- package/src/lib/component/auto-complete/auto-complete.component.html +39 -0
- package/src/lib/component/auto-complete/auto-complete.component.scss +0 -0
- package/src/lib/component/auto-complete/auto-complete.component.spec.ts +23 -0
- package/src/lib/component/auto-complete/auto-complete.component.ts +31 -0
- package/src/lib/component/bottom-sheet/bottom-sheet.component.html +9 -0
- package/src/lib/component/bottom-sheet/bottom-sheet.component.scss +0 -0
- package/src/lib/component/bottom-sheet/bottom-sheet.component.spec.ts +23 -0
- package/src/lib/component/bottom-sheet/bottom-sheet.component.ts +19 -0
- package/src/lib/component/button/button.component.css +0 -0
- package/src/lib/component/button/button.component.html +54 -0
- package/src/lib/component/button/button.component.spec.ts +23 -0
- package/src/lib/component/button/button.component.ts +17 -0
- package/src/lib/component/button-toggle/button-toggle.component.html +21 -0
- package/src/lib/component/button-toggle/button-toggle.component.scss +0 -0
- package/src/lib/component/button-toggle/button-toggle.component.spec.ts +23 -0
- package/src/lib/component/button-toggle/button-toggle.component.ts +26 -0
- package/src/lib/component/checkbox/checkbox.component.html +6 -0
- package/src/lib/component/checkbox/checkbox.component.scss +0 -0
- package/src/lib/component/checkbox/checkbox.component.spec.ts +23 -0
- package/src/lib/component/checkbox/checkbox.component.ts +17 -0
- package/src/lib/component/chips/chip.component.html +75 -0
- package/src/lib/component/chips/chip.component.scss +3 -0
- package/src/lib/component/chips/chip.component.spec.ts +23 -0
- package/src/lib/component/chips/chip.component.ts +125 -0
- package/src/lib/component/date-picker/date-picker.component.html +18 -0
- package/src/lib/component/date-picker/date-picker.component.scss +0 -0
- package/src/lib/component/date-picker/date-picker.component.spec.ts +23 -0
- package/src/lib/component/date-picker/date-picker.component.ts +13 -0
- package/src/lib/component/dialog/dialog.component.html +12 -0
- package/src/lib/component/dialog/dialog.component.scss +3 -0
- package/src/lib/component/dialog/dialog.component.spec.ts +23 -0
- package/src/lib/component/dialog/dialog.component.ts +12 -0
- package/src/lib/component/pagination/pagination.component.html +10 -0
- package/src/lib/component/pagination/pagination.component.scss +0 -0
- package/src/lib/component/pagination/pagination.component.spec.ts +23 -0
- package/src/lib/component/pagination/pagination.component.ts +86 -0
- package/src/lib/component/progress-bar/progress-bar.component.html +1 -0
- package/src/lib/component/progress-bar/progress-bar.component.scss +0 -0
- package/src/lib/component/progress-bar/progress-bar.component.spec.ts +23 -0
- package/src/lib/component/progress-bar/progress-bar.component.ts +15 -0
- package/src/lib/component/progress-spinner/progress-spinner.component.html +7 -0
- package/src/lib/component/progress-spinner/progress-spinner.component.scss +0 -0
- package/src/lib/component/progress-spinner/progress-spinner.component.spec.ts +23 -0
- package/src/lib/component/progress-spinner/progress-spinner.component.ts +16 -0
- package/src/lib/component/radio/radio.component.html +13 -0
- package/src/lib/component/radio/radio.component.scss +14 -0
- package/src/lib/component/radio/radio.component.spec.ts +23 -0
- package/src/lib/component/radio/radio.component.ts +29 -0
- package/src/lib/component/rich-text-editor/rich-text-editor.component.html +10 -0
- package/src/lib/component/rich-text-editor/rich-text-editor.component.scss +0 -0
- package/src/lib/component/rich-text-editor/rich-text-editor.component.spec.ts +23 -0
- package/src/lib/component/rich-text-editor/rich-text-editor.component.ts +13 -0
- package/src/lib/component/select/select.component.html +25 -0
- package/src/lib/component/select/select.component.scss +0 -0
- package/src/lib/component/select/select.component.spec.ts +23 -0
- package/src/lib/component/select/select.component.ts +32 -0
- package/src/lib/component/slide-toggle/slide-toggle.component.html +7 -0
- package/src/lib/component/slide-toggle/slide-toggle.component.scss +0 -0
- package/src/lib/component/slide-toggle/slide-toggle.component.spec.ts +23 -0
- package/src/lib/component/slide-toggle/slide-toggle.component.ts +13 -0
- package/src/lib/component/slider/slider.component.html +11 -0
- package/src/lib/component/slider/slider.component.scss +0 -0
- package/src/lib/component/slider/slider.component.spec.ts +23 -0
- package/src/lib/component/slider/slider.component.ts +13 -0
- package/src/lib/component/snack-bar/snack-bar.component.html +1 -0
- package/src/lib/component/snack-bar/snack-bar.component.scss +0 -0
- package/src/lib/component/snack-bar/snack-bar.component.spec.ts +23 -0
- package/src/lib/component/snack-bar/snack-bar.component.ts +10 -0
- package/src/lib/component/table/table.component.html +82 -0
- package/src/lib/component/table/table.component.scss +17 -0
- package/src/lib/component/table/table.component.spec.ts +23 -0
- package/src/lib/component/table/table.component.ts +54 -0
- package/src/lib/component/textarea/textarea.component.html +22 -0
- package/src/lib/component/textarea/textarea.component.scss +3 -0
- package/src/lib/component/textarea/textarea.component.spec.ts +23 -0
- package/src/lib/component/textarea/textarea.component.ts +13 -0
- package/src/lib/component/textbox/textbox.component.html +27 -0
- package/src/lib/component/textbox/textbox.component.scss +3 -0
- package/src/lib/component/textbox/textbox.component.spec.ts +23 -0
- package/src/lib/component/textbox/textbox.component.ts +13 -0
- package/src/lib/control-builder/control-builder.component.html +5 -0
- package/src/lib/control-builder/control-builder.component.scss +0 -0
- package/src/lib/control-builder/control-builder.component.ts +14 -0
- package/src/lib/control-type/AutoComplete.ts +6 -0
- package/src/lib/control-type/Button.ts +6 -0
- package/src/lib/control-type/ButtonToggle.ts +6 -0
- package/src/lib/control-type/CheckBox.ts +6 -0
- package/src/lib/control-type/Chip.ts +6 -0
- package/src/lib/control-type/DatePicker.ts +6 -0
- package/src/lib/control-type/Divider.ts +6 -0
- package/src/lib/control-type/Editor.ts +6 -0
- package/src/lib/control-type/Radio.ts +6 -0
- package/src/lib/control-type/RichTextEditor.ts +6 -0
- package/src/lib/control-type/SlideToggle.ts +6 -0
- package/src/lib/control-type/Slider.ts +6 -0
- package/src/lib/control-type/select.ts +6 -0
- package/src/lib/control-type/textarea.ts +6 -0
- package/src/lib/control-type/textbox.ts +6 -0
- package/src/lib/falcon-core.module.ts +141 -0
- package/src/lib/model/constant.ts +32 -0
- package/src/lib/model/enum.ts +151 -0
- package/src/lib/model/environments.ts +28 -0
- package/src/lib/model/interface.ts +310 -0
- package/src/lib/model/ivalidator.ts +18 -0
- package/src/lib/module/angularmaterial.module.ts +98 -0
- package/src/lib/reactive-field.directive.ts +24 -0
- package/src/lib/service/appsetting.service.ts +57 -0
- package/src/lib/service/http/generic-http-client.ts +205 -0
- package/src/lib/service/http/httpInterceptor.ts +36 -0
- package/src/lib/service/http/igeneric-http-client.ts +110 -0
- package/src/lib/service/logger.service.ts +75 -0
- package/src/lib/service/open-id/TokenHelperService.ts +76 -0
- package/src/lib/service/open-id/auth-guard.service.ts +25 -0
- package/src/lib/service/open-id/auth.service.ts +179 -0
- package/src/public-api.ts +35 -0
- package/tsconfig.lib.json +15 -0
- package/tsconfig.lib.prod.json +10 -0
- package/tsconfig.spec.json +14 -0
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
## Build
|
|
2
|
+
Run `ng build @falcon-ng/tailwind` to build the project. The build artifacts will be stored in the `dist/` directory.
|
|
3
|
+
|
|
4
|
+
## In Production
|
|
5
|
+
|
|
6
|
+
- Add the dependencies to the project `npm i @falcon-ng/tailwind`
|
|
7
|
+
### Publish to NPM
|
|
8
|
+
- `ng build @falcon-ng/tailwind --configuration=production`
|
|
9
|
+
- `npm login`
|
|
10
|
+
- From the project root folder: `cd dist/@falcon-ng/tailwind`
|
|
11
|
+
- `npm publish --access public` access public is for free version
|
|
12
|
+
### To unplish the package from NPM
|
|
13
|
+
- `npm unpublish @falcon-ng/tailwind@<version>`
|
|
14
|
+
- If publish error or previous version try the below command
|
|
15
|
+
```
|
|
16
|
+
npm unpublish --force @falcon-ng/tailwind@0.0.1
|
|
17
|
+
npm publish --force --access public
|
|
18
|
+
```
|
|
19
|
+
- To update the version of the library, cd into the library project
|
|
20
|
+
```
|
|
21
|
+
npm version <new_Version_No>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## In Development
|
|
25
|
+
|
|
26
|
+
- During development the best way to consume library is using `npm link`
|
|
27
|
+
```
|
|
28
|
+
cd dist/@falcon-ng/tailwind
|
|
29
|
+
npm link
|
|
30
|
+
```
|
|
31
|
+
- We can link an Angular project to this library from anywhere on local machine. From the project root folder:
|
|
32
|
+
```
|
|
33
|
+
npm link @falcon-ng/tailwind
|
|
34
|
+
```
|
|
35
|
+
- If we now build the library with the watch flag `ng build @falcon-ng/tailwind --watch`, and at the same time run `ng serve -o` to another project in another terminal window.
|
|
36
|
+
- This will allow us to develop an application and (one or more) linked libraries simultaneously, and see the app recompile with each modification to the library’s source code.
|
|
37
|
+
- add `preserveSymlinks = true` to the `angular.json` located at the other project
|
|
38
|
+
```
|
|
39
|
+
{
|
|
40
|
+
"architect":
|
|
41
|
+
{
|
|
42
|
+
"build":
|
|
43
|
+
{
|
|
44
|
+
"builder": "@angular-devkit/build-angular:browser",
|
|
45
|
+
"options": {
|
|
46
|
+
"preserveSymlinks": true
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
- Add falcol tailwind module to the project
|
|
53
|
+
```
|
|
54
|
+
import { FalconCoreModule } from '@falcon-ng/tailwind';
|
|
55
|
+
import {environment} from "../environments/environment";
|
|
56
|
+
@NgModule({
|
|
57
|
+
declarations: [],
|
|
58
|
+
imports:[
|
|
59
|
+
FalconCoreModule.forRoot(environment)
|
|
60
|
+
],
|
|
61
|
+
bootstrap: [AppComponent]
|
|
62
|
+
})
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Publish code to GitHub
|
|
66
|
+
|
|
67
|
+
ng build --configuration=production --output-path docs --base-href /<project_name>/
|
|
68
|
+
|
|
69
|
+
Example --> ng build --configuration=production --output-path docs --base-href /Angular-Tailwind-Reusable-Form/
|
|
70
|
+
|
|
71
|
+
- Reference - https://angular.io/guide/deployment
|
package/ng-package.json
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import {ControlType} from './model/enum';
|
|
2
|
+
import {IValidator} from './model/ivalidator';
|
|
3
|
+
import {
|
|
4
|
+
FloatLabelType,
|
|
5
|
+
MatFormFieldAppearance,
|
|
6
|
+
} from '@angular/material/form-field';
|
|
7
|
+
import {
|
|
8
|
+
IComponentEvent,
|
|
9
|
+
IMatHint,
|
|
10
|
+
IOptions,
|
|
11
|
+
ISelectOptions, ISliderProperty,
|
|
12
|
+
ISuffixPrefixConfig,
|
|
13
|
+
ITextAreaProperty,
|
|
14
|
+
} from './model/interface';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @description
|
|
18
|
+
* Class use for setting the layout.
|
|
19
|
+
* @usageNotes
|
|
20
|
+
* ```ts
|
|
21
|
+
* new Dropdown({
|
|
22
|
+
* key: 'brave',
|
|
23
|
+
* label: 'Bravery Rating',
|
|
24
|
+
* options: [
|
|
25
|
+
* {key: 'solid', value: 'Solid'},
|
|
26
|
+
* {key: 'great', value: 'Great'},
|
|
27
|
+
* {key: 'good', value: 'Good'},
|
|
28
|
+
* {key: 'unproven', value: 'Unproven'}
|
|
29
|
+
* ],
|
|
30
|
+
* order: 3
|
|
31
|
+
* }),
|
|
32
|
+
** ```
|
|
33
|
+
*/
|
|
34
|
+
export interface Layout<T> {
|
|
35
|
+
class?: string;
|
|
36
|
+
baseControls: BaseControl<T>[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @description
|
|
41
|
+
* Class use for setting the control properties.
|
|
42
|
+
* @usageNotes
|
|
43
|
+
* ```ts
|
|
44
|
+
* new Dropdown({
|
|
45
|
+
* formControlName: 'brave',
|
|
46
|
+
* label: 'Bravery Rating',
|
|
47
|
+
* options: [
|
|
48
|
+
* {key: 'solid', value: 'Solid'},
|
|
49
|
+
* {key: 'great', value: 'Great'},
|
|
50
|
+
* {key: 'good', value: 'Good'},
|
|
51
|
+
* {key: 'unproven', value: 'Unproven'}
|
|
52
|
+
* ],
|
|
53
|
+
* order: 3
|
|
54
|
+
* }),
|
|
55
|
+
** ```
|
|
56
|
+
*/
|
|
57
|
+
export class BaseControl<T> {
|
|
58
|
+
value: T | undefined;
|
|
59
|
+
formControlName: string;
|
|
60
|
+
label: string;
|
|
61
|
+
labelPosition: any;
|
|
62
|
+
order: number;
|
|
63
|
+
controlType: ControlType;
|
|
64
|
+
type: string;
|
|
65
|
+
disabled: boolean;
|
|
66
|
+
options: IOptions[] | any;
|
|
67
|
+
validations: IValidator[];
|
|
68
|
+
appearance: MatFormFieldAppearance | any;
|
|
69
|
+
class: string;
|
|
70
|
+
style: { [klass: string]: any };
|
|
71
|
+
placeHolder: string;
|
|
72
|
+
floatLabel: FloatLabelType;
|
|
73
|
+
hint: IMatHint;
|
|
74
|
+
suffix: ISuffixPrefixConfig;
|
|
75
|
+
prefix: ISuffixPrefixConfig;
|
|
76
|
+
textAreaProperty: ITextAreaProperty;
|
|
77
|
+
event: IComponentEvent<T>;
|
|
78
|
+
selectProperty: ISelectOptions;
|
|
79
|
+
color: string;
|
|
80
|
+
sliderProperty: ISliderProperty;
|
|
81
|
+
chipSelectedOptions: IOptions[] | any;
|
|
82
|
+
editorProperty: any;
|
|
83
|
+
formArray: BaseControl<T>[] | undefined;
|
|
84
|
+
constructor(
|
|
85
|
+
options: {
|
|
86
|
+
value?: T;
|
|
87
|
+
formControlName?: string;
|
|
88
|
+
label?: string;
|
|
89
|
+
labelPosition?: any;
|
|
90
|
+
order?: number;
|
|
91
|
+
controlType?: ControlType;
|
|
92
|
+
type?: string;
|
|
93
|
+
disabled?: boolean;
|
|
94
|
+
options?: IOptions[] | any;
|
|
95
|
+
validations?: IValidator[];
|
|
96
|
+
appearance?: MatFormFieldAppearance | any;
|
|
97
|
+
class?: string;
|
|
98
|
+
style?: { [klass: string]: any };
|
|
99
|
+
placeHolder?: string;
|
|
100
|
+
floatLabel?: FloatLabelType;
|
|
101
|
+
hint?: IMatHint;
|
|
102
|
+
suffix?: ISuffixPrefixConfig;
|
|
103
|
+
prefix?: ISuffixPrefixConfig;
|
|
104
|
+
textAreaProperty?: ITextAreaProperty;
|
|
105
|
+
event?: IComponentEvent<T>;
|
|
106
|
+
selectProperty?: ISelectOptions;
|
|
107
|
+
color?: string;
|
|
108
|
+
sliderProperty?: ISliderProperty;
|
|
109
|
+
chipSelectedOptions?: IOptions[] | any;
|
|
110
|
+
editorProperty?: any;
|
|
111
|
+
formArray?: BaseControl<T>[];
|
|
112
|
+
} = {}
|
|
113
|
+
) {
|
|
114
|
+
this.value = options.value;
|
|
115
|
+
this.formControlName = options.formControlName || '';
|
|
116
|
+
this.label = options.label || '';
|
|
117
|
+
this.labelPosition = options.labelPosition || 'before' || 'after';
|
|
118
|
+
this.order = options.order === undefined ? 1 : options.order;
|
|
119
|
+
this.controlType = options.controlType || ControlType.Button;
|
|
120
|
+
this.type = options.type || '';
|
|
121
|
+
this.disabled = options.disabled || false;
|
|
122
|
+
this.options = options.options || [];
|
|
123
|
+
this.validations = options.validations || [];
|
|
124
|
+
this.appearance = options.appearance || 'outline';
|
|
125
|
+
this.class = options.class || '';
|
|
126
|
+
this.style = options.style || {};
|
|
127
|
+
this.placeHolder = options.placeHolder || '';
|
|
128
|
+
this.floatLabel = options.floatLabel || 'auto';
|
|
129
|
+
this.hint = options.hint || ({} as IMatHint);
|
|
130
|
+
this.prefix = options.prefix || ({} as ISuffixPrefixConfig);
|
|
131
|
+
this.suffix = options.suffix || ({} as ISuffixPrefixConfig);
|
|
132
|
+
this.textAreaProperty =
|
|
133
|
+
options.textAreaProperty || ({} as ITextAreaProperty);
|
|
134
|
+
this.event = options.event || {};
|
|
135
|
+
this.selectProperty = options.selectProperty || {};
|
|
136
|
+
this.color = options.color || '';
|
|
137
|
+
this.sliderProperty = options.sliderProperty || {};
|
|
138
|
+
this.chipSelectedOptions = options.chipSelectedOptions || {};
|
|
139
|
+
this.editorProperty = options.editorProperty || {};
|
|
140
|
+
this.formArray = options.formArray || undefined
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import {Observable} from 'rxjs';
|
|
2
|
+
import {
|
|
3
|
+
FormBuilder,
|
|
4
|
+
FormControl,
|
|
5
|
+
FormGroup,
|
|
6
|
+
ValidatorFn,
|
|
7
|
+
Validators,
|
|
8
|
+
} from '@angular/forms';
|
|
9
|
+
import {BaseControl, Layout} from './base-control';
|
|
10
|
+
import {inject} from '@angular/core';
|
|
11
|
+
import {IValidator} from './model/ivalidator';
|
|
12
|
+
import {ControlType} from './model/enum';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @description
|
|
16
|
+
* Base form component initialized to create form controls, set validation, submit.
|
|
17
|
+
*
|
|
18
|
+
* @usageNotes
|
|
19
|
+
* The following snippet shows how a component can implement this abstract class to
|
|
20
|
+
* define its own initialization method.
|
|
21
|
+
* ```ts
|
|
22
|
+
* export class InputComponent extends BaseFormComponent<any> implements OnInit {
|
|
23
|
+
* constructor(fb : FormBuilder) {
|
|
24
|
+
* super(fb);
|
|
25
|
+
* this.defineForm();
|
|
26
|
+
* }
|
|
27
|
+
* protected defineForm(): void {
|
|
28
|
+
* }
|
|
29
|
+
* ngOnInit(): void {
|
|
30
|
+
* this.formGroup = this.createControls();
|
|
31
|
+
* }
|
|
32
|
+
* protected submitDatasource(model: any): Observable<any> {
|
|
33
|
+
* return of(model);
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export abstract class BaseFormComponent<T> {
|
|
38
|
+
public formGroup!: FormGroup;
|
|
39
|
+
|
|
40
|
+
protected abstract defineForm(): void;
|
|
41
|
+
|
|
42
|
+
protected abstract submitDataSource(model: T): Observable<T>;
|
|
43
|
+
|
|
44
|
+
public dataSource: T | undefined = undefined;
|
|
45
|
+
public controlsConfig!: Layout<T>;
|
|
46
|
+
public showLoading: boolean = false;
|
|
47
|
+
protected fb = inject(FormBuilder);
|
|
48
|
+
|
|
49
|
+
constructor() {
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @description
|
|
54
|
+
* Method evoke on when the form is submitted.
|
|
55
|
+
* @returns submitDatasource() method with form data if valid otherwise form invalid.
|
|
56
|
+
*/
|
|
57
|
+
public onSubmit() {
|
|
58
|
+
if (this.formGroup !== undefined && this.formGroup.valid) {
|
|
59
|
+
this.submitDataSource(this.formGroup.value);
|
|
60
|
+
} else {
|
|
61
|
+
this.validateAllFormFields(this.formGroup);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @description
|
|
67
|
+
* Private method to validate all form controls before is form submited.
|
|
68
|
+
* @param formGroup Validate form group.
|
|
69
|
+
* @returns Groups of controls added to the form builder.
|
|
70
|
+
*/
|
|
71
|
+
private validateAllFormFields(formGroup: FormGroup) {
|
|
72
|
+
if (this.formGroup !== undefined) this.formGroup.markAllAsTouched();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @description
|
|
77
|
+
* Create the reactive form controls
|
|
78
|
+
* @returns Groups of controls added to the form builder.
|
|
79
|
+
*/
|
|
80
|
+
protected createControls() {
|
|
81
|
+
const group = this.fb.group({});
|
|
82
|
+
this.controlsConfig.baseControls.forEach((controls, index) => {
|
|
83
|
+
this.bindControl(controls, group, index);
|
|
84
|
+
});
|
|
85
|
+
return group;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @description
|
|
90
|
+
* Private method to bind the form control.
|
|
91
|
+
* @param controlConfig field to bind.
|
|
92
|
+
* @param group group to add.
|
|
93
|
+
* @param index index of the layout
|
|
94
|
+
*/
|
|
95
|
+
private bindControl(
|
|
96
|
+
controlConfig: BaseControl<T>,
|
|
97
|
+
group: FormGroup,
|
|
98
|
+
index: number
|
|
99
|
+
) {
|
|
100
|
+
if (controlConfig.controlType === ControlType.Button) return;
|
|
101
|
+
let control = null;
|
|
102
|
+
if (controlConfig.formArray !== undefined) {
|
|
103
|
+
control =
|
|
104
|
+
controlConfig.formArray.length > 0
|
|
105
|
+
? this.fb.array([
|
|
106
|
+
this.createFormArrayGroup(
|
|
107
|
+
controlConfig.formArray[
|
|
108
|
+
controlConfig.formArray.length - 1
|
|
109
|
+
].formArray,
|
|
110
|
+
),
|
|
111
|
+
])
|
|
112
|
+
: this.fb.array(
|
|
113
|
+
[],
|
|
114
|
+
this.bindValidations(controlConfig.validations || []),
|
|
115
|
+
);
|
|
116
|
+
} else {
|
|
117
|
+
control = this.fb.control(
|
|
118
|
+
{
|
|
119
|
+
value: controlConfig.value,
|
|
120
|
+
disabled: controlConfig.disabled,
|
|
121
|
+
},
|
|
122
|
+
this.bindValidations(controlConfig.validations || [])
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
group.addControl(controlConfig.formControlName, control);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @description
|
|
130
|
+
* Private method to bind the validation to the form controls on form submit.
|
|
131
|
+
* @param validations Push the validation to the controls.
|
|
132
|
+
* @returns Validation.
|
|
133
|
+
*/
|
|
134
|
+
private bindValidations(validations: IValidator[]) {
|
|
135
|
+
if (validations.length > 0) {
|
|
136
|
+
const validList: (ValidatorFn | null | undefined)[] = [];
|
|
137
|
+
validations.forEach((valid: IValidator) => {
|
|
138
|
+
validList.push(valid.validator);
|
|
139
|
+
});
|
|
140
|
+
return Validators.compose(validList);
|
|
141
|
+
}
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Create an form array element
|
|
147
|
+
* @param layoutConfig layout of form array
|
|
148
|
+
* @returns Form array group
|
|
149
|
+
*/
|
|
150
|
+
private createFormArrayGroup(componentConfig: BaseControl<T>[] | undefined): FormGroup {
|
|
151
|
+
var formGroup: FormGroup = this.fb.group({});
|
|
152
|
+
componentConfig?.forEach((item, index) => {
|
|
153
|
+
var control = null;
|
|
154
|
+
if (item.formArray !== undefined) {
|
|
155
|
+
control =
|
|
156
|
+
item.formArray.length > 0
|
|
157
|
+
? this.fb.array(
|
|
158
|
+
[
|
|
159
|
+
this.createFormArrayGroup(
|
|
160
|
+
item.formArray[item.formArray.length - 1].formArray,
|
|
161
|
+
),
|
|
162
|
+
],
|
|
163
|
+
this.bindValidations(item.validations || []),
|
|
164
|
+
)
|
|
165
|
+
: this.fb.array(
|
|
166
|
+
[],
|
|
167
|
+
this.bindValidations(item.validations || []),
|
|
168
|
+
);
|
|
169
|
+
} else {
|
|
170
|
+
control = this.fb.control(
|
|
171
|
+
{
|
|
172
|
+
value: item.value,
|
|
173
|
+
disabled: item.disabled,
|
|
174
|
+
},
|
|
175
|
+
this.bindValidations(item.validations || []),
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
formGroup.addControl(item.formControlName, control);
|
|
179
|
+
});
|
|
180
|
+
return formGroup;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* @description
|
|
185
|
+
* Reset fild values to default or specify some value.
|
|
186
|
+
* @param defaultValues Specify the specific value to set to the controls.
|
|
187
|
+
* @returns void.
|
|
188
|
+
*/
|
|
189
|
+
public reset(defaultValues?: any): void {
|
|
190
|
+
this.formGroup.reset(defaultValues);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* @description
|
|
195
|
+
* Reset specific fild Errors.
|
|
196
|
+
* @param name Name of the field to reset the error.
|
|
197
|
+
* @returns void.
|
|
198
|
+
*/
|
|
199
|
+
resetFieldErrors(name: string): void {
|
|
200
|
+
this.formGroup?.get(name)?.setErrors(null);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* @description
|
|
205
|
+
* Get the controls value from the form.
|
|
206
|
+
* @returns Form controls values.
|
|
207
|
+
*/
|
|
208
|
+
get value(): any {
|
|
209
|
+
return this.formGroup.value;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* @description
|
|
214
|
+
* Updating parts of the data model.
|
|
215
|
+
* Use the patchValue() method to replace any properties defined in the object that have changed in the form model.
|
|
216
|
+
* @returns Form controls values.
|
|
217
|
+
* @param value The object that matches the structure of the group.
|
|
218
|
+
* @param options Configuration options that determine how the control propagates changes and
|
|
219
|
+
* emits events after the value is patched.
|
|
220
|
+
* `onlySelf`: When true, each change only affects this control and not its parent. Default is
|
|
221
|
+
* true.
|
|
222
|
+
* `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
|
|
223
|
+
* `valueChanges`
|
|
224
|
+
* @usageNotes
|
|
225
|
+
* The following snippet shows how a component can implement this abstract class to
|
|
226
|
+
* define its own initialization method.
|
|
227
|
+
* ```ts
|
|
228
|
+
* this.formGroup.patchValue({
|
|
229
|
+
* name: 'Todd Motto',
|
|
230
|
+
* event: {
|
|
231
|
+
* title: 'AngularCamp 2016',
|
|
232
|
+
* location: 'Barcelona, Spain'
|
|
233
|
+
* }
|
|
234
|
+
* });
|
|
235
|
+
* ```
|
|
236
|
+
*/
|
|
237
|
+
protected patchValue(
|
|
238
|
+
value: { [key: string]: any },
|
|
239
|
+
options?: { onlySelf?: boolean; emitEvent?: boolean }
|
|
240
|
+
) {
|
|
241
|
+
return this.formGroup.patchValue(value, options);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* @description
|
|
246
|
+
* Updating parts of the data model.
|
|
247
|
+
* Use the setValue() method to set a new value for an individual control. The setValue() method strictly adheres to the structure of the form group and replaces the entire value for the control.
|
|
248
|
+
* @returns Form controls values.
|
|
249
|
+
* @param value The object that matches the structure of the group.
|
|
250
|
+
* @param options Configuration options that determine how the control propagates changes and
|
|
251
|
+
* emits events after the value is patched.
|
|
252
|
+
* `onlySelf`: When true, each change only affects this control and not its parent. Default is
|
|
253
|
+
* true.
|
|
254
|
+
* `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
|
|
255
|
+
* `valueChanges`
|
|
256
|
+
* @usageNotes
|
|
257
|
+
* The following snippet shows how a component can implement this abstract class to
|
|
258
|
+
* define its own initialization method.
|
|
259
|
+
* ```ts
|
|
260
|
+
* this.formGroup.setValue({
|
|
261
|
+
* name: 'Todd Motto',
|
|
262
|
+
* event: {
|
|
263
|
+
* title: 'AngularCamp 2016',
|
|
264
|
+
* location: 'Barcelona, Spain'
|
|
265
|
+
* }
|
|
266
|
+
* });
|
|
267
|
+
* ```
|
|
268
|
+
*/
|
|
269
|
+
protected setValue(
|
|
270
|
+
value: { [key: string]: any },
|
|
271
|
+
options?: { onlySelf?: boolean; emitEvent?: boolean }
|
|
272
|
+
) {
|
|
273
|
+
return this.formGroup.setValue(value, options);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* @description
|
|
278
|
+
* Dynamically remove the form control.
|
|
279
|
+
* @param index Index of item.
|
|
280
|
+
* @usageNotes
|
|
281
|
+
* The following snippet shows how to remove the form control from Froup Group
|
|
282
|
+
* ```ts
|
|
283
|
+
* removeControl(1);
|
|
284
|
+
* ```
|
|
285
|
+
*/
|
|
286
|
+
protected removeControl(layoutIndex: number, index: number) {
|
|
287
|
+
this.formGroup.removeControl(
|
|
288
|
+
this.controlsConfig.baseControls[layoutIndex].formControlName
|
|
289
|
+
);
|
|
290
|
+
this.controlsConfig.baseControls.splice(index, 1);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* @description
|
|
295
|
+
* Dynamically add the form control.
|
|
296
|
+
* @param configToAdd Configuration of the form control.
|
|
297
|
+
* @param index Add controls to the specific index.
|
|
298
|
+
* @usageNotes
|
|
299
|
+
* The following snippet shows how a component can implement this abstract class to
|
|
300
|
+
* define its own initialization method.
|
|
301
|
+
* ```ts
|
|
302
|
+
* var configToadd = {
|
|
303
|
+
* componentProperty: {
|
|
304
|
+
* label: "Outline Auto complete",
|
|
305
|
+
* options: [{ value: 'Extra-cheese', viewValue: 'Extra cheese' },
|
|
306
|
+
* { value: 'Bellsprout', viewValue: 'Bellsprout' },
|
|
307
|
+
* { value: 'Mushroom', viewValue: 'Mushroom' },
|
|
308
|
+
* { value: 'Onion', viewValue: 'Onion' },
|
|
309
|
+
* { value: 'Pepperoni', viewValue: 'Pepperoni' },
|
|
310
|
+
* { value: 'Sausage', viewValue: 'Sausage' },
|
|
311
|
+
* { value: 'Tomato', viewValue: 'Tomato' }],
|
|
312
|
+
* appearance: Appearance.Outline,
|
|
313
|
+
* color: 'accent'
|
|
314
|
+
* },
|
|
315
|
+
* componentType: ComponentType.AutoComplete,
|
|
316
|
+
* formControlName: "test"
|
|
317
|
+
* };
|
|
318
|
+
* this.addControl(configToadd); or this.addControl(configToadd,1);
|
|
319
|
+
* ```
|
|
320
|
+
*/
|
|
321
|
+
// protected addControl(layoutToAdd?: BaseControl<string>[],index?: number) {
|
|
322
|
+
// layoutToAdd.forEach((layout, layoutIndex) => {
|
|
323
|
+
// layout.componentConfig.forEach(
|
|
324
|
+
// (componentConfig, componentIndex) => {
|
|
325
|
+
// if (componentConfig.formArray !== undefined) {
|
|
326
|
+
// componentConfig.formArray.forEach((control) => {
|
|
327
|
+
// this.formGroup.setControl(
|
|
328
|
+
// 'productOption',
|
|
329
|
+
// this.createFormArrayGroup(control.componentConfig),
|
|
330
|
+
// );
|
|
331
|
+
// this.controlsConfig.container.layoutConfig[1].componentConfig[0].formArray.push(
|
|
332
|
+
// layout,
|
|
333
|
+
// );
|
|
334
|
+
// });
|
|
335
|
+
// } else {
|
|
336
|
+
// this.formGroup.addControl(
|
|
337
|
+
// componentConfig.formControlName,
|
|
338
|
+
// new UntypedFormControl(
|
|
339
|
+
// {
|
|
340
|
+
// value: componentConfig.componentProperty.value,
|
|
341
|
+
// disabled:
|
|
342
|
+
// componentConfig.componentProperty.disabled,
|
|
343
|
+
// },
|
|
344
|
+
// this.bindValidations(
|
|
345
|
+
// componentConfig.validations || [],
|
|
346
|
+
// ),
|
|
347
|
+
// ),
|
|
348
|
+
// );
|
|
349
|
+
// index !== null
|
|
350
|
+
// ? this.controlsConfig.container.layoutConfig.splice(
|
|
351
|
+
// index,
|
|
352
|
+
// 0,
|
|
353
|
+
// layout,
|
|
354
|
+
// )
|
|
355
|
+
// : this.controlsConfig.container.layoutConfig.push(
|
|
356
|
+
// layout,
|
|
357
|
+
// );
|
|
358
|
+
// }
|
|
359
|
+
// },
|
|
360
|
+
// );
|
|
361
|
+
// });
|
|
362
|
+
// }
|
|
363
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<mat-form-field *ngIf="control.appearance != 'plain'; else plainInput" [appearance]="control.appearance"
|
|
2
|
+
[formGroup]="formGroup" [ngStyle]="control.style" [ngClass]="control.class">
|
|
3
|
+
<mat-label>{{control.label}}</mat-label>
|
|
4
|
+
<input matInput [formControl]="autoCompleteControl" [formControlName]="control.formControlName"
|
|
5
|
+
[placeholder]="control.placeHolder" [type]="control.type" [ngStyle]="control.style" [ngClass]="control.class"
|
|
6
|
+
[matAutocomplete]="auto"
|
|
7
|
+
[required]="formGroup.get(control.formControlName)?.errors !== null && formGroup.get(control.formControlName)?.errors?.['required']">
|
|
8
|
+
<mat-autocomplete #auto="matAutocomplete" (optionSelected)='optionSelected($event.option.viewValue)'>
|
|
9
|
+
<mat-option *ngFor="let item of filteredOptions | async" [value]="item.key">
|
|
10
|
+
{{item.value}}
|
|
11
|
+
</mat-option>
|
|
12
|
+
</mat-autocomplete>
|
|
13
|
+
|
|
14
|
+
<span matPrefix [matTooltip]="control.prefix.toolTipText!"
|
|
15
|
+
[ngClass]="{'material-icons': control.prefix.isIcon}">{{control.prefix.text}} </span>
|
|
16
|
+
<span matSuffix [matTooltip]="control.suffix.toolTipText!"
|
|
17
|
+
[ngClass]="{'material-icons': control.suffix.isIcon}">{{control.suffix.text}} </span>
|
|
18
|
+
|
|
19
|
+
<mat-hint>{{control.hint.text}}</mat-hint>
|
|
20
|
+
<ng-container *ngFor="let validation of control.validations;" ngProjectAs="mat-error">
|
|
21
|
+
<mat-error *ngIf="formGroup.get(control.formControlName)?.hasError(validation.name)">{{validation.message}}
|
|
22
|
+
</mat-error>
|
|
23
|
+
</ng-container>
|
|
24
|
+
</mat-form-field>
|
|
25
|
+
|
|
26
|
+
<ng-template #plainInput>
|
|
27
|
+
<div [formGroup]="formGroup" [ngStyle]="control.style" [ngClass]="control.class">
|
|
28
|
+
<input type="text" [formControl]="autoCompleteControl" [formControlName]="control.formControlName"
|
|
29
|
+
[placeholder]="control.placeHolder" [type]="control.type" [ngStyle]="control.style" [ngClass]="control.class"
|
|
30
|
+
[matAutocomplete]="auto"
|
|
31
|
+
[required]="formGroup.get(control.formControlName)?.errors !== null && formGroup.get(control.formControlName)?.errors?.['required']"
|
|
32
|
+
class="bg-gray-200 appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-purple-500">
|
|
33
|
+
</div>
|
|
34
|
+
<mat-autocomplete #auto="matAutocomplete" (optionSelected)='optionSelected($event.option.viewValue)'>
|
|
35
|
+
<mat-option *ngFor="let item of filteredOptions | async" [value]="item.key">
|
|
36
|
+
{{item.value}}
|
|
37
|
+
</mat-option>
|
|
38
|
+
</mat-autocomplete>
|
|
39
|
+
</ng-template>
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
|
|
3
|
+
import { AutoCompleteComponent } from './auto-complete.component';
|
|
4
|
+
|
|
5
|
+
describe('AutoCompleteComponent', () => {
|
|
6
|
+
let component: AutoCompleteComponent;
|
|
7
|
+
let fixture: ComponentFixture<AutoCompleteComponent>;
|
|
8
|
+
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
await TestBed.configureTestingModule({
|
|
11
|
+
declarations: [ AutoCompleteComponent ]
|
|
12
|
+
})
|
|
13
|
+
.compileComponents();
|
|
14
|
+
|
|
15
|
+
fixture = TestBed.createComponent(AutoCompleteComponent);
|
|
16
|
+
component = fixture.componentInstance;
|
|
17
|
+
fixture.detectChanges();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should create', () => {
|
|
21
|
+
expect(component).toBeTruthy();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Component, OnInit, Input } from '@angular/core';
|
|
2
|
+
import {BaseControl} from "../../base-control";
|
|
3
|
+
import {FormControl, FormGroup} from "@angular/forms";
|
|
4
|
+
import {IOptions} from "../../model/interface";
|
|
5
|
+
import {Observable} from "rxjs";
|
|
6
|
+
import { map, startWith } from 'rxjs/operators';
|
|
7
|
+
@Component({
|
|
8
|
+
selector: 'falcon-auto-complete',
|
|
9
|
+
templateUrl: './auto-complete.component.html',
|
|
10
|
+
styleUrls: ['./auto-complete.component.scss'],
|
|
11
|
+
})
|
|
12
|
+
export class AutoCompleteComponent {
|
|
13
|
+
control!: BaseControl<string>;
|
|
14
|
+
formGroup!: FormGroup;
|
|
15
|
+
autoCompleteControl = new FormControl();
|
|
16
|
+
constructor() { }
|
|
17
|
+
filteredOptions!: Observable<IOptions[]>;
|
|
18
|
+
|
|
19
|
+
ngOnInit() {
|
|
20
|
+
this.filteredOptions = this.autoCompleteControl.valueChanges.pipe(startWith(''),map(value => this._filter(value)));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private _filter(value: string): IOptions[] {
|
|
24
|
+
const filterValue = value.toLowerCase();
|
|
25
|
+
return this.control.options.filter((option: IOptions) => option?.key?.toLowerCase().includes(filterValue));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
optionSelected(value: any) {
|
|
29
|
+
this.formGroup?.get(this.control?.formControlName)?.setValue(value);
|
|
30
|
+
}
|
|
31
|
+
}
|