0

I'm debugging my component that use ng-select and each time I'm typing into input my ngModel is changing even that I don't use ngModel in my view. I've removed every use of ngModel only class properties remained.

<div>
  <div class="invlisible" #list>
    <div *ngFor="let item of items">{{item}}</div>
  </div>
  <div class="invlisible" #value>{{ngModel}}</div>
  <ng-select [items]="items"
             [clearable]="false"
             [loading]="loading"
             [placeholder]="placeholder"
             [typeahead]="typeahead">
  </ng-select>
</div>

When I've put "x" into ng-select input my ngModel is changing, I've removed every use of ngModel only this is in my component:

@Component({
  selector: 'disco-ng-select',
  templateUrl: './disco-ng-select.component.html',
  styleUrls: ['./disco-ng-select.component.scss']
})
export class DiscoNgSelectComponent extends CSSProps implements OnInit, OnDestroy {
  private _value: any;

  @Input() public items: any[];
  @Input() public loading: boolean;
  @Input() public placeholder: string;
  @Input() public typeahead: Observable<any[]>;
  @Input() public ngModel: any;
  @Output() public ngModelChange = new EventEmitter<any>();

  constructor(
    _host: ElementRef) {
    super(_host);
  }
  public onChange(value: any) {
    this.ngModelChange.emit(value);
  }
}

ngModel is not connected in any way to my component but it's value is changing when I'm typing. The same is happening when I'm putting empty input, and enter text to that input, ngModel is changing.

How can I make ngModel (I want to use ngModel not [model]="value") work the same as normal two way data binding?

2
  • You could add the NG_VALUE_ACCESSORprovider and implement the ControlValueAccessor interface, as shown in this answer. Commented Mar 25, 2019 at 12:03
  • @ConnorsFan thanks, this is exactly what I needed, putting same NG_VALUE_ACCESSOR code + interface and empty methods disabled default behavior. If you want you can add answer it will be easier to find. Commented Mar 25, 2019 at 12:20

1 Answer 1

0

You can use a specific syntax put in place by Angular to create similar behavior, but with custom names.

Here it is in action : https://stackblitz.com/edit/angular-ta6sic?file=src%2Fapp%2Fapp.component.html

import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'hello',
  template: `<h1>Hello {{name}}!</h1>`,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent  {
  _name: string;
  @Input() get name() { return this._name; }
  @Output() nameChange = new EventEmitter<string>();

  set name(value) {
    this._name = value;
    this.nameChange.emit(this._name);
  }
}

You have to

  • create a private property that will hold the value (_name)
  • create a getter input that will return the private property
  • create an event emitter having the name of the Input, followed by Change
  • create a setter that will set the value of the private property and emit changes through the event emitter.

This way, you can use the component like so :

<hello [(name)]="name"></hello>
Sign up to request clarification or add additional context in comments.

2 Comments

He said in the question that he wants to use ngModel, not another property name.
Good point, didn't notice the end of the message. Leaving the answer just in case someone else wonders !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.