[FEATURE] : use formcontrolName in input, combo, etc
xavierclotet opened this issue Β· comments
π Feature request
Is your feature request related to a problem?
Would be interesting to use those components in a formgroup.
Describe the solution you'd like
Use like
<app-input formControlname="firstName">
Hi @xavierclotet. Thank you for a first issue on this repository :) Components that you see in the demo project are just sketches to demonstrate library capabilities. Indeed, in our real life cases they implement ControlValueAccessor
interface and able to work with forms and ngModel, however here they serve a specific role. Adding extra code to make them closer to what you could actually use in your applications would dilute what they are meant to show.
That said, here's the code for app-input
to use it with forms. If you need something else, you can use it as basis. One day, I hope, we might release a polymorpheus based UI components library, but that's just a dream at this point.
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
forwardRef,
Input,
} from '@angular/core';
import {PolymorpheusContent} from '@tinkoff/ng-polymorpheus';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
@Component({
selector: 'app-input',
templateUrl: './input.template.html',
styleUrls: ['./input.style.less'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => InputComponent),
multi: true,
},
],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class InputComponent implements ControlValueAccessor {
@Input()
content: PolymorpheusContent<never> | null = null;
@Input()
placeholder = '';
value = '';
disabled = false;
onChange: Function = () => {};
onTouched: Function = () => {};
constructor(private readonly changeDetectorRef: ChangeDetectorRef) {}
writeValue(value: any) {
this.value = value ? String(value) : '';
this.changeDetectorRef.markForCheck();
}
setDisabledState(disabled: boolean) {
this.disabled = disabled;
this.changeDetectorRef.markForCheck();
}
registerOnTouched(onTouched: Function) {
this.onTouched = onTouched;
}
registerOnChange(onChange: Function) {
this.onChange = onChange;
}
onMouseDown(event: MouseEvent, input: HTMLInputElement) {
event.preventDefault();
input.focus();
}
onBlur() {
this.onTouched();
}
onValueChange(value: string) {
this.value = value;
this.onChange(value);
}
}
<input
#input
type="text"
class="input"
[placeholder]="placeholder"
[disabled]="disabled"
[ngModel]="value"
(ngModelChange)="onValueChange($event)"
(blur)="onBlur()"
/>
<polymorpheus-outlet
class="outlet"
[content]="content"
(mousedown)="onMouseDown($event, input)"
>
<ng-template let-icon><div [innerHTML]="icon"></div></ng-template>
</polymorpheus-outlet>
Note that to keep things declarative we still have internal value
property and do not access native input element directly. That's why we need changeDetectorRef.markForCheck()
to trigger change detection when control value has been changed externally.
Ok thanks! but this is not supporting formControlname, you need an @input() group: FormGroup
That is a proper way to implement custom control. You can use it like that:
<form [formGroup]="group">
<app-input formControlName="name"/>
</form>
<app-input [formControl]="control"/>
<app-input [(ngModel)]="value"/>
Ok thank you very much!