0

I would like to get to work such a scenario:

  1. A user selects an item in the dropdown. But previous value is still shown as selected (until a point 3 succeeded).
  2. Selected value emitted through the @Output variable.
  3. Selected value confirmed in any other place.
  4. Selected value set as current in the dropdown.

As I can see, this behavior couldn't be achieved with two way binding to [(ngModel)] as recommended in examples.

In my particular case (using ngrx Store), I would like selected value (in ng-select dropdown) be bound to the value in the store. So the selected value will be change when appropriate ngrx Action changes the value in the Store.

https://ng-select.github.io/ng-select

Thanks in advance, guys.

Anton Kochev
  • 300
  • 1
  • 3
  • 13

1 Answers1

1

Solution found

Template and component's controller example. Please, read comments in the code.

Template:

<ng-select #select (change)="onChange($event)" ... >
...
</ng-select>

Generally, we need a reference to the component and change event handler.

Controller:

    @Component(...)
    export class NgSelectWrapper implements OnInit, OnChanges
        @Input() value: string | number;
        @Output() changed = new EventEmitter<string>();

        private _selectedValue: string | number;

        ngOnChanges(changes: SimpleChanges): void {
            if (changes.value) {
                // Selected value can be changed only through the @Input field.
                this._selectedValue = changes.value.currentValue;
                // First time itemsList of ng-select component is not initialized,
                // so we need to wait to the next tick to select an item.
                setTimeout(() => this.selectValue(this._selectedValue), 0);
            }
        }

        onChange(event: NewDropdownOptionModel) {
            // Overwrite selection done by the user interaction and select the previous item forcibly.
            // So only ngOnChanges hook can change the selected item.
            this.selectValue(this._selectedValue);
            if (event.id !== this._selectedValue) {
                this.changed.emit(event.id);
            }
        }

        private selectValue(value: string | number): void {
            if (value) {
                if (!this.trySelectItem(value)) {
                    this.select.clearModel();
                }
            }
        }

        private trySelectItem(value: string | number): boolean {
            const item = this.select.itemsList.findItem(value);
            return item
                ? (this.select.select(item), true)
                : false;
        }
    }

So we do not need to use [(ngModel)] binding and handle a selection of an item manually.

Akash Kumar Verma
  • 3,185
  • 2
  • 16
  • 32
Anton Kochev
  • 300
  • 1
  • 3
  • 13