Create Custom Form Control for ng-select in Angular
How to Create Custom Form Control in Angular
Why we create custom form control ? Normally, we used to create custom form control for re-usability.
The best advantage is that to add common functionality and features in this custom form control and extend the functionality as per our need and requirement.
And we can use everywhere into the application.
But this example will tell you how to create custom form control to extend the functionality of angular ng-select component.
We are adding a feature for this control, multi selection along with checkbox.
Before that, we need to know what is the basic syntax of creating custom form control in angular.
So, we start by implementing the ControlValueAccessor interface from @angular/forms into the component. This interface has three functions that need to be implemented and one optional functional.
writeValue(obj: any): void { }
registerOnChange(fn: any): void
{ }
registerOnTouched(fn: any): void { }
setDisabledState?(isDisabled:
boolean): void { }
The function setDisabledState is optional.
Let's create a example, this example will gives us the idea to how to extend the functionality and re-usability of ng-select component with below steps:
Step 1 : create a new component
with the name of
custom-ng-select.component.
Step 2 : add below code to custom-ng-select.component.html
All{{item[itemLabel]}}
Step 3 : add below code to this custom-ng-select.component.ts
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; import { Component, EventEmitter, forwardRef, Input, Output } from '@angular/core'; @Component({ selector: 'app-custom-ng-select', templateUrl: './custom-ng-select.component.html', styleUrls: ['./custom-ng-select.component.scss'], providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CustomNgSelectComponent), multi: true }] }) export class CustomNgSelectComponent implements ControlValueAccessor { public isChecked = false; private innerValue: any = ''; public touchedFunction: () => void; public changeFunction: (value: any) => void; @Input() public itemTitle = ''; @Input() public itemsList: any; @Input() public itemLabel: string; @Input() public itemValue: string; @Input() public isClearable = true; @Input() public isMultiple = false; @Input() public isDisabled = false; @Input() public isSelectAll = false; @Input() public isSearchable = false; @Input() public isVirtualScroll = false; @Input() public isCloseOnSelect = false; @Input() public itemPlaceholder: string; @Input() public isSelectableGroup: false; @Output() public changeEventHandler: EventEmitter= new EventEmitter (); public checkValue(event: any): void { if (this.isChecked) { this.selectedValue = this.itemsList.map(itemList => itemList[this.itemValue]); } else { this.selectedValue = []; } } public onChange(event: any): void { if (this.selectedValue === [] || this.selectedValue.length === 0 || this.selectedValue.length !== this.itemsList.length) { this.isChecked = false; } else if (this.selectedValue.length === this.itemsList.length) { this.isChecked = true; } this.changeEventHandler.emit(); } public get selectedValue(): any { return this.innerValue; } public set selectedValue(value: any) { if (value !== this.innerValue) { this.innerValue = value; this.changeFunction(value); } } public writeValue(value: any): void { // tslint:disable-next-line: triple-equals if (value !== null && value !== undefined && value != '') { this.innerValue = value; } else { this.isChecked = false; this.innerValue = []; } } public registerOnChange(fn: () => void) { this.changeFunction = fn; } public registerOnTouched(fn: () => void) { this.touchedFunction = fn; } public setDisabledState?(isDisabled: boolean): void { } }
We have successfully created the custom form control component added with some additional functionality to them.
Let's use this custom form control into application.
Step 1 : add code in app.component.html
Step 2 : add code in app.component.ts
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent implements OnInit { public title = 'demo-app'; public selectedCar: string; public carsInformation: any; public ngOnInit(): void { setTimeout(() => { this.carsInformation = [ { id: 1, name: 'Ford Mustang (1964-Present)' }, { id: 2, name: 'Rolls-Royce Silver Cloud (1955-1966)' }, { id: 3, name: 'Ferrari Testarossa (1984-1996)' }, { id: 4, name: 'Lamborghini Countach (1974-1990)' }, { id: 5, name: 'Dodge Viper (1992-Present)' }, { id: 6, name: 'Chevrolet Corvette (1953-Present)' }, { id: 7, name: 'Bugatti Veyron (2006-Present)' }, { id: 8, name: 'Porsche Carrera 1956-Present' } ] }, 5000); } }
Step 3 : add code in app.module.ts
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { CustomNgSelectComponent } from './custom-ng-select/custom-ng-select.component'; import { CommonModule } from '@angular/common'; import { NgSelectModule } from '@ng-select/ng-select'; import { FormsModule } from '@angular/forms'; @NgModule({ declarations: [ AppComponent, CustomNgSelectComponent ], imports: [ BrowserModule, AppRoutingModule, CommonModule, NgSelectModule, FormsModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Step 4 : add code in styles.scss
/* You can add global styles to this file, and also import other style files */ @import "~@ng-select/ng-select/themes/default.theme.css"; .divcenter { display: flex; align-items: center; justify-content: center; }
Expected Result Should like below :
Good tutorial. I am trying to add validation to this but the validation classes do not propagate to the parent. Any idea why?
ReplyDeleteFrom my deepest point of my heart I would like to say thank you, you are the real super man!
ReplyDelete