In the first part of this series we covered the basics of Angular Formly. Here we delve deeper and reveal more concepts.

Layouts in Formly

Layouts from the Formly library helps us design responsive forms with modern aesthetics.

We have to use the fieldGroupClassName property in the configuration and have to assign the class name. Then in the fieldGroup we need to add one more property – className (the name of the class can be anything, but should pass naming conventions)

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
formFields = [
{
fieldGroupClassName: 'display-flex'
fieldGroup: [
{
className: 'flex-1' ,
type: 'input' ,
templateOptions: {
label: 'Workset Name'
}
} ,
{
className: 'flex-1' ,
type: 'select' ,
templateOptions: {
label: 'Workflow' ,
options: [{ id: 1 , name: 'Workflow 1' }]
}
} ,
{
className: 'flex-1' ,
type: 'select' ,
templateOptions: {
label: 'Process' ,
options: [{ id: 1 , name: 'Process 1' }]
}
}
...... ]
}
] as FormlyFieldConfig []
formFields = [ { fieldGroupClassName: 'display-flex' fieldGroup: [ { className: 'flex-1', type: 'input', templateOptions: { label: 'Workset Name' } }, { className: 'flex-1', type: 'select', templateOptions: { label: 'Workflow', options: [{ id: 1, name: 'Workflow 1'}] } }, { className: 'flex-1', type: 'select', templateOptions: { label: 'Process', options: [{ id: 1, name: 'Process 1'}] } } ......] } ] as FormlyFieldConfig[]
formFields = [
{
fieldGroupClassName: 'display-flex'
fieldGroup: [
{
  className: 'flex-1',
  type: 'input',
  templateOptions: {
     label: 'Workset Name'
   }
},
{
  className: 'flex-1',
  type: 'select',
  templateOptions: {
     label: 'Workflow',
     options:     [{ id: 1, name: 'Workflow 1'}]
  }
},
{
  className: 'flex-1',
  type: 'select',
  templateOptions: {
     label: 'Process',
     options:     [{ id: 1, name: 'Process 1'}]
   }
}
......]
}
] as FormlyFieldConfig[]
Layout with flexbox

Layout with flexbox

Without wrapper classes, all the fields will display one below the other.

Custom Templates

As stated in part 1, Formly supports several pre-built templates. However, we can also create custom templates as well.

First you must create a component representing the field which extends the FieldType class.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import { Component } from '@angular/core' ;
import { FieldType } from '@ngx-formly/core' ;
@ Component ({
selector: 'formly-custom-template-input-field' ,
template: `
< input type= "input" [ formControl ] = "formControl" [ formlyAttributes ] = "field" >
`,
})
export class FormlyCustomTemplateInputField extends FieldType {}
import { Component } from '@angular/core'; import { FieldType } from '@ngx-formly/core'; @Component({ selector: 'formly-custom-template-input-field', template: ` <input type="input" [formControl]="formControl" [formlyAttributes]="field"> `, }) export class FormlyCustomTemplateInputField extends FieldType {}
import { Component } from '@angular/core';
import { FieldType } from '@ngx-formly/core';

@Component({
selector: 'formly-custom-template-input-field',
template: `
  <input type="input" [formControl]="formControl" [formlyAttributes]="field">
`,
})
export class FormlyCustomTemplateInputField extends FieldType {}

Then register the custom type in the NgModule declaration:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
FormlyModule. forRoot ({
types: [
{ name: 'input' , component: FormlyFieldInput } ,
] ,
}) ,
FormlyModule.forRoot({ types: [ { name: 'input', component: FormlyFieldInput }, ], }),
FormlyModule.forRoot({
 types: [
   { name: 'input', component: FormlyFieldInput },
 ],
}),

types allows you to specify a custom type which you can use in your field configuration and requires two properties:

  1. name: The name of the template
  2. component: The component that Formly should create when this type is set

Use the newly created custom type in the form config:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
fields: FormlyFieldConfig [] = [
{
key: 'firstname' ,
type: 'input' ,
} ,
] ;
fields: FormlyFieldConfig[] = [ { key: 'firstname', type: 'input', }, ];
fields: FormlyFieldConfig[] = [
  {
    key: 'firstname',
    type: 'input',
  },
];

Building nested forms in Formly

There are situations where we need nested forms. To do this simply add the following extra properties in the field configurations,

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
wrappers: [ 'panel' ] ,
templateOptions: { label: 'Address' } ,
fieldGroup: [{ }]
wrappers: ['panel'], templateOptions: { label: 'Address' }, fieldGroup: [{ }]
wrappers: ['panel'],
templateOptions: { label: 'Address' },
fieldGroup: [{   }]
 
        

Where, wrapper is a panel. Under templateOptions we have to give a label name to display the name on the panel. The last property is fieldGroup where we can add as many fields in it.

Hooks

In order to customise the behaviour of our form control at run time Formly contains a concept called hooks. These are of type “FormlyLifeCycleOptions” under which they provide the following life cycles:

  1. OnInit
  2. OnChanges
  3. doCheck
  4. afterContentInit
  5. afterContentChecked
  6. afterViewInit
  7. afterViewChecked
  8. onDestroy

Here is an example of these life cycle hooks,

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
key: 'FirstName' ,
hooks: {
onInit: ( field: FormlyFormField ) {
field. templateOptions . lable = 'Enter The First Name'
}
}
key: 'FirstName', hooks: { onInit: (field: FormlyFormField) { field.templateOptions.lable = 'Enter The First Name' } }
key: 'FirstName',
hooks: {
      onInit: (field: FormlyFormField) {
          field.templateOptions.lable = 'Enter The First Name'
      }
}

We initialise the field label as “FirstName” however when our form renders in the view, at runtime we will display the label as “Enter The First Name”. The label which we have initialized will no longer display in the view. Consequently, this means that we can control any field’s label and value using hooks. Operations using “RxJs” are also possible in Formly.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
key: 'cityId' ,
options: []
hooks: {
onInit: ( field: FormlyFormField ) {
field. templateOptions . options = field. form . get ( 'stateId' ) . valueChanges . pipe ( switchMap ( nationId = > this . serviceName . getCities ( stateId ))
)
}
}
key: 'cityId', options: [] hooks: { onInit: (field: FormlyFormField) { field.templateOptions.options = field.form.get('stateId').valueChanges.pipe(switchMap(nationId => this.serviceName.getCities(stateId)) ) } }
key: 'cityId',
options: []
hooks: {
      onInit: (field: FormlyFormField) {
          field.templateOptions.options = field.form.get('stateId').valueChanges.pipe(switchMap(nationId => this.serviceName.getCities(stateId))
     )      
  }
}

Here we assume that we have a list of states and based on selected stateId we will filter the cities from the states. We can directly associate the filtered cities to the options array.

Conclusion

The Formly library helps rapidly build forms with custom validation, use services for fetching results using an API, runtime changes and more.

Learn More about Encora

We are the software development company fiercely committed and uniquely equipped to enable companies to do what they can’t do now.

Learn More

Global Delivery

READ MORE

Careers

READ MORE

Industries

READ MORE

Related Insights

Enabling Transformation in Hospitality through Technology-Led Innovation

As the exclusive sponsor of the 2024 Hotel Visionary Awards, we support organizations leading ...

Read More

Key Insights from HLTH 2024: The Future of Patient-Centered Healthcare

Discover key insights from HLTH 2024 on digital health, AI in diagnostics, data interoperability, ...

Read More

Data-Driven Engineering: Transforming Operations and Products from Insight to Impact

Discover how data-driven engineering transforms operations and product development, enhancing team ...

Read More
Previous Previous
Next

Accelerate Your Path
to Market Leadership 

Encora logo

Santa Clara, CA

+1 669-236-2674

letstalk@encora.com

Innovation Acceleration

Speak With an Expert

Encora logo

Santa Clara, CA

+1 (480) 991 3635

letstalk@encora.com

Innovation Acceleration