npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ng-deco-forms

v1.0.1

Published

A forms library for Angular. Relying heavily on Angular's dependency injection mechanism makes this library incredibly flexible. Form fields are entirely described via Typescript decorators, making forms easier to maintain. Loosely inspired by Formly.

Downloads

44

Readme

Angular Decorated Forms

A forms library for Angular. Relying heavily on Angular's dependency injection mechanism makes this library incredibly flexible. Form fields are entirely described via Typescript decorators, making forms easier to maintain. Loosely inspired by Formly.

Table of contents

Basic Examples

Field Examples

Text Input


export class TextTypeComponent {

  constructor(@Inject(FIELD_FORM_CONTROL_TOKEN) public control: FormControl) {

    
  }
    
  
}
<input
  class="deco-text"
  type="text"
  [formControl]="control"
>

Number Input


export class NumberTypeComponent {

  
  constructor(@Inject(FIELD_FORM_CONTROL_TOKEN) public control: FormControl,
    @Optional() @Inject(FIELD_CONFIG_TOKEN) public config: NumberFieldConfig) {

  }
}
<input
  class="deco-number"
  type="number"
  [formControl]="control"
  [step]="config.step"
  [min]="config.min"
  [max]="config.max"
>

Label Wrapper

export class FieldLabelWrapperComponent {

  constructor(
    @Optional() @Inject(FIELD_CONFIG_TOKEN) public config: LabelConfig
  ) {

  }
}
<div class="deco-field-label">
  <div class="deco-field-label__label">
    <label
      *ngIf="config.label"
      class="deco-field-label__text"
    >{{ config.label }}</label>
  </div>

  <div class="deco-field-label__field">
    <ng-content></ng-content>
  </div>
</div>

Simple Usage

Create a field:


export const Text = () => DecoField(TextTypeComponent)

Or with config:


export const Number = (props?: NumberFieldConfig) => DecoField(NumberTypeComponent, props)

Create a form:


@Form()
class DemoForm {

    @Text()
    my_text = "Bla Bla"

    @Number({step: 2})
    my_number = 1
}

Render your form:


const demo = new DemoForm()

<ng-container [deco-form]="form"></ng-container>

Add Wrappers

Create a wrapper:


const LabelWrapper = Wrap(FieldLabelWrapperComponent)

Make a propertry for it:


const LabelProp = (label: string) => Prop(FieldLabelWrapperComponent, 'label', label)

Use it:


@Form()
class DemoForm {

    @LabelProp('Your Opinion')
    @LabelWrapper()
    @Text()
    my_text = "Bla Bla"

    @LabelProp('Your Contribution')
    @LabelWrapper()
    @Number({step: 2000})
    my_number = 1
}

Or chain them together:


const Label = (label: string) => chain([
  LabelWrapper, LabelProp(label)
])

@Form()
class DemoForm {

    @Label('Your Opinion')
    @Text()
    my_text = "Bla Bla"

    @Label('Your Contribution')
    @Number({step: 2000})
    my_number = 1
}

Add CSS Classes


@Class('form-class') // adds a css class to the form component element
@Form(SubmitComponent)
class DemoForm {

    @Class('text-class') // adds a css class to the text component element
    @Text()
    my_text = "Bla Bla"

}

Providers

Use providers to inject your component with built-in or custom tokens.


const MAX_LENGTH_TOKEN = new InjectionToken<number>('max-length')

@Form()
class DemoForm {

    @Provide({provide: MAX_LENGTH_TOKEN, useValue: 50})
    @Text()
    my_text = "Bla Bla"

}

And in TextTypeComponent


export class TextTypeComponent {

  constructor(@Inject(MAX_LENGTH_TOKEN) public maxLength: Number) {

    
  }
  
}

Chaining Decorators

Sometimes you want to chain decorators to make the easier to use or understand.


const Label = (label: string) => chain([
    Wrap(FieldLabelWrapperComponent), 
    Prop(FieldLabelWrapperComponent,'label', label)
])

@Form(SubmitComponent)
class DemoForm {

    @Label('Label')
    @Text()
    my_text = "Bla Bla"

}

Usage Details

Form Controls

Deco Forms uses Reactive Forms as its primary source of control. You have access to the form control's through FIELD_FORM_CONTROL_TOKEN.


export class NumberTypeComponent {

  
  constructor(@Inject(FIELD_FORM_CONTROL_TOKEN) public control: FormControl) {

  }
}

Props

If you component can be configured, add a field called config in the constructor.


export class NumberTypeComponent {
  
  
  constructor(@Optional() @Inject(FIELD_CONFIG_TOKEN) public config: NumberFieldConfig) {
    
    }
}

Use Prop for single properties and Props for multiple properties.


  const Label = (label: string) => Prop(FieldLabelWrapperComponent, 'label', label)

  const LabelProps = (props: {label: string, labelColor: Color}) => Props(FieldLabelWrapperComponent, props)

Decorator Order

Decorator order is important. Props, Prop, Class and Providers will apply on the last component, be it a field or a wrapper.

API

Decorators

Form

Decorate classes with Form to enable deco forms to render it. Receives a root component to render the form. Optionally accepts a component to render, defaults to GroupComponent.

DecoField

Use DecoField(Component) on a class memeber to render it using Component. Its initial value will be the value assigned to it.

Group

Use Group on class members to render another class. This can be thought of as grouping inputs using FormGroup.

Wrap

Use Wrap(Component) to wrap fields with Component. Wrapper components should use ng-content.

Class

Assigns CSS classes to the last component in the decorator chain.

Provide

Assign providers to be injected into components. These will be added to the last components in the decorator chain.

Listen

Receives a factory function that returns a function, which listen to form control changes. Can decorate groups as well.

Components

Form

To create a new form:


<deco-form [form-target]="form"></deco-form>

Where "form" is a class annotated with @Form

Group

To create a new group within a form tree:


<deco-group></deco-group>

Directives

Form Directive

If you know what your doing you can render the form without DecoFormComponent with:


    <ng-container [deco-form]="formTarget"></ng-container>

Field Directive

You can render fields with:


    <ng-container [deco-field]="formTarget"></ng-container>

Tokens

The library supplies some tokens to be used:

FORM_FIELDS_TOKEN - gives you access to the fields in a custom Group.

FIELD_FORM_CONTROL_TOKEN - gives you the form control of a field.

FIELD_PARENT_CONTROL_TOKEN - gives you the parent control of a field.

FIELD_PROP_KEY_TOKEN - gives the name of the field form control.

FIELD_CONFIG_TOKEN - the config of a field.

FIELD_CHANGE_TRACKING_TOKEN - Use this to provide a function that will trigger on field changes.

FORM_SUBMIT_TOKEN - Controls what happensn when a form submits.

Implementations

Bootstrap Implementation and Demo

Check out the bootstrap implementation and a Live Demo.