File

assets/angular/shared/form/field-base.ts

Description

Base class for dynamic form models...

Author: Shilo Banihit

Index

Properties
Methods
Accessors

Constructor

constructor(options: , injector: )
Parameters :
Name Type Optional Description
options
injector

Methods

Public createFormModel
createFormModel()
Returns : any
Public emitEvent
emitEvent(eventName: string, eventData: any, origData: any)
Parameters :
Name Type Optional Description
eventName string
eventData any
origData any
Returns : void
getFromInjector
getFromInjector(token: any)
Parameters :
Name Type Optional Description
token any
Returns : any
Public getGroup
getGroup(group: any, fieldMap: any)

Creates a control group and populates field map with:

fieldMap[name].control = the NG2 FormControl fieldMap[name].field = the Field model (this)

Author: Shilo Banihit

Parameters :
Name Type Optional Description
group any
fieldMap any
Returns : any
getTranslated
getTranslated(key: , defValue: )
Parameters :
Name Type Optional Description
key
defValue
Returns : any
Public reactEvent
reactEvent(eventName: string, eventData: any, origData: any)
Parameters :
Name Type Optional Description
eventName string
eventData any
origData any
Returns : void
setOptions
setOptions(options: literal type)
Parameters :
Name Type Optional Description
options literal type
Returns : void
Public setupEventHandlers
setupEventHandlers()
Returns : void
Public triggerValidation
triggerValidation()
Returns : void
valueNotNull
valueNotNull(data: )
Parameters :
Name Type Optional Description
data
Returns : boolean

Properties

compClass
compClass: any
Type : any
controlType
controlType: string
Type : string
cssClasses
cssClasses: any
Type : any
defaultValue
defaultValue: any
Type : any
editMode
editMode: boolean
Type : boolean
fieldMap
fieldMap: any
Type : any
form
form: any
Type : any
formModel
formModel: any
Type : any
groupName
groupName: string
Type : string
hasControl
hasControl: boolean
Type : boolean
hasGroup
hasGroup: boolean
Type : boolean
hasLookup
hasLookup: boolean
Type : boolean
help
help: string
Type : string
id
id: string
Type : string
injector
injector: Injector
Type : Injector
label
label: string
Type : string
marginTop
marginTop: string
Type : string
name
name: string
Type : string
onChange
onChange: any
Type : any
options
options: any
Type : any
publish
publish: any
Type : any
readOnly
readOnly: boolean
Type : boolean
required
required: boolean
Type : boolean
subscribe
subscribe: any
Type : any
translationService
translationService: TranslationService
Type : TranslationService
utilityService
utilityService: UtilityService
Type : UtilityService
validationMessages
validationMessages: any
Type : any
value
value: T
Type : T

Accessors

isValid
getisValid()
import { Output, EventEmitter, Injector } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { TranslationService } from '../translation-service';
import { UtilityService } from '../util-service';

import * as _ from "lodash-lib";
/**
 * Base class for dynamic form models...
 *
 * Author: <a href='https://github.com/shilob' target='_blank'>Shilo Banihit</a>
 *
 */
export class FieldBase<T> {
  value: T;
  id: string;
  name: string;
  label: string;
  required: boolean;
  controlType: string;
  compClass: any;
  form: any;
  cssClasses: any;
  hasGroup: boolean;
  hasLookup: boolean;
  options: any;
  groupName: string;
  hasControl: boolean;
  formModel: any;
  validationMessages: any;
  editMode: boolean;
  readOnly: boolean;
  help: string;
  translationService: TranslationService;
  defaultValue: any;
  marginTop: string;
  onChange: any; // custom configuration for each component, for dates: e.g. { 'setStartDate': ['name of pickers']}
  publish: any; // configuration for publishing events
  subscribe: any; // configuration for subscribing to events published by other components
  fieldMap: any;
  utilityService: UtilityService;
  injector: Injector;

  @Output() public onValueUpdate: EventEmitter<any> = new EventEmitter<any>();

  constructor(options = {}, injector) {
    this.injector = injector;
    this.translationService = this.getFromInjector(TranslationService);
    this.setOptions(options);
  }

  getFromInjector(token:any) {
    return this.injector.get(token);
  }

  setOptions(options: {
    value?: T,
    name?: string,
    id?: string,
    label?: string,
    required?: boolean,
    order?: number,
    controlType?: string,
    cssClasses?: any,
    groupName?: string,
    editMode? : boolean,
    readOnly?: boolean,
    help?: string,
    defaultValue?: any
  } = {}) {
    this.value = this.getTranslated(options.value, undefined);
    this.name = options.name || '';
    this.id = options.id || '';
    this.label = this.getTranslated(options.label, '');
    this.help = this.getTranslated(options.help, undefined);
    this.required = !!options.required;
    this.controlType = options.controlType || '';
    this.cssClasses = options.cssClasses || {}; // array of
    this.groupName = options.groupName || null;
    this.editMode = options.editMode || false;
    this.readOnly = options.readOnly || false;
    this.onChange = options['onChange'] || null;
    this.publish = options['publish'] || null;
    this.subscribe = options['subscribe'] || null;

    if (this.groupName) {
      this.hasGroup = true;
    }
    this.options = options;
    this.hasControl = true;
    this.validationMessages = {};
    _.forOwn(options['validationMessages'] || {}, (messageKey, messageName) => {
      this.validationMessages[messageName] = this.getTranslated(messageKey, messageKey);
    });
    this.defaultValue = this.getTranslated(options.defaultValue, undefined);
    if ((_.isUndefined(this.value) || _.isEmpty(this.value)) && !_.isUndefined(this.defaultValue)) {
      this.value = this.defaultValue;
    }
  }

  getTranslated(key, defValue) {
    if (!_.isEmpty(key) && !_.isUndefined(key)) {
      if (_.isFunction(key.startsWith) && key.startsWith('@') && this.translationService) {
        return this.translationService.t(key);
      } else {
        return key;
      }
    } else {
      return defValue;
    }
  }

  get isValid() {
    if (this.form && this.form.controls) {
      return this.form.controls[this.name].valid;
    }
    return false;
  }

  public createFormModel(): any {
    this.formModel = this.required ? new FormControl(this.value || '', Validators.required)
                                      : new FormControl(this.value || '');
    return this.formModel;
  }

  /**
   * Creates a control group and populates field map with:
   *
   * fieldMap[name].control = the NG2 FormControl
   * fieldMap[name].field = the Field model (this)
   *
   * Author: <a href='https://github.com/shilob' target='_blank'>Shilo Banihit</a>
   * @param  {any} group
   * @param  {any} fieldMap
   * @return {any}
   */
  public getGroup(group: any, fieldMap: any) : any {
    this.fieldMap = fieldMap;
    let retval = null;
    fieldMap[this.name] = {field:this};
    let control = this.createFormModel();
    fieldMap[this.name].control = control;
    if (this.hasGroup && this.groupName) {
      if (group[this.groupName]) {
        group[this.groupName].addControl(this.name, control);
      } else {
        const fg = {};
        fg[this.name] = control;
        group[this.groupName] = new FormGroup(fg);
      }
      retval = group[this.groupName];
    } else {
      if (this.hasControl) {
        group[this.name] = control;
        retval = group[this.name];
      }
    }
    return retval;
  }

  public triggerValidation() {
    if (this.formModel) {
      this.formModel.markAsTouched();
      this.formModel.updateValueAndValidity();
    }
  }

  valueNotNull(data) {
    return !_.isNull(data) && (_.isArray(data) ? (!_.isNull(data[0])): true );
  }

  public setupEventHandlers() {
    if (!_.isEmpty(this.formModel)) {
      const publishConfig = this.publish;
      const subscribeConfig = this.subscribe;

      if (!_.isEmpty(publishConfig)) {
        _.forOwn(publishConfig, (eventConfig, eventName) => {
          console.log(`Setting up ${eventName} handlers for field: ${this.name}`)
          const eventSource = eventConfig.modelEventSource;
          this.formModel[eventSource].subscribe((value:any) => {
            if (this.valueNotNull(value)) {
              let emitData = value;
              if (!_.isEmpty(eventConfig.fields)) {
                if (_.isArray(value)) {
                  emitData = [];
                  _.each(value, (v:any) => {
                    if (!_.isEmpty(v)) {
                      const item = {};
                      _.each(eventConfig.fields, (f:any)=> {
                        _.forOwn(f, (src, tgt) => {
                          item[tgt] = _.get(v, src);
                        });
                      });
                      emitData.push(item);
                    }
                  });
                } else {
                  emitData = {};
                  if (!_.isEmpty(value)) {
                    _.each(eventConfig.fields, (f:any)=> {
                      _.forOwn(f, (src, tgt) => {
                        emitData[tgt] = _.get(value, src);
                      });
                    });
                  }
                }
              }
              console.log(`Emitting data:`);
              console.log(emitData);
              this.emitEvent(eventName, emitData, value);
            }
          });
        });
      }

      if (!_.isEmpty(subscribeConfig)) {
        _.forOwn(subscribeConfig, (subConfig, srcName) => {
          _.forOwn(subConfig, (eventConfArr, eventName) => {
            const eventEmitter = srcName == "this" ? this[eventName] : this.fieldMap[srcName].field[eventName];
            eventEmitter.subscribe((value:any) => {
              let curValue = value;
              if (_.isArray(value)) {
                curValue = [];
                _.each(value, (v: any) => {
                  let entryVal = v;
                  _.each(eventConfArr, (eventConf: any) => {
                    const fn = _.get(this, eventConf.action);
                    if (fn) {
                      entryVal = fn(entryVal, eventConf);
                    }
                  });
                  if (!_.isEmpty(entryVal)) {
                    curValue.push(entryVal);
                  }
                });
              } else {
                _.each(eventConfArr, (eventConf: any) => {
                  const fn = _.get(this, eventConf.action);
                  if (fn) {
                    curValue = fn(curValue, eventConf);
                  }
                });
              }
              this.reactEvent(eventName, curValue, value);
            });
          });
        });
      }
    }
  }

  public emitEvent(eventName: string, eventData: any, origData: any) {
    this[eventName].emit(eventData);
  }

  public reactEvent(eventName: string, eventData: any, origData: any) {
    this.formModel.setValue(eventData, { onlySelf: true, emitEvent: false });
  }
}

results matching ""

    No results matching ""