assets/angular/dmp/dmp-form.component.ts
Main DMP Edit component
moduleId | module.id |
providers |
Location
{ : , : }
|
selector | dmp-form |
templateUrl | ./dmp-form.html |
Properties |
Methods |
Inputs |
constructor(elm: ElementRef, RecordsService: RecordsService, fcs: FieldControlService, LocationService: Location, translationService: TranslationService)
|
||||||||||||||||||||||||
Defined in assets/angular/dmp/dmp-form.component.ts:96
|
||||||||||||||||||||||||
Expects a number of DI'ed elements.
Parameters :
|
editMode
|
Edit mode
Type: |
Defined in assets/angular/dmp/dmp-form.component.ts:50
|
oid
|
The OID for this Form.
Type: |
Defined in assets/angular/dmp/dmp-form.component.ts:45
|
recordType
|
The Record type
Type: |
Defined in assets/angular/dmp/dmp-form.component.ts:55
|
clearError |
clearError()
|
Defined in assets/angular/dmp/dmp-form.component.ts:255
|
Clear the error message.
Returns :
void
|
clearSaving |
clearSaving()
|
Defined in assets/angular/dmp/dmp-form.component.ts:235
|
Convenience wrapper to clear saving status.
Returns :
void
|
clearStatus | ||||||||
clearStatus(stat: string)
|
||||||||
Defined in assets/angular/dmp/dmp-form.component.ts:215
|
||||||||
Clears status
Parameters :
Returns :
void
|
clearSuccess |
clearSuccess()
|
Defined in assets/angular/dmp/dmp-form.component.ts:272
|
Clear the 'success' message.
Returns :
void
|
formatValues | ||||||||
formatValues(data: any)
|
||||||||
Defined in assets/angular/dmp/dmp-form.component.ts:366
|
||||||||
Trigger form elements to format their values.
Parameters :
Returns :
any
|
gotoDashboard |
gotoDashboard()
|
Defined in assets/angular/dmp/dmp-form.component.ts:390
|
Redirect to dashboard.
Returns :
void
|
isSaving |
isSaving()
|
Defined in assets/angular/dmp/dmp-form.component.ts:381
|
Returns the saving status of the form.
Returns :
any
|
isValid | ||||||||
isValid(forceValidate: boolean)
|
||||||||
Defined in assets/angular/dmp/dmp-form.component.ts:314
|
||||||||
Checks form validity.
Parameters :
Returns :
boolean
|
onCancel |
onCancel()
|
Defined in assets/angular/dmp/dmp-form.component.ts:398
|
Form cancellation handler.
Returns :
void
|
onSubmit | ||||||||||||||||
onSubmit(nextStep: boolean, targetStep: string, forceValidate: boolean)
|
||||||||||||||||
Defined in assets/angular/dmp/dmp-form.component.ts:151
|
||||||||||||||||
Main submit method.
Parameters :
Returns :
void
|
rebuildForm |
rebuildForm()
|
Defined in assets/angular/dmp/dmp-form.component.ts:280
|
Rebuild the form message.
Returns :
void
|
setError | ||||||||
setError(msg: string)
|
||||||||
Defined in assets/angular/dmp/dmp-form.component.ts:244
|
||||||||
Set a 'error' message.
Parameters :
Returns :
void
|
setSaving | ||||||||
setSaving(msg: string)
|
||||||||
Defined in assets/angular/dmp/dmp-form.component.ts:225
|
||||||||
Convenience wrapper to set saving status.
Parameters :
Returns :
void
|
setStatus | ||||||||||||
setStatus(stat: string, msg: string)
|
||||||||||||
Defined in assets/angular/dmp/dmp-form.component.ts:202
|
||||||||||||
Sets the form message status.
Parameters :
Returns :
void
|
setSuccess | ||||||||
setSuccess(msg: string)
|
||||||||
Defined in assets/angular/dmp/dmp-form.component.ts:264
|
||||||||
Set a 'success' message.
Parameters :
Returns :
void
|
stepTo | ||||||||
stepTo(targetStep: string)
|
||||||||
Defined in assets/angular/dmp/dmp-form.component.ts:332
|
||||||||
Submit the form towards a target step.
Parameters :
Returns :
void
|
triggerValidation |
triggerValidation()
|
Defined in assets/angular/dmp/dmp-form.component.ts:301
|
Trigger form validation
Returns :
void
|
watchForChanges |
watchForChanges()
|
Defined in assets/angular/dmp/dmp-form.component.ts:288
|
Enable form change monitor.
Returns :
void
|
criticalError |
criticalError:
|
Type : any
|
Defined in assets/angular/dmp/dmp-form.component.ts:83
|
Critical error message |
cssClasses |
cssClasses:
|
Type : any
|
Defined in assets/angular/dmp/dmp-form.component.ts:91
|
CSS classes for this form |
fieldMap |
fieldMap:
|
Type : any
|
Defined in assets/angular/dmp/dmp-form.component.ts:71
|
Field map |
fields |
fields:
|
Type : any[]
|
Defined in assets/angular/dmp/dmp-form.component.ts:59
|
Fields for the form |
form |
form:
|
Type : FormGroup
|
Defined in assets/angular/dmp/dmp-form.component.ts:63
|
Form group |
formDef |
formDef:
|
Type : any
|
Defined in assets/angular/dmp/dmp-form.component.ts:87
|
Form definition |
initSubs |
initSubs:
|
Type : any
|
Defined in assets/angular/dmp/dmp-form.component.ts:67
|
Initialization subscription |
needsSave |
needsSave:
|
Type : boolean
|
Defined in assets/angular/dmp/dmp-form.component.ts:96
|
Flag when form needs saving. |
payLoad |
payLoad:
|
Type : any
|
Defined in assets/angular/dmp/dmp-form.component.ts:75
|
Form JSON string |
status |
status:
|
Type : any
|
Defined in assets/angular/dmp/dmp-form.component.ts:79
|
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>