UNPKG

angular-formio

Version:

The Form.io dynamic form and data management system for Angular.

272 lines (249 loc) 8.04 kB
import { Component, Input, Output, EventEmitter, OnInit, OnChanges, ViewEncapsulation, Optional, ElementRef, ViewChild } from '@angular/core'; import { FormioService } from './formio.service'; import { FormioLoader } from './formio.loader'; import { FormioAlerts, FormioAlert } from './formio.alerts'; import { FormioAppConfig } from './formio.config'; import { FormioForm, FormioOptions, FormioError, FormioRefreshValue } from './formio.common'; /* tslint:disable */ const Formio = require('formiojs/full'); const _each = require('lodash/each'); /* tslint:enable */ @Component({ selector: 'formio', template: '<div>' + '<formio-loader></formio-loader>' + '<formio-alerts></formio-alerts>' + '<div #formio></div>' + '</div>', styles: [require('formiojs/dist/formio.form.min.css').toString()], encapsulation: ViewEncapsulation.None }) export class FormioComponent implements OnInit, OnChanges { public ready: Promise<boolean>; public readyResolve: any; @Input() form: FormioForm; @Input() submission: any = {}; @Input() src: string; @Input() url: string; @Input() service: FormioService; @Input() options: FormioOptions; @Input() readOnly: boolean = false; @Input() hideComponents: string[]; @Input() refresh: EventEmitter<FormioRefreshValue>; @Input() error: EventEmitter<any>; @Input() success: EventEmitter<object>; @Output() render: EventEmitter<object>; @Output() customEvent: EventEmitter<object>; @Output() submit: EventEmitter<object>; @Output() prevPage: EventEmitter<object>; @Output() nextPage: EventEmitter<object>; @Output() beforeSubmit: EventEmitter<object>; @Output() change: EventEmitter<object>; @Output() invalid: EventEmitter<boolean>; @Output() errorChange: EventEmitter<any>; @Output() formLoad: EventEmitter<any>; @ViewChild('formio') formioElement:ElementRef; private formio: any; private initialized: boolean; constructor( private loader: FormioLoader, private alerts: FormioAlerts, @Optional() private config: FormioAppConfig ) { if (this.config) { Formio.Formio.setBaseUrl(this.config.apiUrl); Formio.Formio.setAppUrl(this.config.appUrl); } else { console.warn('You must provide an AppConfig within your application!'); } this.ready = new Promise((resolve: any) => { this.readyResolve = resolve; }); this.beforeSubmit = new EventEmitter(); this.prevPage = new EventEmitter(); this.nextPage = new EventEmitter(); this.submit = new EventEmitter(); this.errorChange = new EventEmitter(); this.invalid = new EventEmitter(); this.change = new EventEmitter(); this.customEvent = new EventEmitter(); this.render = new EventEmitter(); this.formLoad = new EventEmitter(); this.initialized = false; this.alerts.alerts = []; } setForm(form: FormioForm) { this.form = form; // Only initialize a single formio instance. if (this.formio) { this.formio.form = this.form; return; } // Create the form. return Formio.Formio.createForm(this.formioElement.nativeElement, this.form, { noAlerts: true, readOnly: this.readOnly, i18n: this.options.i18n }).then((formio: any) => { this.formio = formio; if (this.url) { this.formio.url = this.url; } if (this.src) { this.formio.url = this.src; } this.formio.nosubmit = true; this.formio.on('prevPage', (data: any) => this.onPrevPage(data)); this.formio.on('nextPage', (data: any) => this.onNextPage(data)); this.formio.on('change', (value: any) => this.change.emit(value)); this.formio.on('customEvent', (event: any) => this.customEvent.emit(event)); this.formio.on('submit', (submission: any) => this.submitForm(submission)); this.formio.on('error', (err: any) => this.onError(err)); this.formio.on('render', () => this.render.emit()); this.formio.on('formLoad', (loadedForm: any) => this.formLoad.emit(loadedForm)); this.loader.loading = false; this.readyResolve(); }); } initialize() { if (this.initialized) { return; } this.options = Object.assign({ errors: { message: 'Please fix the following errors before submitting.' }, alerts: { submitMessage: 'Submission Complete.' }, hooks: { beforeSubmit: null } }, this.options); this.initialized = true; } ngOnInit() { this.initialize(); if (this.refresh) { this.refresh.subscribe((refresh: FormioRefreshValue) => this.onRefresh(refresh)); } if (this.error) { this.error.subscribe((err: any) => this.onError(err)) } if (this.success) { this.success.subscribe((message: string) => { this.alerts.setAlert({ type: 'success', message: message || this.options.alerts.submitMessage }); }); } if (this.src) { if (!this.service) { this.service = new FormioService(this.src); } this.loader.loading = true; this.service.loadForm().subscribe((form: FormioForm) => { if (form && form.components) { this.setForm(form); } // if a submission is also provided. if (!this.submission && this.service.formio.submissionId) { this.service.loadSubmission().subscribe((submission: any) => { this.submission = this.formio.submission = submission; }, (err) => this.onError(err)); } }, (err) => this.onError(err)); } } onRefresh(refresh: FormioRefreshValue) { switch (refresh.property) { case 'submission': this.formio.submission = refresh.value; break; case 'form': this.formio.form = refresh.value; break; } } ngOnChanges(changes: any) { this.initialize(); if (changes.form && changes.form.currentValue) { this.setForm(changes.form.currentValue); } this.ready.then(() => { if (changes.submission && changes.submission.currentValue) { this.formio.submission = changes.submission.currentValue; } if (changes.hideComponents) { this.formio.hideComponents(changes.hideComponents.currentValue); } }); } onPrevPage(data: any) { this.alerts.setAlerts([]); this.prevPage.emit(data) } onNextPage(data: any) { this.alerts.setAlerts([]); this.nextPage.emit(data) } onSubmit(submission: any, saved: boolean) { if (saved) { this.formio.emit('submitDone', submission); } this.submit.emit(submission); if (!this.success) { this.alerts.setAlert({ type: 'success', message: this.options.alerts.submitMessage }); } } onError(err: any) { this.alerts.setAlerts([]); if (!err) { return; } // Make sure it is an array. err = (err instanceof Array) ? err : [err]; // Emit these errors again. this.errorChange.emit(err); // Iterate through each one and set the alerts array. _each(err, (error: any) => { this.alerts.setAlert({ type: 'danger', message: error.message || error.toString() }); }); } submitExecute(submission: object) { if (this.service) { this.service.saveSubmission(submission).subscribe( (sub: {}) => this.onSubmit(sub, true), (err) => this.onError(err) ); } else { this.onSubmit(submission, false); } } submitForm(submission: any) { this.beforeSubmit.emit(submission); // if they provide a beforeSubmit hook, then allow them to alter the submission asynchronously // or even provide a custom Error method. if (this.options.hooks.beforeSubmit) { this.options.hooks.beforeSubmit(submission, (err: FormioError, sub: object) => { if (err) { this.onError(err); return; } this.submitExecute(sub); }); } else { this.submitExecute(submission); } } }