|
|
|
|
@ -4,14 +4,22 @@ import {
|
|
|
|
|
ChangeDetectorRef,
|
|
|
|
|
Component,
|
|
|
|
|
Input,
|
|
|
|
|
OnChanges,
|
|
|
|
|
Optional,
|
|
|
|
|
SimpleChanges,
|
|
|
|
|
SkipSelf,
|
|
|
|
|
OnChanges,
|
|
|
|
|
} from '@angular/core';
|
|
|
|
|
import { ControlContainer, Validators, ValidatorFn } from '@angular/forms';
|
|
|
|
|
import {
|
|
|
|
|
ControlContainer,
|
|
|
|
|
FormGroup,
|
|
|
|
|
FormGroupDirective,
|
|
|
|
|
ValidatorFn,
|
|
|
|
|
Validators,
|
|
|
|
|
} from '@angular/forms';
|
|
|
|
|
import { NgbDateAdapter, NgbTimeAdapter } from '@ng-bootstrap/ng-bootstrap';
|
|
|
|
|
import { Observable, of } from 'rxjs';
|
|
|
|
|
import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';
|
|
|
|
|
import snq from 'snq';
|
|
|
|
|
import { DateAdapter } from '../../adapters/date.adapter';
|
|
|
|
|
import { TimeAdapter } from '../../adapters/time.adapter';
|
|
|
|
|
import { ePropType } from '../../enums/props.enum';
|
|
|
|
|
@ -38,6 +46,8 @@ export class ExtensibleFormPropComponent implements OnChanges {
|
|
|
|
|
|
|
|
|
|
@Input() prop: FormProp;
|
|
|
|
|
|
|
|
|
|
asterisk = '';
|
|
|
|
|
|
|
|
|
|
options$: Observable<ABP.Option<any>[]> = of([]);
|
|
|
|
|
|
|
|
|
|
validators: ValidatorFn[] = [];
|
|
|
|
|
@ -46,15 +56,55 @@ export class ExtensibleFormPropComponent implements OnChanges {
|
|
|
|
|
|
|
|
|
|
disabled: boolean;
|
|
|
|
|
|
|
|
|
|
constructor(public readonly cdRef: ChangeDetectorRef, public readonly track: TrackByService) {}
|
|
|
|
|
private readonly form: FormGroup;
|
|
|
|
|
|
|
|
|
|
typeaheadModel: any;
|
|
|
|
|
|
|
|
|
|
get asterisk(): string {
|
|
|
|
|
return this.validators.some(validator => validator === Validators.required) ? '*' : '';
|
|
|
|
|
setTypeaheadValue(selectedOption: ABP.Option<string>) {
|
|
|
|
|
this.typeaheadModel = selectedOption || { key: null, value: null };
|
|
|
|
|
const { key, value } = this.typeaheadModel;
|
|
|
|
|
const [keyControl, valueControl] = this.getTypeaheadControls();
|
|
|
|
|
keyControl.setValue(key);
|
|
|
|
|
valueControl.setValue(value);
|
|
|
|
|
valueControl.markAsDirty();
|
|
|
|
|
valueControl.markAsTouched();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getComponent(prop: FormProp): string {
|
|
|
|
|
if (prop.options && prop.type !== ePropType.MultiSelect) return 'select';
|
|
|
|
|
search = (text$: Observable<string>) =>
|
|
|
|
|
text$
|
|
|
|
|
? text$.pipe(
|
|
|
|
|
debounceTime(300),
|
|
|
|
|
distinctUntilChanged(),
|
|
|
|
|
switchMap(text => this.prop.options(this.data, text)),
|
|
|
|
|
)
|
|
|
|
|
: of([]);
|
|
|
|
|
|
|
|
|
|
typeaheadFormatter = (option: ABP.Option<any>) => option.key;
|
|
|
|
|
|
|
|
|
|
get isInvalid() {
|
|
|
|
|
const control = this.form.get(this.prop.name);
|
|
|
|
|
return control.touched && control.invalid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
constructor(
|
|
|
|
|
public readonly cdRef: ChangeDetectorRef,
|
|
|
|
|
public readonly track: TrackByService,
|
|
|
|
|
groupDirective: FormGroupDirective,
|
|
|
|
|
) {
|
|
|
|
|
this.form = groupDirective.form;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private getTypeaheadControls() {
|
|
|
|
|
const { name } = this.prop;
|
|
|
|
|
const { [name + '_Text']: key, [name]: value } = this.form.controls;
|
|
|
|
|
return [key, value];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private setAsterisk() {
|
|
|
|
|
this.asterisk = this.validators.some(v => v === Validators.required) ? '*' : '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getComponent(prop: FormProp): string {
|
|
|
|
|
switch (prop.type) {
|
|
|
|
|
case ePropType.Boolean:
|
|
|
|
|
return 'checkbox';
|
|
|
|
|
@ -62,14 +112,18 @@ export class ExtensibleFormPropComponent implements OnChanges {
|
|
|
|
|
return 'date';
|
|
|
|
|
case ePropType.DateTime:
|
|
|
|
|
return 'dateTime';
|
|
|
|
|
case ePropType.Hidden:
|
|
|
|
|
return 'hidden';
|
|
|
|
|
case ePropType.MultiSelect:
|
|
|
|
|
return 'multiselect';
|
|
|
|
|
case ePropType.Text:
|
|
|
|
|
return 'textarea';
|
|
|
|
|
case ePropType.Time:
|
|
|
|
|
return 'time';
|
|
|
|
|
case ePropType.MultiSelect:
|
|
|
|
|
return 'multiselect';
|
|
|
|
|
case ePropType.Typeahead:
|
|
|
|
|
return 'typeahead';
|
|
|
|
|
default:
|
|
|
|
|
return 'input';
|
|
|
|
|
return prop.options ? 'select' : 'input';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -92,14 +146,15 @@ export class ExtensibleFormPropComponent implements OnChanges {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ngOnChanges({ prop }: SimpleChanges) {
|
|
|
|
|
const options = prop.currentValue.options;
|
|
|
|
|
const readonly = prop.currentValue.readonly;
|
|
|
|
|
const disabled = prop.currentValue.disabled;
|
|
|
|
|
const validators = prop.currentValue.validators;
|
|
|
|
|
const currentProp = snq<FormProp>(() => prop.currentValue);
|
|
|
|
|
const { options, readonly, disabled, validators } = currentProp || {};
|
|
|
|
|
|
|
|
|
|
if (options) this.options$ = options(this.data);
|
|
|
|
|
if (readonly) this.readonly = readonly(this.data);
|
|
|
|
|
if (disabled) this.disabled = disabled(this.data);
|
|
|
|
|
if (validators) this.validators = validators(this.data);
|
|
|
|
|
if (validators) {
|
|
|
|
|
this.validators = validators(this.data);
|
|
|
|
|
this.setAsterisk();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|