angular-formio
Version:
The Form.io dynamic form and data management system for Angular.
202 lines (178 loc) • 7.19 kB
text/typescript
import { EventEmitter, Injectable, Optional } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { FormioResourceConfig } from './resource.config';
import { FormioResources, FormioResourceMap } from './resources.service';
import { FormioLoader, FormioAppConfig } from '../index';
import { FormioRefreshValue } from '../formio.common';
/* tslint:disable */
let Promise = require('native-promise-only');
let Formio = require('formiojs');
let FormioUtils = require('formiojs/utils');
/* tslint:enable */
export class FormioResourceService {
public form: any;
public resource: any;
public resourceUrl: string;
public formUrl: string;
public formFormio: any;
public formio: any;
public onParents: EventEmitter<object[]>;
public onIndexSelect: EventEmitter<object>;
public refresh: EventEmitter<FormioRefreshValue>;
public resourceLoading: Promise<any>;
public resourceLoaded: Promise<any>;
public resourceResolve: any;
public resourceReject: any;
public resourceId: string;
public formLoading: Promise<any>;
public formLoaded: Promise<any>;
public formResolve: any;
public formReject: any;
public resources: FormioResourceMap;
constructor(
public appConfig: FormioAppConfig,
public config: FormioResourceConfig,
public loader: FormioLoader,
public resourcesService: FormioResources
) {
if (this.appConfig && this.appConfig.appUrl) {
Formio.setBaseUrl(this.appConfig.apiUrl);
Formio.setAppUrl(this.appConfig.appUrl);
Formio.formOnly = this.appConfig.formOnly;
}
else {
console.error('You must provide an AppConfig within your application!');
}
// Create the form url and load the resources.
this.formUrl = this.appConfig.appUrl + '/' + this.config.form;
this.initialize();
}
initialize() {
this.onParents = new EventEmitter();
this.onIndexSelect = new EventEmitter();
this.refresh = new EventEmitter();
this.resource = {data: {}};
this.resourceLoaded = new Promise((resolve: any, reject: any) => {
this.resourceResolve = resolve;
this.resourceReject = reject;
});
this.formLoaded = new Promise((resolve: any, reject: any) => {
this.formResolve = resolve;
this.formReject = reject;
});
// Add this resource service to the list of all resources in context.
if (this.resourcesService) {
this.resourcesService.resources[this.config.name] = this;
this.resources = this.resourcesService.resources;
}
this.loadForm();
this.setParents();
}
onError(error: any) {
if (this.resourcesService) {
this.resourcesService.error.emit(error);
}
throw error;
}
onFormError(err: any) {
this.formReject(err);
this.onError(err);
}
loadForm() {
if (this.formLoading) {
return this.formLoading;
}
this.formFormio = (new Formio(this.formUrl));
this.loader.loading = true;
this.formLoading = this.formFormio.loadForm().then((form: any) => {
this.form = form;
this.formResolve(form);
this.loader.loading = false;
return form;
}, (err: any) => this.onFormError(err)).catch((err: any) => this.onFormError(err));
return this.formLoading;
}
setParents() {
if (!this.config.parents || !this.config.parents.length) {
return;
}
if (!this.resourcesService) {
console.warn('You must provide the FormioResources within your application to use nested resources.');
return;
}
// Iterate through the list of parents.
const parentsLoaded: Array<Promise<any>> = [];
this.config.parents.forEach((parent: string) => {
// See if this parent is already in context.
if (this.resources.hasOwnProperty(parent)) {
parentsLoaded.push(this.resources[parent].resourceLoaded.then((resource: any) => {
// Make sure we hide the component that is the parent.
this.formLoaded.then((form) => {
const component = FormioUtils.getComponent(form.components, parent);
if (component) {
component.hidden = true;
this.refresh.emit({
property: 'form',
value: form
});
}
});
if (!this.resourceLoading) {
// Set the value of this parent in the submission data.
this.resource.data[parent] = resource;
this.refresh.emit({
property: 'submission',
value: this.resource
});
return {
'name': parent,
'resource': resource
};
}
return null;
}));
}
});
// When all the parents have loaded, emit that to the onParents emitter.
Promise.all(parentsLoaded).then((parents: any) => this.onParents.emit(parents));
}
onSubmissionError(err: any) {
this.resourceReject(err);
this.onError(err);
}
loadResource(route: ActivatedRoute) {
// Reuse the same loading promise if the params are the same.
if (
this.resourceLoading &&
(route.snapshot.params['id'] === this.resourceId)
) {
return this.resourceLoading;
}
this.resourceId = route.snapshot.params['id'];
this.resource = {data: {}};
this.resourceUrl = this.appConfig.appUrl + '/' + this.config.form;
this.resourceUrl += '/submission/' + this.resourceId;
this.formio = (new Formio(this.resourceUrl));
this.loader.loading = true;
this.resourceLoading = this.formio.loadSubmission().then((resource: any) => {
this.resource = resource;
this.resourceResolve(resource);
this.loader.loading = false;
return resource;
}, (err: any) => this.onSubmissionError(err)).catch((err: any) => this.onSubmissionError(err));
return this.resourceLoading;
}
save(resource:any) {
const formio = resource._id ? this.formio : this.formFormio;
return formio.saveSubmission(resource).then((saved: any) => {
this.resource = saved;
return saved;
}, (err: any) => this.onError(err)).catch((err: any) => this.onError(err));
}
remove() {
return this.formio.deleteSubmission().then(() => {
this.resource = null;
}, (err: any) => this.onError(err)).catch((err: any) => this.onError(err));
}
}