123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- /* *********************************************************************************************************************
- * Dynaform Service, exposing 10 public methods
- * *********************************************************************************************************************
- *
- * BUILD
- * -----
- * This is the main method you'll use to build forms from models and metadata:
- *
- * build(model, meta = {}, createFromMeta = false)
- *
- * Takes a model and (lazy)metadata and returns an object containing a FormGroup and Modeled MetaData :
- * {
- * form: FormGroup,
- * meta: ModeledMetaData
- * }
- *
- * meta is optional, and if not supplied all the model fields will become Text inputs in the FormGroup,
- * with their labels set to the un-camel-cased property name
- *
- * createFromMeta is optional.
- * If true it will create new fields in the FormGroup even when they don't already exist in the model,
- * but exist in the metadata. This is NOT the default behaviour, except when an empty model is supplied.
- * i.e. It defaults to false, except when model == {}
- *
- * Usage
- * -----
- *
- * build(model) - build everything from the model
- * build({}, meta) - build everything from the metadata
- * build(model, meta) - build by combining the model with metadata, lazyily (not every model field needs metadata, as sensible defaults)
- * build(model, meta, true) - build by combining model with metadata, creating new fields from metadata points that don't occur in the model
- *
- *
- * REGISTER
- * --------
- * Registers callbacks attached to the form (e.g. to buttons), identified by strings.
- *
- * register({
- * 'SAYHELLO': () => { alert('HELLO') },
- * 'SEARCH': execSearch,
- * 'NEW': addNew,
- * }, varToBind);
- *
- * If varToBind is supplied it is bound as 'this' to the functions.
- * Typically you'd supply the component class instance, so that 'this' used in callbacks refers to the host component.
- *
- *
- * LOWER-LEVEL METHODS
- * -------------------
- *
- * autoBuildFormGroupAndMeta(model, meta, createFromMeta) - synonym for build
- * autoBuildModeledMeta(model, meta, createFromMeta) - takes a model and (lazy)metadata and returns expanded metadata
- *
- * buildFormGroup(metadata) - builds FormGroups from modelled metdata, recursively if necessary
- * buildFieldSpecificMeta(metadata) - use field metadta models to fill out metadata
- * combineModelWithMeta(model, extraMeta) - automatically generated metadata for model then combines extra metadata
- * combineExtraMeta(metadata, extraMeta) - combine extra metadata into metatdata, lazyly and recursively
- * autoMeta(model) - generate basic metadata from a raw or mapped model, recursively if necessary
- *
- *
- * NOTES
- * -----
- * This class acts as an injectable wraper around the exports of _formdata-utils.ts,
- * as well as creating a buildFormGroup function using the injected FormBuilder singleton
- *
- *
- * EXAMPLES
- * --------
- *
- * TO ADD ...
- *
- */
- import { Injectable, ComponentRef } from '@angular/core';
- import { FormBuilder, FormGroup } from '@angular/forms';
- import {
- autoMeta, combineModelWithMeta, combineExtraMeta,
- buildFieldSpecificMeta, buildFormGroupFunctionFactory
- } from './_formdata-utils';
- export interface FormAndMeta {
- form: FormGroup;
- meta: StringMap;
- }
- export interface Callbacks {
- [index: string]: () => void
- }
- @Injectable()
- export class DynaformService {
- public buildFormGroup: (meta) => FormGroup;
- private callbacks: Callbacks = {};
- constructor(private fb: FormBuilder) {
- this.buildFormGroup = buildFormGroupFunctionFactory(fb);
- }
- build(model: StringMap, meta = {}, createFromMeta = false): FormAndMeta {
- // Short name for autoBuildFormGroupAndMeta
- return this.autoBuildFormGroupAndMeta(model, meta, createFromMeta);
- }
- register(callbacks: Callbacks, cref: ComponentRef<any>['instance']) {
- // Bind the component instance to the callback, so that 'this' has the context of the component
- if (cref) {
- Object.entries(callbacks).forEach(([key, fn]) => this.callbacks[key] = fn.bind(cref));
- }
- }
-
- call(fnId: string) {
- console.log('Dynaform Service', fnId);
- // Handle callback events
- try {
- this.callbacks[fnId]();
- }
- catch(e) {
- console.error('Dynaform has no registered callback for', fnId);
- console.error(e);
- }
- }
- // -----------------------------------------------------------------------------------------------------------------
- // Convenience methods combining several steps
- autoBuildFormGroupAndMeta(model: StringMap, meta = {}, createFromMeta = false): FormAndMeta {
- if (Object.keys(model).length === 0) {
- createFromMeta = true;
- }
- const modelWithMeta = this.autoBuildModeledMeta(model, meta, createFromMeta);
- return {
- form: this.buildFormGroup(modelWithMeta),
- meta: modelWithMeta
- };
- }
- autoBuildModeledMeta(model: StringMap, meta = {}, createFromMeta = false) {
- const modelWithMeta = this.combineModelWithMeta(model, meta, createFromMeta);
- return this.buildFieldSpecificMeta(modelWithMeta);
- }
- // -----------------------------------------------------------------------------------------------------------------
- // Build field-type-specific metadata using the form field models (see dynaform/models)
- buildFieldSpecificMeta(meta) {
- return buildFieldSpecificMeta(meta);
- }
- // -----------------------------------------------------------------------------------------------------------------
- // Lower-level methods
- combineModelWithMeta(model: StringMap, meta, createFromMeta = false) {
- return combineModelWithMeta(model, meta, createFromMeta);
- }
- combineExtraMeta(meta, extraMeta, createFromExtra = false) {
- return combineExtraMeta(meta, extraMeta, createFromExtra);
- }
- autoMeta(model) {
- return autoMeta(model);
- }
- }
|