0.0.8 • Published 5 years ago

@zodiac-ui/formula v0.0.8

Weekly downloads
-
License
MIT
Repository
-
Last release
5 years ago

@zodiac-ui/formula

Formula is a powerful form generator built for Angular. Inspired by Angular Router, Formula provides a declarative interface for building reactive forms.

Early adopters

Formula is in early development. Don't use this in production.

At A Glance

With Formula you start with the value you want to model...

const value = [
    {
        name: "Bob",
        dob: "1988-01-01",
        favouriteFood: "APPLE_PIE",
        notes: "..."
    },
    ...
]

...and craft a formula that models your value

const formula = users(user(name, age, notes, dob, favouriteFood))

Then you just hook it up to a component

@Component({
    selector: "z-root",
    template: `
        <z-formula [formula]="formula" [value]="value"></z-formula>
    `,
    styleUrls: ["./app.component.scss"],
})
export class AppComponent {
    public formula = formula
    public value = value
}

The result

If you'd like to learn more, read on or check out the example.

Features

Formula aims to achieve feature symmetry with the Route interface from @angular/router and FormBuilder from @angular/forms.

  • Builder (in progress): A convenient utility for generating Formula objects
  • Renderer (in progress): Automatically synchronises the UI based on the current formula and value
  • FormArray (in progress): Automatically populate array controls based on the current value and expose api for adding, moving or removing controls
  • Guards (not supported yet): Contextually control whether a form node can be loaded, activated or deactivated
  • Resolve (not supported yet): Contextually fetch remote or async data (eg. populating select options based on the current user)
  • LoadChildren (not supported yet): To allow for code splitting/lazy loading
  • StyleGuide (in progress): A common convention for declaring readable, composible, maintainable forms
  • Themes (in progress): Apply different styles to the same form by targeting classes exposed by each form element
  • FormContainer (in progress): Formula provides a container type useful for adding nodes that do not need a model (eg. a submit button)
  • Smart Validators (not supported yet): In addition to the usual validator options, Formula will also support validator class tokens that will be instantiated with the Angular injector.
  • Computed Fields (in progress): A method for creating one-way or two-way computed fields that react to changes in the form model
  • Material (in progress): A support library that wraps Angular Material

FormulaBuilder

Formula provides a form builder to construct Formula objects that are used to render forms.

API

MemberDescription
group: FormulaBuildFn<FormulaGroup>Creates a factory for FormulaType.GROUP nodes
array: FormulaBuildFn<FormulaArray>Creates a factory for FormulaType.ARRAY nodes
control: FormulaBuildFn<FormulaControl>Creates a factory for FormulaType.CONTROL nodes
container: FormulaBuildFn<FormulaContainer>Creates a factory for FormulaType.CONTAINER nodes

Usage

Use FormulaBuilder to functionally create and compose various form elements together.

const fb = new FormBuilder()

export const form = (name: string) =>
    fb.group({
        name,
        component: FormContainerComponent,
    })

export const text = (name: string, label: string) =>
    fb.control({
        name,
        component: TextFieldComponent,
        data: {
            label,
        },
    })

export const formula: Formula = form("user")(
    text("firstName", "First Name"),
    text("lastName", "First Name"),
)

FormulaDirective

Creates a FormulaNode tree that is used to render a form. FormulaDirective provides a declarative approach for dynamic forms creation FormulaDirective requires a Formula, if a falsy value is set the view will clear and the form will get destroyed.

API

Formula is under active development. The current API is experimental and likely to change before release.

MemberDescription
@Input() formula: FormulaThe formula to be rendered. See Formula for options.
@Input() value: anyForm value setter. Unknown object keys are discarded.
@Output() valueChanges: EventEmitter<any>Forwards valueChanges from AbstractControl.
@Output() statusChanges: EventEmitter<any>Forwards statusChanges from AbstractControl.
@Output() submit: EventEmitter<any>Forwards submit events from a registered NgForm.
setForm(form: NgForm): voidRegisters a NgForm with the outlet.
setValue(value: any): voidImmediately patches the value of the form

Usage

The simplest case is a formula with a single field.

@Component({
    selector: "z-example",
    template: `
        <z-formula [formula]="formula" [value]="value"></z-formula>
    `,
})
export class ExampleComponent {
    value = {
        exampleText: null,
    }

    formula: Formula

    constructor(fb: FormulaBuilder) {
        this.formula = fb.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:

@Component({
    selector: "z-text-field",
    template: `
        <label [innerHTML]="ctx.data.label"></label> <input [formControl]="ctx.model" />
    `,
})
export class TextFieldComponent {
    constructor(public ctx: FormulaContext) {}
}

Each component in the tree receives a FormulaContext containing the model, data and resolve data.

Important note: Formula components are rendered dynamically. You may encounter errors about missing ComponentFactory or unknown Provider. Ensure all components are marked as entry components and that all providers are provided in the NgModule the form gets rendered in.

FormulaOutlet

Renders the current FormulaNode in the node tree. It is functionally similar to router-outlet; use this directive inside Formula components to render children of the current node.

Usage

Anywhere in your Formula component template, place a single z-formula-outlet tag.

@Component({
    selector: "z-form-container",
    template: `
        <z-form> <z-formula-outlet></z-formula-outlet> </z-form>
    `,
})
export class FormContainerComponent {}

FormComponent

Selectors: <z-form>

A basic wrapper for NgForm that forwards native submit events to the root FormulaOutlet. If nested inside another FormComponent, renders <ng-form> instead of <form>. Will throw an error if not used with FormulaGroup or FormulaArray

Usage

See Formula Outlet

0.0.8

5 years ago

0.0.4

5 years ago

0.0.3

5 years ago

0.0.2

5 years ago

0.0.1

5 years ago