@zodiac-ui/formula
Version:
Formula is a powerful form generator built for Angular. Inspired by Angular Router, Formula provides a declarative interface for building reactive forms.
1,161 lines (1,145 loc) • 33.9 kB
JavaScript
import { Subject } from 'rxjs';
import { startWith, takeUntil } from 'rxjs/operators';
import { InjectionToken, ComponentFactoryResolver, Injector, IterableDiffers, KeyValueDiffers, Renderer2, ViewContainerRef, Directive, EventEmitter, Inject, Input, Optional, Output, SkipSelf, NgModule, ChangeDetectionStrategy, Component, ViewChild } from '@angular/core';
import { FormArray, FormControl, FormGroup, ReactiveFormsModule, NgForm, FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @enum {number} */
const FormulaType = {
CONTROL: 0,
GROUP: 1,
ARRAY: 2,
CONTAINER: 3,
};
FormulaType[FormulaType.CONTROL] = 'CONTROL';
FormulaType[FormulaType.GROUP] = 'GROUP';
FormulaType[FormulaType.ARRAY] = 'ARRAY';
FormulaType[FormulaType.CONTAINER] = 'CONTAINER';
/**
* @abstract
*/
class FormulaContext {
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
const FORMULA = new InjectionToken("FORMULA");
/** @type {?} */
const FORMULA_DIFFER = new InjectionToken("FORMULA_DIFFER");
/** @type {?} */
const FORMULA_OUTLET = new InjectionToken("FORMULA_OUTLET");
/** @type {?} */
const FORMULA_NODE = new InjectionToken("FORMULA_NODE");
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @abstract
*/
class FormulaRenderer {
/**
* @param {?} vcr
* @param {?} cfr
* @param {?} injector
*/
constructor(vcr, cfr, injector) {
this.vcr = vcr;
this.cfr = cfr;
this.injector = injector;
this.refs = new Map();
this.renderer = injector.get(Renderer2);
this.destroyed$ = new Subject();
this.destroyed = false;
}
/**
* @param {?} node
* @return {?}
*/
render(node) {
/** @type {?} */
const parent = this.injector.get(FORMULA_NODE, null);
/** @type {?} */
const resolve = node.formula.resolve;
/** @type {?} */
const resolvers = resolve
? Object.getOwnPropertySymbols(resolve)
.map((key) => ({
key: key,
token: resolve[key],
}))
.concat(Object.values(resolve).map((key) => ({
key: key,
token: resolve[key],
})))
: [];
/** @type {?} */
const context = {
model: node.model,
data: node.formula.data,
resolve: {},
};
/** @type {?} */
const injector = Injector.create({
parent: this.injector,
providers: [
{
provide: FormulaContext,
useValue: context,
},
{
provide: FORMULA_NODE,
useValue: node,
},
],
});
/** @type {?} */
const resolveData = (/** @type {?} */ ({}));
if (resolve) {
resolvers.forEach(ref => {
/** @type {?} */
const resolver = injector.get(ref.token);
resolveData[ref.key] = resolver.resolve(context);
});
}
if (node.formula.component && node !== parent) {
/** @type {?} */
const factory = this.cfr.resolveComponentFactory(node.formula.component);
/** @type {?} */
const component = this.vcr.createComponent(factory, null, injector);
if (node.formula.class) {
node.formula.class
.split(" ")
.forEach(className => this.renderer.addClass(component.location.nativeElement, className));
}
this.refs.set(node, component);
}
else if (node.children) {
node.children.forEach(childNode => {
/** @type {?} */
const renderer = createRenderer(childNode.formula, injector);
renderer.render(childNode);
});
}
}
/**
* @return {?}
*/
destroy() {
if (this.destroyed) {
throw new Error(`FormulaRenderer was already destroyed.`);
}
this.refs.forEach(ref => {
ref.destroy();
});
this.destroyed$.next();
this.destroyed$.complete();
this.destroyed = true;
}
}
class FormulaArrayRenderer extends FormulaRenderer {
/**
* @param {?} vcr
* @param {?} cfr
* @param {?} injector
* @param {?} differs
*/
constructor(vcr, cfr, injector, differs) {
super(vcr, cfr, injector);
this.differ = differs.find([]).create();
}
/**
* @param {?} node
* @return {?}
*/
addChild(node) {
/** @type {?} */
const renderer = createRenderer(node.formula, this.injector);
renderer.render(node);
this.refs.set(node, renderer.refs.get(node));
}
/**
* @param {?} node
* @param {?} index
* @return {?}
*/
moveChild(node, index) {
/** @type {?} */
const child = this.refs.get(node);
this.vcr.move(child.hostView, index);
}
/**
* @param {?} node
* @return {?}
*/
removeChild(node) {
/** @type {?} */
const child = this.refs.get(node);
child.destroy();
this.refs.delete(node);
}
/**
* @param {?} node
* @return {?}
*/
render(node) {
/** @type {?} */
const parent = this.injector.get(FORMULA_NODE, null);
/** @type {?} */
const injector = Injector.create({
parent: this.injector,
providers: [
{
provide: FormulaContext,
useValue: {
model: node.model,
data: node.formula.data,
resolve: {},
},
},
{
provide: FORMULA,
useValue: node.formula,
},
{
provide: FORMULA_NODE,
useValue: node,
},
],
});
if (node.formula.component && node !== parent) {
/** @type {?} */
const factory = this.cfr.resolveComponentFactory(node.formula.component);
/** @type {?} */
const component = this.vcr.createComponent(factory, null, injector);
if (node.formula.class) {
node.formula.class
.split(" ")
.forEach(className => this.renderer.addClass(component.location.nativeElement, className));
}
this.refs.set(node, component);
}
else {
node.model.valueChanges.pipe(startWith(null)).subscribe(() => {
/** @type {?} */
const diff = this.differ.diff(node.children);
if (diff) {
diff.forEachRemovedItem(record => {
this.removeChild(record.item);
});
diff.forEachMovedItem(record => {
this.moveChild(record.item, record.currentIndex);
});
diff.forEachAddedItem(record => {
this.addChild(record.item);
});
}
});
}
}
}
class FormulaGroupRenderer extends FormulaRenderer {
/**
* @param {?} vcr
* @param {?} cfr
* @param {?} injector
* @param {?} differs
*/
constructor(vcr, cfr, injector, differs) {
super(vcr, cfr, injector);
this.differ = differs.find({}).create();
}
}
class FormulaContainerRenderer extends FormulaRenderer {
/**
* @param {?} vcr
* @param {?} cfr
* @param {?} injector
*/
constructor(vcr, cfr, injector) {
super(vcr, cfr, injector);
this.differ = null;
}
/**
* @param {?} node
* @return {?}
*/
render(node) {
/** @type {?} */
const parent = this.injector.get(FORMULA_NODE, null);
/** @type {?} */
const injector = Injector.create({
parent: this.injector,
providers: [
{
provide: FormulaContext,
useValue: {
model: node.model,
data: node.formula.data,
resolve: {},
},
},
{
provide: FORMULA_NODE,
useValue: node,
},
],
});
if (node.formula.component && node !== parent) {
/** @type {?} */
const factory = this.cfr.resolveComponentFactory(node.formula.component);
/** @type {?} */
const component = this.vcr.createComponent(factory, null, injector);
if (node.formula.class) {
node.formula.class
.split(" ")
.forEach(className => this.renderer.addClass(component.location.nativeElement, className));
}
this.refs.set(node, component);
}
else {
node.children.forEach(childNode => {
/** @type {?} */
const renderer = createRenderer(childNode.formula, injector);
renderer.render(childNode);
});
}
}
}
class FormulaDefaultRenderer extends FormulaRenderer {
/**
* @param {?} vcr
* @param {?} cfr
* @param {?} injector
*/
constructor(vcr, cfr, injector) {
super(vcr, cfr, injector);
this.differ = null;
}
}
/**
* @param {?} formula
* @return {?}
*/
function provideRenderer(formula) {
/** @type {?} */
const deps = [ViewContainerRef, ComponentFactoryResolver, Injector, FORMULA_DIFFER];
switch (formula.type) {
case FormulaType.GROUP: {
return {
provide: FormulaGroupRenderer,
useClass: FormulaGroupRenderer,
deps: deps,
};
}
case FormulaType.ARRAY: {
return {
provide: FormulaArrayRenderer,
useClass: FormulaArrayRenderer,
deps: deps,
};
}
case FormulaType.CONTAINER: {
return {
provide: FormulaContainerRenderer,
useClass: FormulaContainerRenderer,
deps: deps,
};
}
default: {
return {
provide: FormulaDefaultRenderer,
useClass: FormulaDefaultRenderer,
deps: deps,
};
}
}
}
/**
* @param {?} formula
* @param {?} injector
* @return {?}
*/
function provideDiffer(formula, injector) {
if (formula.type === FormulaType.ARRAY) {
return {
provide: FORMULA_DIFFER,
useValue: injector.get(IterableDiffers),
};
}
if (formula.type === FormulaType.GROUP) {
return {
provide: FORMULA_DIFFER,
useValue: injector.get(KeyValueDiffers),
};
}
return {
provide: FORMULA_DIFFER,
useValue: null,
};
}
/**
* @param {?} formula
* @param {?} parentInjector
* @return {?}
*/
function createRenderer(formula, parentInjector) {
/** @type {?} */
const DIFFER = provideDiffer(formula, parentInjector);
/** @type {?} */
const RENDERER = provideRenderer(formula);
/** @type {?} */
const injector = Injector.create({
parent: parentInjector,
providers: [
RENDERER,
DIFFER,
{
provide: FORMULA,
useValue: formula,
},
],
});
if (formula.type === FormulaType.ARRAY) {
return injector.get(FormulaArrayRenderer);
}
if (formula.type === FormulaType.GROUP) {
return injector.get(FormulaGroupRenderer);
}
if (formula.type === FormulaType.CONTAINER) {
return injector.get(FormulaContainerRenderer);
}
return injector.get(FormulaDefaultRenderer);
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @param {?} model
* @return {?}
*/
function isFormArray(model) {
return model && model["removeAt"];
}
/**
* @param {?} model
* @return {?}
*/
function isFormGroup(model) {
return model && model["removeControl"];
}
/**
* @param {?} model
* @return {?}
*/
function isFormControl(model) {
return model && !isFormGroup(model) && !isFormArray(model);
}
/**
* @param {?} formula
* @param {?} parent
* @param {?} control
* @return {?}
*/
function setParentControl(formula, parent, control) {
control.setParent(parent);
if (isFormArray(parent)) {
parent.push(control);
}
if (isFormGroup(parent)) {
parent.setControl(formula.name, control);
}
}
/**
* @param {?} formula
* @param {?} parent
* @return {?}
*/
function createModel(formula, parent) {
/** @type {?} */
let model;
if (isFormControl(parent)) {
return parent;
}
switch (formula.type) {
case FormulaType.CONTROL: {
model = new FormControl();
break;
}
case FormulaType.GROUP: {
model = new FormGroup({});
break;
}
case FormulaType.ARRAY: {
model = new FormArray([]);
break;
}
default: {
return parent;
}
}
if (isFormGroup(parent) || isFormArray(parent)) {
setParentControl(formula, parent, model);
}
return model;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @abstract
*/
class FormulaNode {
}
class FormulaArrayNode {
/**
* @param {?} formula
* @param {?} model
* @param {?} parent
* @param {?} children
*/
constructor(formula, model, parent, children) {
this.parent = parent;
this.model = model;
this.formula = formula;
this.children = children;
}
/**
* @param {?} values
* @return {?}
*/
setValue(values) {
/** @type {?} */
const len = this.model.controls.length;
values.forEach((value, index) => {
if (index < len) {
this.children[index].setValue(value);
}
else {
/** @type {?} */
const formula = this.formula.children[index % this.formula.children.length];
/** @type {?} */
const model = createModel(formula, this.model);
/** @type {?} */
const node = createFormulaNode(formula, model, this);
node.setValue(value);
this.children.push(node);
}
});
/** @type {?} */
const valLen = values.length;
this.children.forEach((child, index) => {
if (index >= valLen) {
this.model.removeAt(index);
}
});
}
}
class FormulaControlNode {
/**
* @param {?} formula
* @param {?} model
* @param {?} parent
*/
constructor(formula, model, parent) {
this.formula = formula;
this.model = model;
this.parent = parent;
this.children = null;
}
/**
* @param {?} value
* @return {?}
*/
setValue(value) {
this.model.setValue(value);
}
}
class FormulaContainerNode {
/**
* @param {?} formula
* @param {?} model
* @param {?} parent
* @param {?} children
*/
constructor(formula, model, parent, children) {
this.parent = parent;
this.model = model;
this.formula = formula;
this.children = children;
if (!parent) {
throw new Error("Containers can not be used as a root node");
}
if (children.length > 1) {
throw new Error(`Containers can only have one child`);
}
}
/**
* @param {?} value
* @return {?}
*/
setValue(value) {
if (this.children) {
this.children[0].setValue(value);
}
}
}
class FormulaGroupNode {
/**
* @param {?} formula
* @param {?} model
* @param {?} parent
* @param {?} children
*/
constructor(formula, model, parent, children) {
this.parent = parent;
this.model = model;
this.formula = formula;
this.children = children;
}
/**
* @param {?} value
* @return {?}
*/
setValue(value) {
this.children.forEach(child => {
child.setValue(value[child.formula.name]);
});
}
}
/**
* @param {?} formula
* @param {?} model
* @param {?} parent
* @param {?} children
* @return {?}
*/
function createGroupNode(formula, model, parent, children) {
return new FormulaGroupNode(formula, model, parent, children);
}
/**
* @param {?} formula
* @param {?} model
* @param {?} parent
* @return {?}
*/
function createControlNode(formula, model, parent) {
return new FormulaControlNode(formula, model, parent);
}
/**
* @param {?} formula
* @param {?} model
* @param {?} parent
* @param {?} children
* @return {?}
*/
function createArrayNode(formula, model, parent, children) {
return new FormulaArrayNode(formula, model, parent, children);
}
/**
* @param {?} formula
* @param {?} model
* @param {?} parent
* @param {?} children
* @return {?}
*/
function createContainerNode(formula, model, parent, children) {
return new FormulaContainerNode(formula, model, parent, children);
}
/**
* @param {?} formula
* @param {?} model
* @param {?} parent
* @return {?}
*/
function createFormulaNode(formula, model, parent) {
/** @type {?} */
let children = [];
switch (formula.type) {
case FormulaType.CONTROL: {
return createControlNode(formula, model, parent);
}
case FormulaType.GROUP: {
children = formula.children.map(childFormula => {
/** @type {?} */
const childModel = createModel(childFormula, model);
return createFormulaNode(childFormula, childModel, parent);
});
return createGroupNode(formula, model, parent, children);
}
case FormulaType.ARRAY: {
return createArrayNode(formula, model, parent, children);
}
default: {
children = formula.children.map(childFormula => {
/** @type {?} */
const childModel = createModel(childFormula, model);
return createFormulaNode(childFormula, childModel, parent);
});
return createContainerNode(formula, model, parent, children);
}
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Creates a {link FormulaNode} tree that is used to render a form. `FormulaDirective` provides a declarative
* approach for dynamic forms creation
*
* `FormulaDirective` requires a {link Formula}, if a falsy value is set the view will clear and the
* form will get destroyed.
*
* ### Usage
*
* The simplest case is a formula with a single field.
*
* ```ts
* \@Component({
* selector: "z-example",
* template: `
* <z-formula [formula]="formula" [value]="value"></z-formula>
* `,
* })
* export class ExampleComponent {
* value = {
* exampleText: null
* }
* formula: Formula = {
* type: FormulaType.CONTROL,
* name: "exampleText",
* component: TextFieldComponent,
* data: {
* label: "Example Text",
* placeholder: "Type text here"
* },
* }
* }
* ```
*
* In this example we are declaring a `formula` that contains a single form control called
* `exampleText`. It is rendered with a component, which is up to the user to implement. The
* concept is similar to that of Angular route components. For example, the `TextFieldComponent`
* may be as simple as this:
*
* ```ts
* \@Component({
* selector: "z-text-field",
* template: `
* <label [innerHTML]="ctx.data.label"></label>
* <input [formControl]="ctx.model" />
* `,
* })
* export class TextFieldComponent {
* constructor(public ctx: FormulaContext) {}
* }
* ```
*
* Every Formula component receives a {link FormulaContext} containing the model, data and resolve
* data defined for that node in the `FormulaNode` tree
*
*/
class FormulaDirective {
/**
* @param {?} injector
* @param {?} vcr
* @param {?} parent
*/
constructor(injector, vcr, parent) {
this.valueChanges = new EventEmitter();
this.statusChanges = new EventEmitter();
this.submit = new EventEmitter();
this.injector = Injector.create({
parent: injector,
providers: [
{
provide: ViewContainerRef,
useValue: vcr,
},
],
});
this.parent = parent;
this.root = parent ? parent.root : this;
}
/**
* @param {?} changes
* @return {?}
*/
ngOnChanges(changes) {
if (changes.formula) {
if (!changes.formula.isFirstChange()) {
this.renderer.destroy();
}
if (this.formula) {
this.renderer = createRenderer(this.formula, this.injector);
this.render();
}
}
if (changes.value) {
this.setValue(this.value);
}
}
/**
* @return {?}
*/
ngOnDestroy() {
if (this.renderer) {
this.renderer.destroy();
}
}
/**
* @param {?} value
* @return {?}
*/
setValue(value) {
if (this.node) {
this.node.setValue(value);
}
}
/**
* @param {?} form
* @return {?}
*/
setForm(form) {
if (this.form) {
throw new Error("Only one top level NgForm is allowed");
}
this.form = form;
form.ngSubmit.subscribe(this.submit);
}
/**
* @private
* @return {?}
*/
render() {
this.model = createModel(this.formula, this.parent ? this.parent.node.model : null);
this.node = createFormulaNode(this.formula, this.model, this.parent ? this.parent.node : null);
this.renderer.render(this.node);
this.model.valueChanges
.pipe(takeUntil(this.renderer.destroyed$))
.subscribe(this.valueChanges);
this.model.statusChanges
.pipe(takeUntil(this.renderer.destroyed$))
.subscribe(this.statusChanges);
}
}
FormulaDirective.decorators = [
{ type: Directive, args: [{
selector: "z-formula, [zFormula]",
providers: [
{
provide: FORMULA_OUTLET,
useExisting: FormulaDirective,
},
],
},] }
];
/** @nocollapse */
FormulaDirective.ctorParameters = () => [
{ type: Injector },
{ type: ViewContainerRef },
{ type: undefined, decorators: [{ type: SkipSelf }, { type: Optional }, { type: Inject, args: [FORMULA_OUTLET,] }] }
];
FormulaDirective.propDecorators = {
formula: [{ type: Input }],
value: [{ type: Input }],
valueChanges: [{ type: Output }],
statusChanges: [{ type: Output }],
submit: [{ type: Output }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
const mapChildren = child => (typeof child === "function" ? child() : child);
/**
* @param {?} config
* @return {?}
*/
function group(config) {
return function (...children) {
return Object.assign({ type: FormulaType.GROUP, children: children.map(mapChildren) }, config, { data: config.data || {} });
};
}
/**
* @param {?=} config
* @return {?}
*/
function control(config) {
return function () {
return Object.assign({ type: FormulaType.CONTROL }, config, { data: config.data || {} });
};
}
/**
* @param {?} config
* @return {?}
*/
function array(config) {
return function (...children) {
return Object.assign({ type: FormulaType.ARRAY, children: children.map(mapChildren) }, config, { data: config.data || {} });
};
}
/**
* @param {?} config
* @return {?}
*/
function container(config) {
return function (...children) {
return Object.assign({ type: FormulaType.CONTAINER, children: children.map(mapChildren) }, config, { data: config.data || {} });
};
}
/**
* @template T
* @param {?} buildFn
* @param {?} opts
* @return {?}
*/
function extend(buildFn, opts) {
return function (...args) {
/** @type {?} */
const formula = buildFn(...args);
Object.getOwnPropertyNames(opts).forEach(key => {
/** @type {?} */
const source = formula[key];
/** @type {?} */
const value = opts[key];
if (Array.isArray(value)) {
formula[key] = [...source, ...value];
}
else if (typeof value === "object" && value !== null) {
formula[key] = Object.assign({}, source, value);
}
else {
formula[key] = value;
}
});
return formula;
};
}
class FormulaBuilder {
constructor() {
this.group = group;
this.array = array;
this.container = container;
this.control = control;
this.extend = extend;
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class FormulaModule {
}
FormulaModule.decorators = [
{ type: NgModule, args: [{
imports: [ReactiveFormsModule],
declarations: [FormulaDirective],
exports: [FormulaDirective],
providers: [FormulaBuilder],
},] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Renders the current {link FormulaNode} in the tree. Being functionally similar to `router-outlet`,
* use this directive inside Formula components to continue rendering child nodes of the current
* branch in the node tree.
*
* ### Usage
*
* Anywhere in your Formula component template, place a single `z-formula-outlet` tag.
*
* ```ts
* \@Component({
* selector: 'z-form-container',
* template: `
* <form>
* <z-formula-outlet></z-formula-outlet>
* </form>
* `,
* })
* export class FormContainerComponent {}
* ```
* f
* In many cases you probably want a native `form` element as the top level component in your form.
* This is a minimal way to achieve that. All child nodes will now be rendered between the `<form>`
* tags.
*/
class FormulaOutletDirective {
/**
* @param {?} injector
* @param {?} vcr
* @param {?} formula
* @param {?} node
* @param {?} parent
*/
constructor(injector, vcr, formula, node, parent) {
this.injector = Injector.create({
parent: injector,
providers: [
{
provide: ViewContainerRef,
useValue: vcr,
},
],
});
this.parent = parent;
this.root = parent.root;
this.node = node;
this.renderer = createRenderer(formula, injector);
}
/**
* @return {?}
*/
ngOnInit() {
this.render();
}
/**
* @return {?}
*/
ngOnDestroy() {
this.renderer.destroy();
}
/**
* @param {?} value
* @return {?}
*/
setValue(value) {
this.node.setValue(value);
}
/**
* @private
* @return {?}
*/
render() {
this.renderer.render(this.node);
}
}
FormulaOutletDirective.decorators = [
{ type: Directive, args: [{
selector: "z-formula-outlet, [zFormulaOutlet]",
providers: [
{
provide: FORMULA_OUTLET,
useExisting: FormulaOutletDirective,
},
],
},] }
];
/** @nocollapse */
FormulaOutletDirective.ctorParameters = () => [
{ type: Injector },
{ type: ViewContainerRef },
{ type: undefined, decorators: [{ type: Inject, args: [FORMULA,] }] },
{ type: FormulaNode, decorators: [{ type: Inject, args: [FORMULA_NODE,] }] },
{ type: undefined, decorators: [{ type: SkipSelf }, { type: Inject, args: [FORMULA_OUTLET,] }] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class FormulaOutletModule {
}
FormulaOutletModule.decorators = [
{ type: NgModule, args: [{
imports: [],
declarations: [FormulaOutletDirective],
exports: [FormulaOutletDirective],
},] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class FormComponent {
/**
* @param {?} ctx
* @param {?} outlet
* @param {?} parent
*/
constructor(ctx, outlet, parent) {
if (isFormGroup(ctx.model) || isFormArray(ctx.model)) {
this.model = ctx.model;
}
else {
throw new Error("<z-form> only accepts FormGroup or FormArray");
}
this.ngFormOptions = ctx.data.ngFormOptions || {};
this.outlet = outlet.root;
this.parent = parent;
}
/**
* @return {?}
*/
ngAfterViewInit() {
if (!this.parent) {
this.outlet.setForm(this.form);
}
}
}
FormComponent.decorators = [
{ type: Component, args: [{
selector: "z-form",
template: `
<ng-container *ngIf="parent; then: ngForm; else: form"></ng-container>
<ng-template #form>
<form [ngFormOptions]="ngFormOptions">
<ng-container [ngTemplateOutlet]="content"></ng-container>
</form>
</ng-template>
<ng-template #ngForm>
<ng-form [ngFormOptions]="ngFormOptions">
<ng-container [ngTemplateOutlet]="content"></ng-container>
</ng-form>
</ng-template>
<ng-template #content> <ng-content></ng-content> </ng-template>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
styles: [":host{display:block;width:100%}"]
}] }
];
/** @nocollapse */
FormComponent.ctorParameters = () => [
{ type: FormulaContext },
{ type: undefined, decorators: [{ type: Inject, args: [FORMULA_OUTLET,] }] },
{ type: FormComponent, decorators: [{ type: Optional }, { type: SkipSelf }] }
];
FormComponent.propDecorators = {
form: [{ type: ViewChild, args: [NgForm,] }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class FormModule {
}
FormModule.decorators = [
{ type: NgModule, args: [{
imports: [CommonModule, FormsModule],
declarations: [FormComponent],
entryComponents: [FormComponent],
exports: [FormComponent],
},] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
export { FormulaModule, FORMULA, FORMULA_DIFFER, FORMULA_OUTLET, FORMULA_NODE, FormulaDirective, FormulaType, FormulaContext, FormulaOutletModule, FormulaOutletDirective, FormModule, FormComponent, group, control, array, container, extend, FormulaBuilder, FormulaNode as ɵa };
//# sourceMappingURL=zodiac-ui-formula.js.map