We have a form component:
<label> <h3>Type</h3> <workout-type formControlName="type" ></workout-type> </label> form = this.fb.group({ name: ['', Validators.required], type: 'strength' }); constructor( private fb: FormBuilder ) {}
the 'type' FormControl will be a custom form element component which refers to 'workout-type' componet.
For the workout-type component:
import {ChangeDetectionStrategy, Component, forwardRef} from '@angular/core'; import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms'; // Register the control value accessor export const TYPE_CONTROL_ACCESSOR = { provide: NG_VALUE_ACCESSOR, multi: true, useExisting: forwardRef(() => WorkoutTypeComponent) }; @Component({ selector: 'workout-type', providers: [TYPE_CONTROL_ACCESSOR], changeDetection: ChangeDetectionStrategy.OnPush, styleUrls: ['workout-type.component.scss'], template: ` <div class="workout-type"> <div *ngFor="let selector of selectors" [class.active]="selector === value" (click)="setSelected(selector)" class="workout-type__pane"> <img src="/img/{{selector}}.svg" alt="{{selector}}"> <p> {{selector}} </p> </div> </div> ` }) export class WorkoutTypeComponent implements ControlValueAccessor{ selectors = ['strength', 'endurance']; private onTouch: Function; private onModelChange: Function; private value: string; constructor() { } writeValue(value: string): void { this.value = value; } registerOnChange(fn: Function): void { this.onModelChange = fn; } registerOnTouched(fn: Function): void { this.onTouch = fn; } setSelected(value: string): void { this.value = value; this.onModelChange(value); this.onTouch(); } }