Search code examples
angularngrxangular-ngselect

Angular and ng-select. Confirmation on selected item


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.


Solution

  • 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.