3

I have a very basic select-option input control in Angular 8. User selects one item from dropdown and it's reflected correctly in dropdown as well as in ngModel variable.

But if I empty the source array programmatically, dropdown is still keeping the old value in ngModel and angular validation shows the control to be in a "valid" state. However, nothing is shown as selected in the dropdown as the source array is now empty.

I am expecting that ngModel should be reset and control should be in invalid state as nothing is selected now.

Is my expectation wrong? Or am I doing something wrong?

Following is a complete example to reproduce the behavior:

Angular 8: StackBlitz

Update 1:

I have created an example in Angular 1 which is working exactly as I expected. AngularJS clears the model value if there is no matching option found in options array. My point is that if dropdown is visible empty then user would assume nothing is selected. However in case of Angular2+, its holding old model value behind the scene.

Angular 1: StackBlitz

coder
  • 8,346
  • 16
  • 39
  • 53
user296526
  • 404
  • 1
  • 3
  • 9

5 Answers5

2

I think in your expectation has something wrong, no need to empty the dropdown list. Just need to set the ngModel to empty value like this model.power = ''.

So since you are using template driven form here also you could reset the form state by using the reset() method of the form (heroForm) like bellow, no need to change anything:

<button type="button" class="btn btn-default" (click)="heroForm.reset()">Clear Array</button>

Working DEMO

If you need to empty the dropdown and also need get the form state to invalid state use like bellow

<button type="button" class="btn btn-default" (click)="powers=[]; model.power=''">Clear Array</button>

According to your updated question you could achieve it like bellow:

<div class="form-group">
        <label for="power">Hero Power</label>
        <select class="form-control" id="power"
                required
                [(ngModel)]="model.power" name="power"
                #power="ngModel">
          <option [ngValue]="null">All</option>
          <option *ngFor="let pow of powers" [ngValue]="pow">{{pow}}</option>
        </select>
      </div>

      <button type="button" class="btn btn-default" (click)="powers=[]; model.power=null">Clear Array</button>

Working DEMO

coder
  • 8,346
  • 16
  • 39
  • 53
  • My expectation is based on how it used to behave in Angular 1. I have updated my question with Angular 1 example which is working as I expected. – user296526 Dec 12 '19 at 04:03
  • Also, I am not resetting the form or emptying the array in real app. In actual code, I have some logic to manipulate the options array. So at some point the currently selected item might not be available in the options, and I was expecting the control to go in invalid state if nothing is visibly selected in it. – user296526 Dec 12 '19 at 04:08
  • updated the [stackblitz](https://stackblitz.com/edit/angular-pwkrpu-6ekbbk?file=src/app/hero-form/hero-form.component.html) please check – coder Dec 12 '19 at 04:11
1

The model and array of options are setting differently for the selection to be get emptied you have to reset or set the ngModel to blank or "". Because the selection sets the ngModel value but it has no link to array so ngModel contains the value that is set to it. When you remove the array the value of the select is not present because it is refrence to the array of values where the ngModel does not refer to the array but the value it is set to by drop down

It is working properly.

Hitech Hitesh
  • 1,641
  • 1
  • 9
  • 18
  • the model and array were connected to each other in case of Angular 1. I have updated my question with Angular 1 example which is working as I expected. – user296526 Dec 12 '19 at 04:06
1

Why would you expect changing an array to also change the model of a dropdown bond to it? A model can be bound to a dropdown that does not contain it's value. You cannot select that value but the model does not become null because the value is not in the values of the dropdown.

You will need to manually set the value of the model to your desired value.

In your Angular 1 stackblitz if you give the model a default value it does not get cleared by the clear array https://stackblitz.com/edit/angularjs-yia6a4?file=home/home.controller.js

Adrian Brand
  • 20,384
  • 4
  • 39
  • 60
  • My expectation is based on how it used to behave in Angular 1. I have updated my question with Angular 1 example which is working as I expected. – user296526 Dec 12 '19 at 04:01
  • You are no longer using Angular 1, many things are different in Angular over AngularJs – Adrian Brand Dec 12 '19 at 04:34
  • In your Angular 1 StackBlitz try giving it a default value $scope.selectedPower = 'some value'; and you will see the same behavior. – Adrian Brand Dec 12 '19 at 04:38
0
    //suppose in app.component.html you have select list of agent, it works for me.

      <ng-select [multiple]="true" #chooseAgent
                 (selected)="selected($event)"
                 (removed)="removed($event)" *ngIf="agentLists" [items]="agentLists" bindLabel="name" bindValue="id" >
      </ng-select>


       and i have a reset button to reset the select list.

       <button type="button" class="btn btn-themegreen" (click)="Cancel()">Reset</button>



       //in app.component.ts

       import { Component, OnInit, ViewChild, Input, Output, EventEmitter } from '@angular/core';
       import { NgSelectComponent } from '@ng-select/ng-select';

       //define variable.
       @ViewChild('chooseAgent', {static:false})
       ngSelectComponentAgent!: NgSelectComponent;
       agentLists: any[] = [];

       Cancel(){

           this.ngSelectComponentAgent.handleClearClick();
           this.agentLists.length=0;

       }
0

Try like below,

HTML

  <button type="button" class="btn btn-default" (click)="clearArray(heroForm)">Clear Array</button>

Component

clearArray(form: FormGroup) {
    this.powers=[];
    form.reset();
  }

In case if you just want to reset powers only,

form.controls.power.reset();
Ininiv
  • 1,325
  • 7
  • 12