Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] : use formcontrolName in input, combo, etc #4

Closed
xavierclotet opened this issue Oct 11, 2019 · 4 comments
Closed

[FEATURE] : use formcontrolName in input, combo, etc #4

xavierclotet opened this issue Oct 11, 2019 · 4 comments
Assignees

Comments

@xavierclotet
Copy link

xavierclotet commented Oct 11, 2019

🚀 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">

@waterplea
Copy link
Collaborator

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.

@xavierclotet
Copy link
Author

Ok thanks! but this is not supporting formControlname, you need an @input() group: FormGroup

@waterplea
Copy link
Collaborator

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"/>

@waterplea waterplea reopened this Oct 14, 2019
@xavierclotet
Copy link
Author

Ok thank you very much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Status: Done
Development

No branches or pull requests

2 participants