File

assets/angular/dmp/dmp-form.component.ts

Description

Main DMP Edit component

Extends

LoadableComponent

Example

Metadata

moduleId module.id
providers Location { : , : }
selector dmp-form
templateUrl ./dmp-form.html

Index

Properties
Methods
Inputs

Constructor

constructor(elm: ElementRef, RecordsService: RecordsService, fcs: FieldControlService, LocationService: Location, translationService: TranslationService)

Expects a number of DI'ed elements.

Parameters :
Name Type Optional Description
elm ElementRef
RecordsService RecordsService
fcs FieldControlService
LocationService Location
translationService TranslationService

Inputs

editMode

Edit mode

Type: boolean

oid

The OID for this Form.

Type: string

recordType

The Record type

Type: string

Methods

clearError
clearError()

Clear the error message.

Returns : void
clearSaving
clearSaving()

Convenience wrapper to clear saving status.

Returns : void
clearStatus
clearStatus(stat: string)

Clears status

Parameters :
Name Type Optional Description
stat string
  • Clears the status
Returns : void
clearSuccess
clearSuccess()

Clear the 'success' message.

Returns : void
formatValues
formatValues(data: any)

Trigger form elements to format their values.

Parameters :
Name Type Optional Description
data any
Returns : any
gotoDashboard
gotoDashboard()

Redirect to dashboard.

Returns : void
isSaving
isSaving()

Returns the saving status of the form.

Returns : any
isValid
isValid(forceValidate: boolean)

Checks form validity.

Parameters :
Name Type Optional Description
forceValidate boolean
Returns : boolean
onCancel
onCancel()

Form cancellation handler.

Returns : void
onSubmit
onSubmit(nextStep: boolean, targetStep: string, forceValidate: boolean)

Main submit method.

Parameters :
Name Type Optional Description
nextStep boolean
targetStep string
forceValidate boolean
Returns : void
rebuildForm
rebuildForm()

Rebuild the form message.

Returns : void
setError
setError(msg: string)

Set a 'error' message.

Parameters :
Name Type Optional Description
msg string
Returns : void
setSaving
setSaving(msg: string)

Convenience wrapper to set saving status.

Parameters :
Name Type Optional Description
msg string
Returns : void
setStatus
setStatus(stat: string, msg: string)

Sets the form message status.

Parameters :
Name Type Optional Description
stat string

Bootstrap contextual status: https://getbootstrap.com/docs/3.3/css/#helper-classes

msg string

Message

Returns : void
setSuccess
setSuccess(msg: string)

Set a 'success' message.

Parameters :
Name Type Optional Description
msg string
Returns : void
stepTo
stepTo(targetStep: string)

Submit the form towards a target step.

Parameters :
Name Type Optional Description
targetStep string
Returns : void
triggerValidation
triggerValidation()

Trigger form validation

Returns : void
watchForChanges
watchForChanges()

Enable form change monitor.

Returns : void

Properties

criticalError
criticalError: any
Type : any

Critical error message

cssClasses
cssClasses: any
Type : any

CSS classes for this form

fieldMap
fieldMap: any
Type : any

Field map

fields
fields: any[]
Type : any[]

Fields for the form

form
form: FormGroup
Type : FormGroup

Form group

formDef
formDef: any
Type : any

Form definition

initSubs
initSubs: any
Type : any

Initialization subscription

needsSave
needsSave: boolean
Type : boolean

Flag when form needs saving.

payLoad
payLoad: any
Type : any

Form JSON string

status
status: any
Type : any

Form status

import { Component, Inject, Input, ElementRef } from '@angular/core';
import { Location, LocationStrategy, PathLocationStrategy } from '@angular/common';
import { FormGroup } from '@angular/forms';
import { RecordsService } from '../shared/form/records.service';
import { LoadableComponent } from '../shared/loadable.component';
import { FieldControlService } from '../shared/form/field-control.service';
import * as _ from "lodash-lib";
import { TranslationService } from '../shared/translation-service';
/**
 * Main DMP Edit component
 *
 * @author <a target='_' href='https://github.com/shilob'>Shilo Banihit</a>
 *
 */
@Component({
  moduleId: module.id,
  selector: 'dmp-form',
  templateUrl: './dmp-form.html',
  providers: [Location, {provide: LocationStrategy, useClass: PathLocationStrategy}]
})
export class DmpFormComponent extends LoadableComponent {
  /**
   * The OID for this Form.
   *
   */
  @Input() oid: string;
  /**
   * Edit mode
   *
   */
  @Input() editMode: boolean;
  /**
   * The Record type
   *
   */
  @Input() recordType: string;
  /**
   * Fields for the form
   */
  fields: any[] = [];
  /**
   * Form group
   */
  form: FormGroup;
  /**
   * Initialization subscription
   */
  initSubs: any;
  /**
   * Field map
   */
  fieldMap: any;
  /**
   * Form JSON string
   */
  payLoad: any;
  /**
   * Form status
   */
  status: any;
  /**
   * Critical error message
   */
  criticalError: any;
  /**
   * Form definition
   */
  formDef: any;
  /**
   * CSS classes for this form
   */
  cssClasses: any;
  /**
   * Flag when form needs saving.
   *
   */
  needsSave: boolean;
  /**
   * Expects a number of DI'ed elements.
   */
  constructor(
    elm: ElementRef,
    @Inject(RecordsService) protected RecordsService: RecordsService,
    @Inject(FieldControlService) protected fcs: FieldControlService,
    @Inject(Location) protected LocationService: Location,
    translationService: TranslationService
  ) {
    super();
    this.status = {};
    this.initSubs = RecordsService.waitForInit((initStat:boolean) => {
      this.initSubs.unsubscribe();
      translationService.isReady(tService => {
        this.fieldMap = {_rootComp:this};
        this.oid = elm.nativeElement.getAttribute('oid');
        this.editMode = elm.nativeElement.getAttribute('editMode') == "true";
        this.recordType = elm.nativeElement.getAttribute('recordType');
        console.log(`Loading form with OID: ${this.oid}, on edit mode:${this.editMode}, Record Type: ${this.recordType}`);
        this.RecordsService.getForm(this.oid, this.recordType, this.editMode).then((obs:any) => {
          obs.subscribe((form:any) => {
            this.formDef = form;
            if (this.editMode) {
              this.cssClasses = this.formDef.editCssClasses;
            } else {
              this.cssClasses = this.formDef.viewCssClasses;
            }
            this.needsSave = false;
            if (form.fieldsMeta) {
              this.fields = form.fieldsMeta;
              this.rebuildForm();
              this.watchForChanges();
            }
          });
        }).catch((err:any) => {
          console.log("Error loading form...");
          console.log(err);
          if (err.status == false) {
              this.criticalError = err.message;
          }
          this.setLoading(false);
        });
      });
    });
  }
  /**
   * Main submit method.
   *
   * @param  {boolean    =             false} nextStep
   * @param  {string     =             null}  targetStep
   * @param  {boolean=false} forceValidate
   * @return {[type]}
   */
  onSubmit(nextStep:boolean = false, targetStep:string = null, forceValidate:boolean=false) {
    if (!this.isValid(forceValidate)) {
      return;
    }
    this.setSaving(this.formDef.messages.saving);
    const values = this.formatValues(this.form.value);
    this.payLoad = JSON.stringify(values);
    console.log("Saving the following values:");
    console.log(this.payLoad);
    this.needsSave = false;
    if (_.isEmpty(this.oid)) {
      this.RecordsService.create(this.payLoad).then((res:any)=>{
        this.clearSaving();
        console.log("Create Response:");
        console.log(res);
        if (res.success) {
          this.oid = res.oid;
          this.LocationService.go(`record/edit/${this.oid}`);
          this.setSuccess(this.formDef.messages.saveSuccess);
          if (nextStep) {
            this.stepTo(targetStep);
          }
        } else {
          this.setError(`${this.formDef.messages.saveError} ${res.message}`);
        }
      }).catch((err:any)=>{
        this.setError(`${this.formDef.messages.saveError} ${err.message}`);
      });
    } else {
      this.RecordsService.update(this.oid, this.payLoad).then((res:any)=>{
        this.clearSaving();
        console.log("Update Response:");
        console.log(res);
        if (res.success) {
          this.setSuccess(this.formDef.messages.saveSuccess);
        } else {
          this.setError(`${this.formDef.messages.saveError} ${res.message}`);
        }
      }).catch((err:any)=>{
        this.setError(`${this.formDef.messages.saveError} ${err}`);
      });
    }
  }

  /**
   * Sets the form message status.
   *
   * @param  {string} stat  Bootstrap contextual status: https://getbootstrap.com/docs/3.3/css/#helper-classes
   * @param  {string} msg Message
   * @return {[type]}
   */
  setStatus(stat:string, msg:string) {
    _.forOwn(this.status, (stat:string, key:string) => {
      this.status[key] = null;
    });
    this.status[stat] = {msg: msg};
  }

  /**
   * Clears status
   *
   * @param  {string} stat - Clears the status
   * @return {[type]}
   */
  clearStatus(stat:string) {
    this.status[stat] = null;
  }

  /**
   * Convenience wrapper to set saving status.
   *
   * @param  {string = 'Saving...'} msg
   * @return {[type]}
   */
  setSaving(msg:string = 'Saving...') {
    this.clearError();
    this.clearSuccess();
    this.setStatus('saving', msg);
  }
  /**
   * Convenience wrapper to clear saving status.
   *
   * @return {[type]}
   */
  clearSaving() {
    this.clearStatus('saving');
  }
  /**
   * Set a 'error' message.
   *
   * @param  {string} msg
   * @return {[type]}
   */
  setError(msg: string) {
    this.clearSaving();
    this.needsSave = true;
    this.setStatus('error', msg);
  }

  /**
   * Clear the error message.
   *
   * @return {[type]}
   */
  clearError() {
    this.clearStatus('error');
  }

  /**
   * Set a 'success' message.
   * @param  {string} msg
   * @return {[type]}
   */
  setSuccess(msg: string) {
    this.clearSaving();
    this.setStatus('success', msg);
  }
  /**
   * Clear the 'success' message.
   * @return {[type]}
   */
  clearSuccess() {
    this.clearStatus('success');
  }
  /**
   * Rebuild the form message.
   *
   * @return {[type]}
   */
  rebuildForm() {
    this.form = this.fcs.toFormGroup(this.fields, this.fieldMap);
  }
  /**
   * Enable form change monitor.
   *
   * @return {[type]}
   */
  watchForChanges() {
    this.setLoading(false);
    if (this.editMode) {
      this.form.valueChanges.subscribe((data:any) => {
        this.needsSave = true;
      });
    }
  }
  /**
   * Trigger form validation
   *
   * @return {[type]}
   */
  triggerValidation() {
    _.forOwn(this.fieldMap, (fieldEntry:any, fieldName:string) => {
      if (!_.isEmpty(fieldName) && !_.startsWith(fieldName, '_')) {
        fieldEntry.field.triggerValidation();
      }
    });
  }
  /**
   * Checks form validity.
   *
   * @param  {boolean=false} forceValidate
   * @return {[type]}
   */
  isValid(forceValidate:boolean=false) {
    if (this.formDef.skipValidationOnSave  && (_.isUndefined(forceValidate) || _.isNull(forceValidate) || !forceValidate)) {
      return true;
    }
    this.triggerValidation();
    if (!this.form.valid) {
      this.setError('There are issues in the form.');
      this.setError(this.formDef.messages.validationFail);
      return false;
    }
    return true;
  }
  /**
   * Submit the form towards a target step.
   *
   * @param  {string} targetStep
   * @return {[type]}
   */
  stepTo(targetStep: string) {
    console.log(this.form.value);
    if (!this.isValid(true)) {
      return;
    }
    this.needsSave = false;
    if (_.isEmpty(this.oid)) {
      this.onSubmit(true, targetStep, true);
    } else {
      this.setSaving(this.formDef.messages.saving);
      const values = this.formatValues(this.form.value);
      this.payLoad = JSON.stringify(values);
      console.log(this.payLoad);
      this.RecordsService.stepTo(this.oid, this.payLoad, targetStep).then((res:any) => {
        this.clearSaving();
        console.log("Update Response:");
        console.log(res);
        if (res.success) {
          this.setSuccess(this.formDef.messages.saveSuccess);
          this.gotoDashboard();
        } else {
          this.setError(`${this.formDef.messages.saveError} ${res.message}`);
        }
      }).catch((err:any)=>{
        this.setError(`${this.formDef.messages.saveError} ${err}`);
      });
    }
  }
  /**
   * Trigger form elements to format their values.
   *
   * @param  {any}    data
   * @return {[type]}
   */
  formatValues(data:any) {
    const formVals = _.cloneDeep(data);
    _.forOwn(formVals, (val:any, key:string) => {
      if (_.isFunction(this.fieldMap[key].instance.formatValue)) {
        const newVal = this.fieldMap[key].instance.formatValue(formVals[key]);
        formVals[key] = newVal;
      }
    });
    return formVals;
  }
  /**
   * Returns the saving status of the form.
   *
   * @return {[type]}
   */
  isSaving() {
    return this.status.saving;
  }
  /**
   * Redirect to dashboard.
   *
   * @author <a target='_' href='https://github.com/shilob'>Shilo Banihit</a>
   * @return {[type]}
   */
  gotoDashboard() {
    window.location.href = this.RecordsService.getDashboardUrl();
  }
  /**
   * Form cancellation handler.
   *
   * @return {[type]}
   */
  onCancel() {
    this.gotoDashboard();
  }
}
<div *ngIf="!criticalError" class="row">
  <div class="col-xs-1"></div>
  <div class="col-xs-10">
      <div [ngClass]="cssClasses">
        <div *ngIf="form">
          <form (ngSubmit)="onSubmit()" [formGroup]="form">
            <dmp-field *ngFor="let field of fields" [field]="field" [form]="form" class="form-row" [fieldMap]="fieldMap"></dmp-field>
            <div *ngIf="editMode" class="form-row">
              <div class="pull-right col-md-10">
                <button type="button" (click)="onSubmit()" class="btn btn-primary" [disabled]="!needsSave || isSaving()">Save</button>
                <button type="button" class="btn btn-warning" [disabled]="isSaving()" (click)="onCancel()">Cancel</button>
              </div>
            </div>
            <div *ngIf="editMode" class="form-row">
              <div class="pull-right col-md-10 margin-15">
                <p class="bg-info text-16 text-info padding-10" *ngIf="status.saving">{{status.saving.msg}}<i class="fa fa-spinner fa-pulse fa-1x fa-fw"></i></p>
                <p class="bg-danger text-16 text-danger padding-10" *ngIf="status.error">{{status.error.msg}}</p>
                <p class="bg-success text-16 text-success padding-10" *ngIf="status.success">{{status.success.msg}}</p>
              </div>
            </div>
          </form>
        </div>
      </div>
  </div>
  <div class="col-xs-1"></div>
</div>
<div *ngIf="criticalError" class="row">
  <div class="col-xs-2"></div>
  <div class="col-xs-8">
    <div class="panel panel-danger">
      <div class="panel-heading">
         <h3 class="panel-title">Error</h3>
       </div>
       <div class="panel-body">
         <code>
           {{criticalError}}
         </code>
       </div>
    </div>
  </div>
  <div class="col-xs-2"></div>
</div>
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""