Ng-select: Issues wrapping ng-select

Created on 4 May 2018  路  4Comments  路  Source: ng-select/ng-select

Expected behaviour

I'm trying to wrap ng-select in a custom component that can deal with remote data in an easier, more reusable fashion for our domain. After a bit of digging, it looks like when using the formControlName directive with Reactive Forms that the ng-select internal items list hasn't been set as ControlValueAccessor's writeValue function is called before the child ng-select component is initialized (no ngOnChanges or ngOnInit called yet). This may be an Angular issue but was just curious if you had any ideas of suggestions on how to accomplish this. I can add a setTimeout to the write value which fixes things but seems like the component should initialize it's children before writeValue is called?

Actual behaviour

He is a simplified version of what I'm experiencing & trying to do:
https://stackblitz.com/edit/ng-select-example-z7brxu

More Info

ng-select version: 1.4.0

browser: ANY

reproducible in demo page: NO

question

Most helpful comment

Correct. We're saying the same thing. Because writeValue is called before ngOnChanges, the items aren't set before we try to write the value of the model to it. It's a little unfortunate how difficult it is to just wrap a basic component in Angular. It seems like writeValue shouldn't be called until the children have at least had their ngOnInit called. Like I said, I got it working by basically doing this instead:

<ng-select
[items]="items"
[bindValue]="bindValue"
[bindLabel]="bindLabel"
[multiple]="true"
[(ngModel)]="_value"
[disabled]="_disabled"
(change)="_onChange($event)"
(focus)="_onTouched($event)"
</ng-select>
class ... implements ControlValueAccessor {
...

_onChange: any;
_onTouched: any;
_disabled: boolean;
_value: any;

  registerOnChange(fn: any): void {
    this._onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this._onTouched = fn;
  }

  setDisabledState(isDisabled: boolean): void {
    this._disabled = isDisabled;
  }

  writeValue(obj: any): void {
    this._value = obj;
  }

We can close this if you want. Just wanted to document this if someone else runs into it.

All 4 comments

I did end up getting it to work by not delegating to the child ref as well.

Nope, writeValue is called before ngOnChanges. You could check source code to see how we handle it.

Correct. We're saying the same thing. Because writeValue is called before ngOnChanges, the items aren't set before we try to write the value of the model to it. It's a little unfortunate how difficult it is to just wrap a basic component in Angular. It seems like writeValue shouldn't be called until the children have at least had their ngOnInit called. Like I said, I got it working by basically doing this instead:

<ng-select
[items]="items"
[bindValue]="bindValue"
[bindLabel]="bindLabel"
[multiple]="true"
[(ngModel)]="_value"
[disabled]="_disabled"
(change)="_onChange($event)"
(focus)="_onTouched($event)"
</ng-select>
class ... implements ControlValueAccessor {
...

_onChange: any;
_onTouched: any;
_disabled: boolean;
_value: any;

  registerOnChange(fn: any): void {
    this._onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this._onTouched = fn;
  }

  setDisabledState(isDisabled: boolean): void {
    this._disabled = isDisabled;
  }

  writeValue(obj: any): void {
    this._value = obj;
  }

We can close this if you want. Just wanted to document this if someone else runs into it.

Hello @vincentjames501 can you please paste the full code? I tried every way, but failed :/

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ybmt picture ybmt  路  3Comments

shawnshaddock picture shawnshaddock  路  3Comments

wc200107 picture wc200107  路  4Comments

tomasz-nowakowski picture tomasz-nowakowski  路  4Comments

gitlines picture gitlines  路  4Comments