Как я могу получить новый выбор в «select» в Angular 2?

372

Я использую Angular 2 (TypeScript).

Я хочу сделать что-то с новым выбором, но то, что я получаю, onChange()это всегда последний выбор. Как я могу получить новый выбор?

<select [(ngModel)]="selectedDevice" (change)="onChange($event)">
   <option *ngFor="#i of devices">{{i}}</option>
</select>
onChange($event) {
    console.log(this.selectedDevice);
    // I want to do something here with the new selectedDevice, but what I
    // get here is always the last selection, not the one I just selected.
}
Хунбо Мяо
источник

Ответы:

751

Если вам не нужна двусторонняя привязка данных:

<select (change)="onChange($event.target.value)">
    <option *ngFor="let i of devices">{{i}}</option>
</select>

onChange(deviceValue) {
    console.log(deviceValue);
}

Для двусторонней привязки данных разделите привязки событий и свойств:

<select [ngModel]="selectedDevice" (ngModelChange)="onChange($event)" name="sel2">
    <option [value]="i" *ngFor="let i of devices">{{i}}</option>
</select>
export class AppComponent {
  devices = 'one two three'.split(' ');
  selectedDevice = 'two';
  onChange(newValue) {
    console.log(newValue);
    this.selectedDevice = newValue;
    // ... do other stuff here ...
}

Если devicesэто массив объектов, привязать ngValueвместо value:

<select [ngModel]="selectedDeviceObj" (ngModelChange)="onChangeObj($event)" name="sel3">
  <option [ngValue]="i" *ngFor="let i of deviceObjects">{{i.name}}</option>
</select>
{{selectedDeviceObj | json}}
export class AppComponent {
  deviceObjects = [{name: 1}, {name: 2}, {name: 3}];
  selectedDeviceObj = this.deviceObjects[1];
  onChangeObj(newObj) {
    console.log(newObj);
    this.selectedDeviceObj = newObj;
    // ... do other stuff here ...
  }
}

Plunker- не использует <form>
Plunker- использует <form>и использует новый API форм

Марк Райкок
источник
anwere прав, но какова роль ngModel, я все еще не уверен, объясните ли вы это?
Пардип Джейн
1
@PardeepJain, при использовании двусторонней привязки данных с NgModel Angular вызывает 1) автоматическое обновление, selectedDeviceкогда пользователь выбирает другой элемент, и 2) если мы устанавливаем значение selectedDevice, NgModel автоматически обновляет представление. Поскольку мы также хотим получать уведомления об изменениях, я добавил (change)привязку к событию. Нам не нужно делать это таким образом ... мы должны иметь возможность разбить двустороннее связывание данных [ngModel]="selectedDevice" and (ngModelChange)="onChange($event)", но, как я выяснил, onChange()два раза вызывается для каждого изменения списка выбора таким образом.
Марк Райкок
Хорошо, спасибо еще одну вещь, пожалуйста. я хочу получить значение: <option *ngFor="#course of course_array #i=index" #newone value={{course.id}} >{{course.course_name}}</option> course.course_nameи course.idоба, как я могу отправить эти два через (изменить) функцию?
Пардип Джейн
1
@HongboMiao, специальная $eventпеременная / символ является частью «контекста оператора», который есть в шаблонах Angular. Если бы вместо этого я написал, (ngModelChange)="onChange('abc')"то newValueполучил бы строку abc. Это просто обычный вызов функции JavaScript.
Марк Райкок
2
@HongboMiao, используйте [ngValue], если у вас есть массив объектов. Используйте [значение], если у вас есть массив примитивных типов (строка, логическое значение, целое число).
Марк Райкок
40

Вы можете передать значение обратно в компонент, создав ссылочную переменную в теге select #deviceи передав его в обработчик изменений, который onChange($event, device.value)должен иметь новое значение

<select [(ng-model)]="selectedDevice" #device (change)="onChange($event, device.value)">
    <option *ng-for="#i of devices">{{i}}</option>
</select>

onChange($event, deviceValue) {
    console.log(deviceValue);
}
Brocco
источник
1
Здесь вы не привязываетесь ngModel, вы привязываетесь к новой переменной с именем device.
люкс
4
что [(ngModel)]здесь происходит
Пардип Джейн
2
@Brocco Ваши и Марка верны. Надеюсь, вы понимаете, я могу выбрать только один ответ. :)
Хунбо Мяо
22

Просто используйте [ngValue] вместо [value] !!

export class Organisation {
  description: string;
  id: string;
  name: string;
}
export class ScheduleComponent implements OnInit {
  selectedOrg: Organisation;
  orgs: Organisation[] = [];

  constructor(private organisationService: OrganisationService) {}

  get selectedOrgMod() {
    return this.selectedOrg;
  }

  set selectedOrgMod(value) {
    this.selectedOrg = value;
  }
}


<div class="form-group">
      <label for="organisation">Organisation
      <select id="organisation" class="form-control" [(ngModel)]="selectedOrgMod" required>
        <option *ngFor="let org of orgs" [ngValue]="org">{{org.name}}</option>
      </select>
      </label>
</div>
Роберт Кинг
источник
1
Это помогло мне. Не уверен, что мой случай немного отличается, но для меня (change)="selectOrg(selectedOrg)"вызывает функцию selectOrg с текущим / предыдущим выбором, а не вновь выбранный вариант. Я понял, мне даже не нужно (change)немного.
Ник
Хороший споттинг. да, это странное поведение с (изменением) прохождения старой модели. Я думал, что это будет похоже на ng-change, может быть, это ошибка в angular2. Я обновил его, чтобы использовать методы get и set. Таким образом, в методе set selectedOrgMod (value) я могу узнать, что организация изменилась, и обновить мой список организационных групп.
Роберт Кинг
12

Я столкнулся с этой проблемой при выполнении учебного курса по Angular 2 (версия TypeScript) в https://angular.io/docs/ts/latest/guide/forms.html.

Блок выбора / опции не позволял изменить значение выбора, выбрав один из вариантов.

Делать то, что предложил Марк Райкок, сработало, хотя мне интересно, есть ли что-то, что я пропустил в оригинальном уроке или было обновление. В любом случае добавление

onChange(newVal) {
    this.model.power = newVal;
}

на hero-form.component.ts в классе HeroFormComponent

а также

(change)="onChange($event.target.value)"

to hero-form.component.html в <select>элементе заставил его работать

jarisky
источник
4

используйте selectionChange в угловых 6 и выше. пример (selectionChange)= onChange($event.value)

Валентин
источник
Я не использовал подход с реактивной формой. Мне просто нужно выбранное значение, чтобы вызвать сервисный вызов, основанный на этом единственном значении. Метод выше помог мне.
Анаварас Ламурэп
3

Другой вариант - сохранить объект в значении в виде строки:

<select [ngModel]="selectedDevice | json" (ngModelChange)="onChange($event)">
    <option [value]="i | json" *ngFor="let i of devices">{{i}}</option>
</select>

составная часть:

onChange(val) {
    this.selectedDevice = JSON.parse(val);
}

Это был единственный способ получить двухстороннюю привязку, чтобы установить значение select при загрузке страницы. Это произошло потому, что мой список, который заполняет поле выбора, не был точно таким же объектом, с которым был связан мой выбор, и должен быть тем же объектом, а не просто значениями свойств.

kravits88
источник
3
<mat-form-field>
<mat-select placeholder="Vacancies" [(ngModel)]="vacanciesSpinnerSelectedItem.code" (ngModelChange)="spinnerClick1($event)"
    [ngModelOptions]="{standalone: true}" required>
    <mat-option *ngFor="let spinnerValue of vacanciesSpinnerValues" [value]="spinnerValue?.code">{{spinnerValue.description}}</mat-option>
</mat-select>

Я использовал это для раскрытия углового материала. работает отлично

Apurv
источник
1

последние ионные 3.2.0 были изменены (изменить) на (ionChange)

например: HTML

<ion-select (ionChange)="function($event)"> <ion-option>1<ion-option>
</ion-select>

TS

function($event){
// this gives the selected element
 console.log($event);

}
занос
источник
1

Угловой 7/8

Начиная с углового 6, использование свойства ввода ngModel с директивой реактивных форм устарело и полностью удалено в угловом 7+. Читайте официальный документ здесь.

Используя подход реактивной формы, вы можете получить / установить выбранные данные как;

      //in your template
 <select formControlName="person" (change)="onChange($event)"class="form-control">
    <option [value]="null" disabled>Choose person</option>
      <option *ngFor="let person of persons" [value]="person"> 
        {{person.name}}
    </option>
 </select> 


 //in your ts
 onChange($event) {
    let person = this.peopleForm.get("person").value
    console.log("selected person--->", person);
    // this.peopleForm.get("person").setValue(person.id);
  }
7guyo
источник
0

В Angular 5 я поступил следующим образом. получить объект $ event.value вместо $ event.target.value

<mat-form-field color="warn">
   <mat-select (ngModelChange)="onChangeTown($event)" class="form-width" formControlName="branch" [(ngModel)]="branch" placeholder="Enter branch">
     <mat-option *ngFor="let branch of branchs" [value]="branch.value">
                  {{ branch.name }}
     </mat-option>
   </mat-select>
</mat-form-field>

onChangeTown(event): void {
  const selectedTown = event;
  console.log('selectedTown: ', selectedTown);
}
Кумаресан Перумал
источник
0

В Angular 8 вы можете просто использовать «selectionChange» следующим образом:

 <mat-select  [(value)]="selectedData" (selectionChange)="onChange()" >
  <mat-option *ngFor="let i of data" [value]="i.ItemID">
  {{i.ItemName}}
  </mat-option>
 </mat-select>
B.Habibzadeh
источник