Dynamic forms with NgRx

Juan Stoppa

Software Engineer - Wealth Dynamix

@juanstoppa

My journey with forms

@juanstoppa

"Digital Transformation"

@juanstoppa

What does it mean for the user?

@juanstoppa

@juanstoppa

Agenda

  • Define the problem
  • A proposed solution
  • A few demos
  • Conclusion

@juanstoppa

The requirements

  • Design system agnostic
  • Support multiple layouts
  • Dynamic validation
  • Reuse components as much as possible

@juanstoppa

Dynamic forms

Ngrx

Reactive forms

Dynamic component loader

CSS grid

@juanstoppa

Dynamic reactive forms

@juanstoppa

Dynamic reactive forms

let questions: QuestionBase < any > [] = [
    new TextboxQuestion({
        key: 'firstName',
        label: 'First name',
        value: 'Bombasto',
        required: true,
        order: 1
    }),
    new TextboxQuestion({
        key: 'emailAddress',
        label: 'Email',
        type: 'email',
        order: 2
    }),
    new DropdownQuestion({
        key: 'brave',
        label: 'Bravery Rating',
        options: [
            { key: 'solid', value: 'Solid' },
            { key: 'great', value: 'Great' },
            { key: 'good',  value: 'Good'  },
            { key: 'unproven', value: 'Unproven' }],
        order: 3
    })];

@juanstoppa

CSS Grid

.grid-container {
  display: grid;
  grid-template-areas:
    'header header'
    'left   right'
    'bottom bottom';
}

.header { grid-area: header; }
.left   { grid-area: left; }
.right  { grid-area: right; }
.across { grid-area: bottom; }
<div class="grid-container">
  <div class="header">Header</div>
  <div class="left">Field 1</div>  
  <div class="right">Field 2</div>
  <div class="bottom">Field 3</div>
</div>

@juanstoppa

Demo

@juanstoppa

Ngrx

Ngrx store

Questions

Template

2

Form

Groups

Components

3

4

Initial state is loaded

Form Groups recalculated with new state

Data

1

Dispatch [form] load action

@juanstoppa

Ngrx

Ngrx store

Data

Form

Components

Validation rules

let questions: QuestionBase < any > [] = [
    new TextboxQuestion({
        key: 'firstName',
        label: 'First name',
        value: 'Bombasto',
        required: true,
        order: 1
    }),
    new TextboxQuestion({
        key: 'emailAddress',
        label: 'Email',
        type: 'email',
        order: 2,
        rules: {
            readonly: {},
            hidden: {},
            required: {
                condition: "firstName"
            }
        }
    }),
    new DropdownQuestion({
        key: 'brave',
        label: 'Bravery Rating',
        options: [
            { key: 'solid', value: 'Solid' },
            { key: 'great', value: 'Great' },
            { key: 'good',  value: 'Good'  },
            { key: 'unproven', value: 'Unproven' }],
        order: 3
    })];

@juanstoppa

Component loader

 

Container

Component

 

 

Representational

Component

 

@Input

@Ouput

const componentFactory = this.fr.resolveComponentFactory(component);

const ref = viewContainerRef.createComponent(componentFactory);

// @Input
(<QuestionComponent>ref.instance).input = this.component;

// @Output
this.formControl.controls[this.component.id].valuesChanges.subscribe(...

@juanstoppa

Demo

@juanstoppa

Level up the form

Component

Component

Section

Page

Page

Layout

Section

Form Metadata

Form Metadata

@juanstoppa

Level up the form

Component

Component

Section

Page

Page

Layout

Section

FormControl

FormControl

FormGroup

FormGroup

FormGroup

FormGroup

FormGroup

Store Service

Component

Form Metadata

 RF FormGroup

Store Service dictates validation rules with new state

FormGroup applies validation rules from new state

@juanstoppa

Demo

@juanstoppa

Conclusion

Ngrx as one source of truth

Reactive forms FTW

Dynamic component loader for extending

CSS grid for custom layouts

Thank you

Juan Stoppa

@juanstoppa

Dynamic forms with NgRx

By Juan Stoppa

Dynamic forms with NgRx

  • 1,205