UNPKG

@bi8/am-dyn-form

Version:

ng update @angular/cli yarn add @angular/cli

1,241 lines 52.5 kB
import { __decorate, __metadata, __param } from 'tslib';
import { Injectable, Optional, Host, SkipSelf, ElementRef, Input, ViewChild, Component, forwardRef, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormGroup, FormArray, FormControl, Validators, ControlContainer, NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteModule, MatCardModule, MatButtonModule, MatCheckboxModule, MatDatepickerModule, MatNativeDateModule, MatTooltipModule, MatInputModule, MatSelectModule, MatOptionModule, MatDialogModule, MatToolbarModule, MatIconModule, MatSidenavModule, MatMenuModule, MatTableModule, MatListModule } from '@angular/material';
import { tap, filter, debounceTime, distinctUntilChanged, map, takeWhile } from 'rxjs/operators';
import { pipeFromArray } from 'rxjs/internal/util/pipe';
import { NgSelectComponent, NgSelectModule } from '@ng-select/ng-select';
import { Subject, of, ReplaySubject, BehaviorSubject, Observable } from 'rxjs';
import { EventType } from '@bi8/am-io';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { FlexLayoutModule } from '@angular/flex-layout';
import { get, isNil, isObject, chunk } from 'lodash';
import * as moment_ from 'moment';
import { of as of$1 } from 'rxjs/internal/observable/of';

let DynFormService = class DynFormService {
    constructor() {
    }
};
DynFormService = __decorate([
    Injectable(),
    __metadata("design:paramtypes", [])
], DynFormService);

class DynFormGroup extends FormGroup {
    constructor(options = {}, controls) {
        super(controls);
        this.config = {};
        if (options) {
            this.key = options.key || '';
            this.dir = options.dir || '';
        }
    }
    addSlaveObserver(master, slave, options) {
        let masterField = this.get(master);
        let slaveField = this.get(slave);
        if (!options) {
            options = { disable: true, reset: true, apply: true };
        }
        else {
            if (options.reset === undefined) {
                options.reset = true;
            }
            if (options.disable === undefined) {
                options.disable = true;
            }
            if (options.apply === undefined) {
                options.apply = options.disable;
            }
        }
        let ops = [];
        if (options.reset) {
            ops.push(tap(() => slaveField.reset()));
        }
        if (options.disable) {
            ops.push(tap(() => slaveField.disable()));
            if (options.apply) {
                slaveField.disable({ onlySelf: true });
            }
        }
        ops.push(filter((value) => {
            if (!value) {
                return false;
            }
            else {
                return value instanceof Array ? value.length > 0 : true;
            }
        }));
        if (options.disable) {
            ops.push(tap(() => slaveField.enable()));
        }
        if (options.ops) {
            ops.push(...options.ops);
        }
        return masterField.valueChanges.pipe(pipeFromArray([...ops]));
    }
}

class DynFormArray extends FormArray {
    constructor(options = {}, controls) {
        super(controls);
        this.config = {};
        if (options) {
            this.key = options.key || '';
            this.dir = options.dir || '';
        }
    }
    add(values) {
    }
}

class DynFormControl extends FormControl {
    constructor(options = {}, validator, asyncValidator) {
        super(options.defaultValue != undefined ? options.defaultValue : null, validator, asyncValidator);
        this.config = {};
        this.key = options.key || '';
        if (options) {
            this.config.required = options.required != undefined ? options.required : false;
            this.config.hint = options.hint;
            this.config.placeholder = options.placeholder;
            this.config.dir = options.dir || 'ltr';
            this.config.messages = options.messages || [];
            this.config.useDefaultErrorMessages = options.useDefaultErrorMessages || false;
            this.config.loadFn = options.loadFn || null;
            this.config.disable = options.disable || false;
            this.config.appearance = options.appearance || 'standard';
            this.config.compact = options.compact === undefined ? true : options.compact;
            if (this.config.loadFn) {
                this.loadValue(options.defaultValue, this.config.loadFn, { onlySelf: true });
            }
            if (this.config.disable) {
                this.disable({ onlySelf: true });
            }
            if (validator) {
                if (validator instanceof Array) {
                    for (let v of validator) {
                        if (v == Validators.required) {
                            this.config.required = true;
                            break;
                        }
                    }
                }
                else if (validator == Validators.required) {
                    this.config.required = true;
                }
            }
        }
    }
    removeRequired() {
        this.config.required = false;
        this.removeValidator(Validators.required);
        this.updateValueAndValidity();
    }
    addRequired() {
        this.config.required = true;
        this.setValidator(Validators.required);
        this.updateValueAndValidity();
    }
    isRequired() {
        return this.isValidator(Validators.required);
    }
    isValidator(validator) {
        if (!this.validator) {
            return false;
        }
        if (this.validator instanceof Array) {
            return this.validator.find(v => v == validator) != undefined;
        }
        else {
            return this.validator = validator;
        }
    }
    setValidator(validator) {
        if (!this.isValidator(validator)) {
            if (this.validator instanceof Array) {
                return this.validator.push(validator);
            }
            else {
                return this.validator = validator;
            }
        }
    }
    removeValidator(validator) {
        if (this.isValidator(validator)) {
            if (this.validator instanceof Array) {
                this.setValidators(this.validator.filter(v => v != validator));
            }
            else {
                this.setValidators([]);
            }
        }
    }
    setLogicalError(message) {
        this.logicalErrorMessage = message;
        this.markAsTouched();
        let errors = this.errors;
        if (!errors) {
            errors = {};
        }
        errors.logical = true;
        this.setErrors(errors);
    }
    clearLogicalError() {
        this.logicalErrorMessage = null;
        if (this.errors) {
            this.errors.logical = false;
            this.setErrors(this.errors);
        }
    }
    activateValidators() {
    }
    setValue(value, options) {
        if (options && options.loadFn) {
            options.loadFn(value).subscribe((result) => {
                super.setValue(result, options);
            });
        }
        else {
            if (value == null) {
                super.setValue('', options);
            }
            else {
                super.setValue(value, options);
            }
        }
    }
    loadValue(param, loadFn, options) {
        loadFn(param).subscribe((result) => {
            super.setValue(result, options);
        });
    }
}

class DynAutoSelectControl extends DynFormControl {
    constructor(options = {}, validator, asyncValidator) {
        super(options, validator, asyncValidator);
        this.type = 'autoselect';
        this.hasValue = false;
        this.loading = false;
        this.multiple = false;
        this.searchable = true;
        this.clearToggle = false;
        this.showNone = options['showNone'] || false;
        this.noneLabel = options['noneLabel'];
        this.multiple = options['multiple'] || false;
        this.debounce = options['debounce'] || 500;
        this.searchable = options['searchable'] || false;
        let debounceOp = debounceTime(200);
        let showTappet = tap(() => this.loading = true);
        let hideTappet = tap(() => this.loading = false);
        if (options['bindLabel']) {
            this.bindLabel = options['bindLabel'];
        }
        else {
            this.bindLabel = 'name';
        }
        if (options['bindValue']) {
            this.bindValue = options['bindValue'];
        }
        this.labelTemplate = options['labelTemplate'];
        this.optionTemplate = options['optionTemplate'];
        if (options['channel']) {
            this.channel = options['channel'];
            this.channel.asEventObservable().subscribe((event) => {
                switch (event.observeType) {
                    case EventType.on_next:
                        this.loading = true;
                        break;
                    default:
                        this.loading = false;
                        break;
                }
            });
            if (this.searchable) {
                this.typeahead$ = new Subject();
                this.typeahead$.pipe(debounceTime(this.debounce), distinctUntilChanged()).subscribe(this.channel);
            }
            else {
                this.typeahead$ = null;
            }
            this.items$ = this.channel.asObservable();
        }
        this.valueChanges.subscribe((value) => {
            this.checkHasValue(value);
            this.hasValue = !(!value);
        });
        this.channel.next();
    }
    checkHasValue(value) {
        setTimeout(() => {
            if (this.element) {
                if (!value || value.length === 0) {
                    this.element.classList.remove("ng-has-value");
                }
                else {
                    this.element.classList.add("ng-has-value");
                }
            }
        });
    }
    reload(param) {
        this.channel.next(param);
    }
    getCustomPlaceholder() {
        return this.isRequired() ? this.config.placeholder + ' *' : this.config.placeholder;
    }
}

//import {LogService, Logger} from "@bi8/am-logger";
/*@Directive({selector: '[class]'})
export class Class  {
  @HostBinding('class') @Input('class') className: string = '';
}*/
let DynFieldComponent = class DynFieldComponent {
    //@ContentChild('.ng-has-value') stuff;
    //@ViewChildren(Class, {read: ElementRef}) classes: QueryList<ElementRef>;
    constructor(controlContainer, elRef) {
        this.controlContainer = controlContainer;
        this.elRef = elRef;
        this.paths = [];
        this.messages = new Map();
    }
    ngAfterContentInit() {
    }
    ngAfterViewInit() {
        let bling = this.elRef.nativeElement.querySelector('.ng-select-container');
        if (bling) {
            if (this.dfc instanceof DynAutoSelectControl) {
                this.dfc.element = bling;
            }
        }
        if (this.ngSelect && this.dfc instanceof DynAutoSelectControl) {
            this.dfc.ngSelectComponent = this.ngSelect;
        }
    }
    /*removeClass(){
      if ( this.classes && this.classes.length ) {
        return this
          .classes
          .map((elRef:ElementRef):Element => elRef.nativeElement)
          .filter( (element: Element) => element.classList.remove('ng-has-value'));
      }
    }*/
    ngOnInit() {
        this.dfc = this.controlContainer.control.get(this.name);
        this.placeholder = this.dfc.config.placeholder;
        this.hint = this.dfc.config.hint;
        for (let entry of this.dfc.config.messages) {
            this.messages.set(entry.key, entry.value);
        }
        this.path = this.resolvePath();
    }
    resolvePath() {
        let paths = [this.dfc.key];
        this.resolveParentPath(this.dfc.parent, paths);
        let resolvedPath = '';
        paths.reverse().forEach((path, index) => {
            if (path) {
                if (resolvedPath) {
                    resolvedPath += '.';
                }
                resolvedPath += path;
                this.paths.push(resolvedPath);
            }
        });
        return resolvedPath;
    }
    resolveParentPath(control, paths) {
        if (control instanceof DynFormGroup) {
            paths.push(control.key);
        }
        else if (control instanceof DynFormArray) {
            paths.push(control.key);
        }
        if (control.parent) {
            this.resolveParentPath(control.parent, paths);
        }
    }
    resolveValidationMessage(type) {
        let message = '';
        if (this.messages.has(type)) {
            message = this.messages.get(type);
        }
        else if (this.dfc.config.useDefaultErrorMessages) {
            switch (type) {
                case 'required':
                    message = 'Value required';
                    break;
                case 'pattern':
                    message = 'Invalid format';
                    break;
                case 'email':
                    message = 'Invalid email';
                    break;
            }
        }
        return message;
    }
};
DynFieldComponent.ctorParameters = () => [
    { type: ControlContainer, decorators: [{ type: Optional }, { type: Host }, { type: SkipSelf }] },
    { type: ElementRef }
];
__decorate([
    Input(),
    __metadata("design:type", Object)
], DynFieldComponent.prototype, "name", void 0);
__decorate([
    ViewChild('ngselect', { static: false }),
    __metadata("design:type", NgSelectComponent)
], DynFieldComponent.prototype, "ngSelect", void 0);
DynFieldComponent = __decorate([
    Component({
        selector: 'dyn-field',
        template: "<ng-container [ngSwitch]=\"dfc.type\">\r\n  <div fxLayout=\"row\" class=\"am-field-row\">\r\n    <!--=====[ AUTO SELECT FIELD ]=====-->\r\n    <ng-container *ngSwitchCase=\"'autoselect'\">\r\n      <div class=\"am-field-container\" fxLayout=\"row\" fxFlex>\r\n        <ng-select #ngselect [items]=\"dfc.items$ | async\"\r\n                   [formControl]=\"dfc\"\r\n                   [placeholder]=\"dfc.getCustomPlaceholder()\"\r\n                   [bindLabel]=\"dfc.bindLabel\"\r\n                   [typeahead]=\"dfc.typeahead$\"\r\n                   [loading]=\"dfc.loading\"\r\n                   [bindValue]=\"dfc.bindValue\"\r\n                   [multiple]=\"dfc.multiple\"\r\n                   [searchable]=\"dfc.searchable\"\r\n                   fxFlex=\"1 1 auto\"\r\n                   [ngClass]=\"{'am-has-value': dfc.hasValue, 'am-no-value' : !dfc.hasValue}\"\r\n                   style=\"width: 100px;\">\r\n          <ng-template ng-label-tmp let-item=\"item\" *ngIf=\"dfc.labelTemplate\" let-clear=\"clear\">\r\n            <ng-container [ngTemplateOutlet]=\"dfc.labelTemplate\" [ngTemplateOutletContext]=\"{item: item, clear: clear}\"></ng-container>\r\n          </ng-template>\r\n\r\n          <ng-template ng-option-tmp let-item=\"item\" let-index=\"index\" let-search=\"searchTerm\" *ngIf=\"dfc.optionTemplate\">\r\n            <ng-container [ngTemplateOutlet]=\"dfc.optionTemplate\" [ngTemplateOutletContext]=\"{item: item, index: index, search: search}\"></ng-container>\r\n          </ng-template>\r\n        </ng-select>\r\n        <span class=\"am-select-error\" *ngIf=\"dfc.hasError('required') && dfc.touched\">{{resolveValidationMessage('required')}}</span>\r\n        <span class=\"am-select-error\" *ngIf=\"dfc.hasError('pattern') && dfc.touched\">{{resolveValidationMessage('pattern')}}</span>\r\n        <span class=\"am-select-error\" *ngIf=\"dfc.hasError('email') && dfc.touched\">{{resolveValidationMessage('email')}}</span>\r\n        <span class=\"am-select-error\" *ngIf=\"dfc.hasError('match') && dfc.touched\">{{resolveValidationMessage('match')}}</span>\r\n        <span class=\"am-select-error\" *ngIf=\"dfc.hasError('time') && dfc.touched\">{{resolveValidationMessage('time')}}</span>\r\n        <span class=\"am-select-error\" *ngIf=\"dfc.hasError('logical') && dfc.touched\">{{dfc.logicalErrorMessage}}</span>\r\n      </div>\r\n    </ng-container>\r\n\r\n    <!--=====[ TEXT FIELD ]=====-->\r\n    <mat-form-field *ngSwitchCase=\"'text'\" [hintLabel]=\"hint\" fxFlex>\r\n      <input matInput\r\n             hideRequiredMarker=\"false\"\r\n             [name]=\"dfc.key\"\r\n             [formControl]=\"dfc\"\r\n             [type]=\"dfc.config.format\"\r\n             [placeholder]=\"placeholder\"\r\n             [maxlength]=\"dfc.config.maxlimit\"\r\n             [required]=\"dfc.config.required\"\r\n             [dir]=\"dfc.config.dir\">\r\n\r\n      <mat-hint *ngIf=\"dfc.config.counter && dfc.config.maxlimit\" align=\"end\" class=\"no-text-wrap\">{{dfc.value ? dfc.value.length : 0}} / {{dfc.config.maxlimit}}</mat-hint>\r\n\r\n      <mat-error *ngIf=\"dfc.hasError('required')\">{{resolveValidationMessage('required')}}</mat-error>\r\n      <mat-error *ngIf=\"dfc.hasError('pattern')\">{{resolveValidationMessage('pattern')}}</mat-error>\r\n      <mat-error *ngIf=\"dfc.hasError('email')\">{{resolveValidationMessage('email')}}</mat-error>\r\n      <mat-error *ngIf=\"dfc.hasError('match')\">{{resolveValidationMessage('match')}}</mat-error>\r\n      <mat-error *ngIf=\"dfc.hasError('time')\">{{resolveValidationMessage('time')}}</mat-error>\r\n      <mat-error *ngIf=\"dfc.hasError('logical')\">{{dfc.logicalErrorMessage}}</mat-error>\r\n    </mat-form-field>\r\n\r\n    <!--=====[ TEXTAREA FIELD ]=====-->\r\n    <mat-form-field *ngSwitchCase=\"'textarea'\" [hintLabel]=\"hint\" fxFlex>\r\n      <textarea matInput\r\n                hideRequiredMarker=\"false\"\r\n                matTextareaAutosize\r\n                [matAutosizeMinRows]=\"dfc.config.minRows\"\r\n                [matAutosizeMaxRows]=\"dfc.config.maxRows\"\r\n                [name]=\"dfc.key\"\r\n                [formControl]=\"dfc\"\r\n                [placeholder]=\"placeholder\"\r\n                [maxlength]=\"dfc.config.maxlimit\"\r\n                [required]=\"dfc.config.required\"\r\n                [dir]=\"dfc.config.dir\"></textarea>\r\n\r\n      <mat-hint *ngIf=\"dfc.config.counter && dfc.config.maxlimit\" align=\"end\" class=\"no-text-wrap\">{{dfc.value ? dfc.value.length : 0}} / {{dfc.config.maxlimit}}</mat-hint>\r\n      <mat-error *ngIf=\"dfc.hasError('required')\">{{resolveValidationMessage('required')}}</mat-error>\r\n      <mat-error *ngIf=\"dfc.hasError('pattern')\">{{resolveValidationMessage('pattern')}}</mat-error>\r\n      <mat-error *ngIf=\"dfc.hasError('email')\">{{resolveValidationMessage('email')}}</mat-error>\r\n      <mat-error *ngIf=\"dfc.hasError('match')\">{{resolveValidationMessage('match')}}</mat-error>\r\n      <mat-error *ngIf=\"dfc.hasError('logical')\">{{dfc.logicalErrorMessage}}</mat-error>\r\n    </mat-form-field>\r\n\r\n    <!--=====[ AUTOCOMPLETE ]=====-->\r\n    <ng-container *ngSwitchCase=\"'auto-complete'\">\r\n      <mat-form-field fxFlex>\r\n        <input matInput\r\n               [name]=\"dfc.key\"\r\n               [placeholder]=\"placeholder\"\r\n               [matAutocomplete]=\"auto\"\r\n               [formControl]=\"dfc\"\r\n               [required]=\"dfc.config.required\"\r\n               [dir]=\"dfc.config.dir\">\r\n\r\n        <mat-error *ngIf=\"dfc.hasError('required')\">{{resolveValidationMessage('required')}}</mat-error>\r\n        <mat-error *ngIf=\"dfc.hasError('match')\">{{resolveValidationMessage('match')}}</mat-error>\r\n        <mat-error *ngIf=\"dfc.hasError('logical')\">{{dfc.logicalErrorMessage}}</mat-error>\r\n\r\n        <mat-autocomplete #auto=\"matAutocomplete\" [displayWith]=\"dfc.displayFn.bind(dfc)\">\r\n          <mat-option *ngFor=\"let opt of dfc.selectOptions$ | async\" [value]=\"opt\">\r\n            {{dfc.displayFn(opt)}}\r\n          </mat-option>\r\n        </mat-autocomplete>\r\n      </mat-form-field>\r\n    </ng-container>\r\n\r\n    <!--=====[ DATE ]=====-->\r\n    <ng-container *ngSwitchCase=\"'date'\">\r\n      <mat-form-field fxFlex>\r\n        <input matInput\r\n               hideRequiredMarker=\"false\"\r\n               [name]=\"dfc.key\"\r\n               [formControl]=\"dfc\"\r\n               type=\"text\"\r\n               [min]=\"dfc.minDate\"\r\n               [max]=\"dfc.maxDate\"\r\n               [required]=\"dfc.config.required\"\r\n               [matDatepicker]=\"picker\"\r\n               [placeholder]=\"placeholder\"\r\n               style=\"pointer-events:none;\" />\r\n\r\n        <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n        <mat-datepicker #picker></mat-datepicker>\r\n\r\n        <mat-error *ngIf=\"dfc.hasError('required')\">{{resolveValidationMessage('required')}}</mat-error>\r\n        <mat-error *ngIf=\"dfc.hasError('pattern')\">{{resolveValidationMessage('pattern')}}</mat-error>\r\n        <mat-error *ngIf=\"dfc.hasError('match')\">{{resolveValidationMessage('match')}}</mat-error>\r\n        <mat-error *ngIf=\"dfc.hasError('logical')\">{{dfc.logicalErrorMessage}}</mat-error>\r\n      </mat-form-field>\r\n    </ng-container>\r\n\r\n    <!--=====[ DATE ]=====-->\r\n    <ng-container *ngSwitchCase=\"'time'\">\r\n      <am-timepicker [formControl]=\"dfc\"></am-timepicker>\r\n    </ng-container>\r\n\r\n    <!--=====[ SELECT FIELD ]=====-->\r\n    <ng-container *ngSwitchCase=\"'select'\" >\r\n      <mat-form-field fxFlex>\r\n        <mat-select [formControl]=\"dfc\"\r\n                   [placeholder]=\"placeholder\"\r\n                   [required]=\"dfc.config.required\"\r\n                   required=\"true\"\r\n                   [multiple]=\"dfc.multiple\">\r\n          <mat-option *ngIf=\"dfc.showNone\" (click)=\"dfc.reset()\">{{dfc.noneLabel}}</mat-option>\r\n          <mat-option *ngFor=\"let opt of dfc.selectOptions$ | async\" [value]=\"opt.code\">{{opt.value}}</mat-option>\r\n        </mat-select>\r\n        <mat-error *ngIf=\"dfc.hasError('required') && dfc.touched\">This option is required</mat-error>\r\n      </mat-form-field>\r\n    </ng-container>\r\n\r\n    <!--=====[ CHECK BOX ]=====-->\r\n    <ng-container *ngSwitchCase=\"'checkbox'\">\r\n      <mat-checkbox [formControl]=\"dfc\" fxFlex>\r\n        {{placeholder}}\r\n      </mat-checkbox>\r\n    </ng-container>\r\n\r\n    <!--=====[ LABEL ]=====-->\r\n    <ng-container *ngSwitchCase=\"'label'\">\r\n      <div fxFlex>{{placeholder}}</div>\r\n    </ng-container>\r\n  </div>\r\n</ng-container>\r\n",
        styles: [""]
    }),
    __param(0, Optional()), __param(0, Host()), __param(0, SkipSelf()),
    __metadata("design:paramtypes", [ControlContainer, ElementRef])
], DynFieldComponent);

let DynToolbarPanelComponent = class DynToolbarPanelComponent {
    constructor() { }
    ngOnInit() {
    }
};
__decorate([
    Input(),
    __metadata("design:type", String)
], DynToolbarPanelComponent.prototype, "header", void 0);
DynToolbarPanelComponent = __decorate([
    Component({
        selector: 'dyn-toolbar-panel',
        template: "<mat-card class=\"container\">\r\n  <mat-toolbar *ngIf=\"header\" color=\"primary\"> {{header}}</mat-toolbar>\r\n  <div class=\"body\">\r\n    <ng-content></ng-content>\r\n  </div>\r\n</mat-card>\r\n",
        styles: [""]
    }),
    __metadata("design:paramtypes", [])
], DynToolbarPanelComponent);

let DynFieldSetComponent = class DynFieldSetComponent {
    constructor() { }
    ngOnInit() {
    }
};
__decorate([
    Input(),
    __metadata("design:type", String)
], DynFieldSetComponent.prototype, "header", void 0);
DynFieldSetComponent = __decorate([
    Component({
        selector: 'dyn-field-set',
        template: "<fieldset>\r\n  <legend *ngIf=\"header\">{{header}}</legend>\r\n  <ng-content></ng-content>\r\n</fieldset>\r\n",
        styles: [""]
    }),
    __metadata("design:paramtypes", [])
], DynFieldSetComponent);

var AmTimepickerComponent_1;
let AmTimepickerComponent = AmTimepickerComponent_1 = class AmTimepickerComponent {
    constructor(_elementRef) {
        this._elementRef = _elementRef;
        this._cvaOnChange = () => { };
        this._validatorOnChange = () => { };
        this._onTouched = () => { };
        this.timeForm = new FormGroup({
            hours: new FormControl(),
            minutes: new FormControl(),
            amPm: new FormControl()
        });
    }
    set minHours(minHours) {
        this._minHours = minHours;
    }
    set maxHours(maxHours) {
        this._maxHours = maxHours;
    }
    get disabled() { return !!this._disabled; }
    set disabled(value) {
        const newValue = coerceBooleanProperty(value);
        if (this._disabled !== newValue) {
            this._disabled = newValue;
        }
    }
    ngAfterContentInit() {
    }
    ngOnDestroy() {
    }
    writeValue(value) {
        this._data = value;
        console.log("writeValue: ", value);
    }
    registerOnChange(fn) {
        this._cvaOnChange = fn;
        console.log("registerOnChange:", fn);
    }
    registerOnTouched(fn) {
        this._onTouched = fn;
        console.log("registerOnTouch: ", fn);
    }
    setDisabledState(disabled) {
        this.disabled = disabled;
        console.log("setDisabled: ", disabled);
    }
};
AmTimepickerComponent.ctorParameters = () => [
    { type: ElementRef }
];
__decorate([
    Input(),
    __metadata("design:type", Number),
    __metadata("design:paramtypes", [Number])
], AmTimepickerComponent.prototype, "minHours", null);
__decorate([
    Input(),
    __metadata("design:type", Number),
    __metadata("design:paramtypes", [Number])
], AmTimepickerComponent.prototype, "maxHours", null);
__decorate([
    Input(),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [Object])
], AmTimepickerComponent.prototype, "disabled", null);
AmTimepickerComponent = AmTimepickerComponent_1 = __decorate([
    Component({
        selector: 'am-timepicker',
        template: "<form [formGroup]=\"timeForm\" novalidate style=\"display: flex; flex-direction: row;\">\r\n  <mat-form-field style=\"width: 40px; padding-right: 5px;\">\r\n    <mat-select formControlName=\"hours\">\r\n      <mat-option value=\"1\">&nbsp;1</mat-option>\r\n      <mat-option value=\"2\">2</mat-option>\r\n      <mat-option value=\"3\">3</mat-option>\r\n      <mat-option value=\"4\">4</mat-option>\r\n      <mat-option value=\"5\">5</mat-option>\r\n      <mat-option value=\"6\">6</mat-option>\r\n      <mat-option value=\"7\">7</mat-option>\r\n      <mat-option value=\"8\">8</mat-option>\r\n      <mat-option value=\"9\">9</mat-option>\r\n      <mat-option value=\"10\">10</mat-option>\r\n      <mat-option value=\"11\">11</mat-option>\r\n      <mat-option value=\"12\">12</mat-option>\r\n    </mat-select>\r\n  </mat-form-field>\r\n  <mat-form-field style=\"width: 40px; padding-right: 5px;\">\r\n    <mat-select formControlName=\"minutes\">\r\n      <mat-option value=\"1\">00</mat-option>\r\n      <mat-option value=\"1\">05</mat-option>\r\n      <mat-option value=\"2\">10</mat-option>\r\n      <mat-option value=\"3\">15</mat-option>\r\n      <mat-option value=\"4\">20</mat-option>\r\n      <mat-option value=\"5\">25</mat-option>\r\n      <mat-option value=\"6\">30</mat-option>\r\n      <mat-option value=\"7\">35</mat-option>\r\n      <mat-option value=\"8\">40</mat-option>\r\n      <mat-option value=\"9\">45</mat-option>\r\n      <mat-option value=\"10\">50</mat-option>\r\n      <mat-option value=\"11\">55</mat-option>\r\n    </mat-select>\r\n  </mat-form-field>\r\n  <mat-form-field style=\"width: 50px;\">\r\n    <mat-select formControlName=\"amPm\">\r\n      <mat-option value=\"am\">AM</mat-option>\r\n      <mat-option value=\"pm\">PM</mat-option>\r\n    </mat-select>\r\n  </mat-form-field>\r\n</form>\r\n",
        providers: [
            {
                provide: NG_VALUE_ACCESSOR,
                useExisting: forwardRef(() => AmTimepickerComponent_1),
                multi: true
            }
        ]
    }),
    __metadata("design:paramtypes", [ElementRef])
], AmTimepickerComponent);

let AmDynFormModule = class AmDynFormModule {
};
AmDynFormModule = __decorate([
    NgModule({
        imports: [
            CommonModule,
            RouterModule,
            BrowserAnimationsModule,
            FormsModule,
            ReactiveFormsModule,
            FlexLayoutModule,
            MatAutocompleteModule,
            MatCardModule,
            MatButtonModule,
            MatCheckboxModule,
            MatDatepickerModule,
            MatNativeDateModule,
            MatTooltipModule,
            MatInputModule,
            MatSelectModule,
            MatOptionModule,
            MatDialogModule,
            MatToolbarModule,
            MatIconModule,
            MatSidenavModule,
            MatMenuModule,
            MatTableModule,
            MatListModule,
            NgSelectModule
        ],
        exports: [
            DynFieldComponent,
            DynFieldSetComponent,
            DynToolbarPanelComponent,
            AmTimepickerComponent
        ],
        declarations: [
            DynFieldComponent,
            DynFieldSetComponent,
            DynToolbarPanelComponent,
            AmTimepickerComponent
        ],
        providers: [DynFormService]
    })
], AmDynFormModule);

class DynTextControl extends DynFormControl {
    constructor(options = {}, validator, asyncValidator) {
        super(options, validator, asyncValidator);
        this.type = 'text';
        this.config.format = options['format'] || 'text';
        this.config.counter = options['counter'] != undefined ? options['counter'] : true;
        this.config.maxlimit = options['maxlimit'];
    }
}

class DynTextareaControl extends DynFormControl {
    constructor(options = {}, validator, asyncValidator) {
        super(options, validator, asyncValidator);
        this.type = 'textarea';
        this.config.minRows = options['minRows'] || null;
        this.config.maxRows = options['maxRows'] || null;
        this.config.maxlimit = options['maxlimit'];
    }
}

class DynAutoCompleteControl extends DynFormControl {
    constructor(options = {}, validator, asyncValidator) {
        super(options, validator, asyncValidator);
        this.type = 'auto-complete';
        this.selectOptions$ = new Subject();
        this.total = 0;
        this.items = [];
        this.loader = options['loader'];
        // load the initial values after the first tick
        setTimeout(() => {
            this.loadValues(null);
        }, 0);
        this.valueChanges.subscribe((value) => {
            this.loadValues(value);
        });
    }
    loadValues(value) {
        //console.log("loading values: ", value);
        this.loader.prepare({
            value: value
        }).subscribe((result) => {
            this.total = result.total;
            this.items = result.items;
            this.selectOptions$.next(this.items);
        });
    }
    displayFn(item) {
        return get(item, this.loader.valueProperty);
    }
}
class ArrayAutoCompleteLoader {
    constructor(items, filterFn, options) {
        this.items = items;
        this.filterFn = filterFn;
        this.size = !isNil(options.size) ? options.size : 15;
        this.page = !isNil(options.page) ? options.page : 0;
        this.codeProperty = !isNil(options.codeProperty) ? options.codeProperty : 'code';
        this.valueProperty = !isNil(options.valueProperty) ? options.valueProperty : 'value';
    }
    prepare(value) {
        return of(this.items).pipe(map((items) => {
            let filteredList = [];
            // note that when the actual selection takes place, the value will be the actual selected object
            // and not the string that we expect.  If it is an object, there is no reason for loading the list
            let isObject$1 = isObject(value);
            items.forEach((item, index) => {
                let itemValue = get(item, this.valueProperty);
                if (isObject$1 || this.filterFn(item, value.value)) {
                    filteredList.push(item);
                }
            });
            return this.processResponse({
                total: filteredList.length,
                items: filteredList.length > 0 ? chunk(filteredList, this.size)[this.page] : filteredList
            });
        }));
    }
    processResponse(response) {
        return response;
    }
}
class ObservableAutoCompleteLoader {
    constructor(loadFn, options) {
        this.loadFn = loadFn;
        if (options) {
            this.size = isNil(options.size) ? options.size : 15;
            this.page = isNil(options.page) ? options.page : 0;
        }
    }
    prepare(value) {
        let ctx = {
            size: this.size,
            page: this.page,
            value: value
        };
        return this.loadFn(ctx).pipe(map((response) => {
            return this.processResponse(response);
        }));
    }
    processResponse(response) {
        return {
            total: response.total,
            items: response.results
        };
    }
}
class KeywordAutoCompleteCriteriaLoader {
    constructor(loadFn, options) {
        this.loadFn = loadFn;
        if (options) {
            this.size = isNil(options.size) ? options.size : 50;
            this.page = isNil(options.page) ? options.page : 0;
            this.inclusive = isNil(options.inclusive) ? options.inclusive : true;
            this.keywordProperty = options.keywordProperty;
            this.codeProperty = !isNil(options.codeProperty) ? options.codeProperty : 'code';
            this.valueProperty = !isNil(options.valueProperty) ? options.valueProperty : 'value';
        }
    }
    resolveContext(value) {
        let ctx = {
            size: this.size,
            page: this.page,
            inclusive: this.inclusive,
            criteria: []
        };
        if (this.keywordProperty && !isObject(value)) {
            ctx[this.keywordProperty] = value;
        }
        return ctx;
    }
    prepare(value) {
        let ctx = this.resolveContext(value);
        return this.loadFn(ctx).pipe(map((response) => {
            return this.processResponse(response);
        }));
    }
    processResponse(response) {
        return {
            total: response.total,
            items: response.results
        };
    }
}

class DynCheckboxControl extends DynFormControl {
    constructor(options = {}, validator, asyncValidator) {
        super(options, validator, asyncValidator);
        this.type = 'checkbox';
        this.config.leadingLabel = options['leadingLabel'];
    }
}

class DynDateControl extends DynFormControl {
    constructor(options = {}, validator, asyncValidator) {
        super(options, validator, asyncValidator);
        this.type = 'date';
        this.minDate = options['minDate'] || null;
        this.maxDate = options['maxDate'] || null;
    }
}

class DynSelectControl extends DynFormControl {
    constructor(options = {}, validator, asyncValidator) {
        super(options, validator, asyncValidator);
        this.type = 'select';
        this.selectOptions$ = options['selectOptions'] || [];
        this.showNone = options['showNone'] || false;
        this.noneLabel = options['noneLabel'];
        this.multiple = options['multiple'] || false;
    }
    setValue(value, options) {
        if (value == null) {
            super.setValue('', options);
        }
        else {
            super.setValue(value, options);
        }
    }
}

const moment = moment_;
function DynMatchValidator(otherControlName) {
    let thisControl;
    let otherControl;
    return function matchOtherValidate(control) {
        if (!control.parent) {
            return null;
        }
        // Initializing the validator.
        if (!thisControl) {
            thisControl = control;
            otherControl = control.parent.get(otherControlName);
            if (!otherControl) {
                throw new Error('matchOtherValidator(): other control is not found in parent group');
            }
            otherControl.valueChanges.subscribe(() => {
                thisControl.updateValueAndValidity();
            });
        }
        if (!otherControl) {
            return null;
        }
        if (otherControl.value !== thisControl.value) {
            return {
                match: true
            };
        }
        return null;
    };
}
function BusinessLogicValidator() {
    return function matchOtherValidate(control) {
        if (!control.parent) {
            return null;
        }
        return null;
    };
}
class TimeUtils {
    static parseTime(value) {
        if (!value) {
            return null;
        }
        let formats = ['HH:mm', 'H:mm'];
        for (let format of formats) {
            let dt = moment(value, format, true);
            if (dt.isValid()) {
                return {
                    hours: dt.hours(),
                    minutes: dt.minutes(),
                    is24Hour: true
                };
            }
        }
        formats = ['hh:mm a', 'hh:mma', 'h:mm a', 'h:mma', 'h:m a', 'h:ma'];
        for (let format of formats) {
            let dt = moment(value, format, true);
            if (dt.isValid()) {
                return {
                    hours: dt.hours(),
                    minutes: dt.minutes(),
                    is24Hour: false
                };
            }
        }
        return null;
    }
    static formatTime(date) {
        if (date) {
            return date.format('hh:mm a');
        }
        else if (date) {
            return moment(date).format('hh:mm a');
        }
    }
    static applyTime(date, time) {
        if (date) {
            let md = date;
            md.hours(time.hours);
            md.minutes(time.minutes);
        }
        else if (date) {
            let md = moment(date);
            md.hours(time.hours);
            md.minutes(time.minutes);
        }
    }
}
function TimeValidator() {
    return (control) => {
        let value = control.value;
        if (value) {
            let td = TimeUtils.parseTime(value);
            if (td != null) {
                return null;
            }
            else {
                return { time: true };
            }
        }
        else {
            return null;
        }
    };
}

class DynHiddenControl extends DynFormControl {
    constructor(options = {}, validator, asyncValidator) {
        super(options, validator, asyncValidator);
        this.type = 'hidden';
    }
}

var NotificationType;
(function (NotificationType) {
    NotificationType["init"] = "init";
    NotificationType["busy"] = "busy";
    NotificationType["idle"] = "idle";
    NotificationType["paramFunc"] = "paramFunc";
    NotificationType["inputNext"] = "inputNext";
    NotificationType["inputComplete"] = "inputComplete";
    NotificationType["inputError"] = "inputError";
    NotificationType["outputFuncError"] = "outputFuncError";
    NotificationType["outputNext"] = "outputNext";
    NotificationType["outputError"] = "outputError";
    NotificationType["outputComplete"] = "outputComplete";
    NotificationType["close"] = "close";
    NotificationType["enable"] = "enable";
    NotificationType["disable"] = "disable";
})(NotificationType || (NotificationType = {}));
class Channel {
    constructor(fn, options) {
        this.fn = fn;
        this.closed = false;
        this.enabled = true;
        if (options) {
            this.input = options.input || new Subject();
            this.output = options.output || new ReplaySubject(1);
            this.enabled = options.enabled || true;
            this.name = options.name || 'channel';
            this.debug = options.debug || false;
            this.paramFn = options.paramFn;
            this.notificationFn = options.notificationFn;
        }
        else {
            this.input = new Subject();
            this.output = new ReplaySubject(1);
            this.enabled = true;
            this.name = 'channel';
            this.debug = false;
        }
        this.notifications = new BehaviorSubject({ type: NotificationType.init });
        //this.observeNotifications().subscribe();
        if (this.notificationFn) {
            this.observeNotifications().subscribe(this.notificationFn);
        }
        this.input.pipe(takeWhile((value) => !this.closed), filter((value) => this.enabled), map((input) => {
            this.emitNotification({ type: NotificationType.busy });
            if (this.paramFn) {
                let result = this.paramFn(input);
                this.emitNotification({ type: NotificationType.paramFunc, data: { before: input, after: result } });
                return result;
            }
            else {
                return input;
            }
        }), tap((data) => {
            this.inputBusy = true;
            this.emitNotification({ type: NotificationType.inputNext, data: data });
        })).subscribe({
            next: (value) => {
                try {
                    this.outputBusy = true;
                    let observable = this.fn(value);
                    observable.pipe(tap((data) => {
                        this.emitNotification({ type: NotificationType.outputNext, data: data });
                    })).subscribe({
                        next: (response) => this.output.next(response),
                        error: (err) => {
                            this.emitNotification({ type: NotificationType.outputError, error: err });
                            this.output.error(err);
                        },
                        complete: () => {
                            this.outputBusy = false;
                            this.emitNotification({ type: NotificationType.outputComplete });
                            this.emitNotification({ type: NotificationType.idle });
                        }
                    });
                }
                catch (err) {
                    this.emitNotification({ type: NotificationType.outputFuncError, error: err });
                    this.outputBusy = false;
                }
            },
            error: (err) => {
                this.emitNotification({ type: NotificationType.outputFuncError, error: err });
            },
            complete: () => {
                this.inputBusy = false;
            }
        });
    }
    isBusy() {
        return this.inputBusy || this.outputBusy;
    }
    isInputBusy() {
        return this.inputBusy;
    }
    isOutputBusy() {
        return this.outputBusy;
    }
    next(value) {
        this.input.next(value);
        return this;
    }
    emit(value) {
        this.output.next(value);
    }
    observe(value, ...ops) {
        setInterval(() => {
            this.next(value);
        });
        return this.output.pipe(pipeFromArray([...ops]));
    }
    link(observer, ...ops) {
        observer.pipe(pipeFromArray([...ops])).subscribe((value) => this.next(value));
    }
    pipe(observer, ...ops) {
        observer.pipe(pipeFromArray([...ops])).subscribe((value) => this.emit(value));
    }
    asObservable() {
        return this.output.asObservable();
    }
    observeNotifications() {
        return this.notifications.asObservable();
    }
    emitNotification(notification) {
        notification.name = this.name;
        if (this.debug) {
            switch (notification.type) {
                case NotificationType.inputError:
                case NotificationType.outputError:
                case NotificationType.outputFuncError:
                    console.error(`[${notification.name}:${notification.type}] `, notification.error || '');
                    break;
                default:
                    console.debug(`[${notification.name}:${notification.type}] `, notification.data || '');
                    break;
            }
        }
        this.notifications.next(notification);
    }
    enable() {
        this.enabled = false;
        return this;
    }
    disable() {
        this.enabled = true;
        return this;
    }
    close() {
        this.closed = true;
        this.input.unsubscribe();
        this.output.unsubscribe();
    }
}
class ChannelSwitch {
    constructor(...channels) {
        this.channels = new Map();
        channels.forEach((config) => {
            this.channels.set(config.key, config.channel);
        });
    }
    set(key, channel) {
        this.channels.set(key, channel);
        return channel;
    }
    get(key) {
        return this.channels.get(key);
    }
    isBusy(key) {
        let channel = this.channels.get(key);
        return channel ? channel.isBusy() : false;
    }
    isInputBusy(key) {
        let channel = this.channels.get(key);
        return channel ? channel.isInputBusy() : false;
    }
    isOutputBusy(key) {
        let channel = this.channels.get(key);
        return channel ? channel.isOutputBusy() : false;
    }
    next(key, value) {
        let channel = this.channels.get(key);
        return channel ? channel.next(value) : null;
    }
    emit(key, value) {
        let channel = this.channels.get(key);
        return channel ? channel.emit(value) : false;
    }
    observe(key, value, ...ops) {
        let channel = this.channels.get(key);
        return channel ? channel.observe(value, ...ops) : null;
    }
    link(key, observer, ...ops) {
        let channel = this.channels.get(key);
        if (channel) {
            channel.link(observer, ...ops);
        }
    }
    pipe(key, observer, ...ops) {
        let channel = this.channels.get(key);
        if (channel) {
            channel.pipe(observer, ...ops);
        }
    }
    asObservable(key) {
        let channel = this.channels.get(key);
        return channel ? channel.asObservable() : null;
    }
    observeNotifications(key) {
        let channel = this.channels.get(key);
        return channel ? channel.observeNotifications() : null;
    }
    enable(key) {
        let channel = this.channels.get(key);
        return channel ? channel.enable() : null;
    }
    disable(key) {
        let channel = this.channels.get(key);
        return channel ? channel.disable() : null;
    }
    close(key) {
        let channel = this.channels.get(key);
        return channel ? channel.close() : null;
    }
}
class DSPipe {
    constructor(ds, key, obs, ops, enabled = true) {
        this.ds = ds;
        this.key = key;
        this.obs = obs;
        this.ops = ops;
        this.enabled = enabled;
        this.connect();
    }
    isConnected() {
        return !(!this.sub);
    }
    connect() {
        if (this.isConnected()) {
            return;
        }
        this.sub = this.obs.pipe(pipeFromArray([...this.ops])).subscribe((value) => {
            console.log(`----> pipe (${this.key})`, value);
            this.ds.next(this.key, value);
        });
    }
    disconnect() {
        if (!this.isConnected()) {
            return;
        }
        this.sub.unsubscribe();
    }
    setOperators(...ops) {
        this.disconnect();
        this.ops = ops;
        this.connect();
    }
    enable() {
        this.enabled = true;
    }
    disable() {
        this.enabled = false;
    }
}
class ObservableDS {
    constructor(options) {
        this.connected = false;
        this.fnMap = new Map();
        this.subjectMap = new Map();
        this.input$ = new Subject();
        this.inputSub = null;
        this.events$ = new Subject();
        this.pipes = [];
        if (options) {
            if (options.autoconnect) {
                this.connect();
            }
            if (options.key && options.obs) {
                this.addObservable(options.key, options.obs);
            }
        }
        else {
            // we connect by default
            this.connect();
        }
    }
    isConnected() {
        return !(!this.inputSub);
    }
    connect() {
        if (this.isConnected()) {
            return;
        }
        this.inputSub = this.input$.pipe(filter((input) => {
            if (this.fnMap.has(input.id)) {
                return true;
            }
            console.error(`[obs] observable with id '${input.id}' not found`);
            return false;
        }), map((input) => {
            let obsFn = this.fnMap.get(input.id);
            return { event: input, fn: obsFn(input.value), sub: this.subjectMap.get(input.id) };
        }))
            .subscribe((input) => this.relay(input.event, input.fn, input.sub));
        this.connected = true;
    }
    relay(event, obs, subject) {
        //console.log(`-----> relay (${subject}: `, event);
        obs.pipe(takeWhile(() => this.connected), 
        //tap((response) => { console.log(`-----> tap relay: `, response); subject.next(response) }),
        tap((response) => this.emit({ input: event, output: response }))).subscribe();
    }
    emit(event) {
        this.events$.next(event);
    }
    asObservable() {
        return this.events$.asObservable();
    }
    disconnect() {
        if (!this.isConnected()) {
            return;
        }
        this.inputSub.unsubscribe();
        let bla = of$1([1, 2, 3]);
        let blaf = bla.subscribe();
        blaf.add(blaf);
        let duff = new Subject();
        blaf.add(duff.asObservable().subscribe());
    }
    next(key, value, options) {
        if (!this.connected) {
            return;
        }
        let event = { id: key, options: options, value: value };
        //console.log(`-----> next (${event})`, event);
        this.input$.next(event);
    }
    addPipe(obs, key, ...operators) {
        let pipe = new DSPipe(this, key, obs, operators);
        this.pipes.push(pipe);
        return pipe;
    }
    clearPipes(...pipes) {
        pipes.forEach((pipe, index) => {
            pipe.disconnect();
            pipes = pipes.splice(index, 1);
        });
    }
    clearAllPipes() {
        this.clearPipes(...this.pipes);
    }
    getPipes() {
        return this.pipes;
    }
    addObservable(key, obs, options) {
        if (!options) {
            options = { behave: true };
        }
        this.fnMap.set(key, obs instanceof Observable ? () => obs : obs);
        this.subjectMap.set(key, options.behave ? new BehaviorSubject([]) : new Subject());
    }
    observe(key, value, options) {
        let subject = this.subjectMap.get(key);
        try {
            return subject.asObservable();
        }
        finally {
            if (value) {
                this.next(key, value);
            }
        }
    }
    destroy() {
    }
}

/**
 * Generated bundle index. Do not edit.
 */

export { AmDynFormModule, ArrayAutoCompleteLoader, BusinessLogicValidator, Channel, ChannelSwitch, DSPipe, DynAutoCompleteControl, DynAutoSelectControl, DynCheckboxControl, DynDateControl, DynFieldComponent, DynFieldSetComponent, DynFormArray, DynFormControl, DynFormGroup, DynFormService, DynHiddenControl, DynMatchValidator, DynSelectControl, DynTextControl, DynTextareaControl, DynToolbarPanelComponent, KeywordAutoCompleteCriteriaLoader, NotificationType, ObservableAutoCompleteLoader, ObservableDS, TimeUtils, TimeValidator, AmTimepickerComponent as ɵa };
//# sourceMappingURL=bi8-am-dyn-form.js.map