Skip to content

Instantly share code, notes, and snippets.

@bndynet
Last active February 8, 2023 10:28
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save bndynet/e188f125216942bbadb92ad8710f41b6 to your computer and use it in GitHub Desktop.
Save bndynet/e188f125216942bbadb92ad8710f41b6 to your computer and use it in GitHub Desktop.
ngModel in custom component

How to use ngModel in Angular Component?

import { Component, forwardRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';

const noop = () => {
};

export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => CustomInputComponent),
    multi: true
};

@Component({
    selector: 'custom-input',
    template: `<div class="form-group">
                    <label><ng-content></ng-content>
                        <input [(ngModel)]="value"  
                                class="form-control" 
                                (blur)="onBlur()" >
                    </label>
                </div>`,
    providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]
})
export class CustomInputComponent implements ControlValueAccessor {

    //The internal data model
    private innerValue: any = '';

    //Placeholders for the callbacks which are later provided
    //by the Control Value Accessor
    private onTouchedCallback: () => void = noop;
    private onChangeCallback: (_: any) => void = noop;

    //get accessor
    get value(): any {
        return this.innerValue;
    };

    //set accessor including call the onchange callback
    set value(v: any) {
        if (v !== this.innerValue) {
            this.innerValue = v;
            this.onChangeCallback(v);
        }
    }

    //Set touched on blur
    onBlur() {
        this.onTouchedCallback();
    }

    //From ControlValueAccessor interface
    writeValue(value: any) {
        if (value !== this.innerValue) {
            this.innerValue = value;
        }
    }

    //From ControlValueAccessor interface
    registerOnChange(fn: any) {
        this.onChangeCallback = fn;
    }

    //From ControlValueAccessor interface
    registerOnTouched(fn: any) {
        this.onTouchedCallback = fn;
    }

}
@michaelkrog
Copy link

Did you find a solution for this? I am hitting the same issue.

@bndynet
Copy link
Author

bndynet commented Sep 19, 2019

Did you find a solution for this? I am hitting the same issue.

Above is the example component about how to use ngModel in your custom component. Just for angular 2+. I do not know whether it is applicable for the latest version.

@mohamedgontara
Copy link

You have to add a (change) output to the input
<input [(ngModel)]="value" class="form-control" (blur)="onBlur()" (change)="changefn()" >
then

changefn(): void { this.onChangeCallback(this.value); }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment