Wie kann ich in "Auswahl" in Winkel 2 eine neue Auswahl erhalten?

372

Ich verwende Angular 2 (TypeScript).

Ich möchte etwas mit der neuen Auswahl machen, aber was ich bekomme, onChange()ist immer die letzte Auswahl. Wie kann ich die neue Auswahl erhalten?

<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.
}
Hongbo Miao
quelle

Antworten:

749

Wenn Sie keine bidirektionale Datenbindung benötigen:

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

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

Trennen Sie für die bidirektionale Datenbindung die Ereignis- und Eigenschaftsbindungen:

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

Wenn deviceses sich um ein Array von Objekten handelt, binden Sie an ngValueanstelle von 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- verwendet nicht <form>
Plunker- verwendet <form>und verwendet die neue Formular-API

Mark Rajcok
quelle
anwere ist richtig, aber welche Rolle spielt ngModel hier? Ich bin immer noch verwirrt. Wirst du es erklären?
Pardeep Jain
1
@PardeepJain führt bei Verwendung der bidirektionalen Datenbindung mit NgModel dazu, dass Angular 1) automatisch aktualisiert wird, selectedDevicewenn der Benutzer ein anderes Element auswählt, und 2) wenn wir den Wert von selectedDevicefestlegen, aktualisiert NgModel die Ansicht automatisch. Da wir auch über eine Änderung informiert werden möchten, habe ich die (change)Ereignisbindung hinzugefügt . Wir sollten es nicht so machen müssen ... wir sollten in der Lage sein, die bidirektionale Datenbindung aufzuteilen [ngModel]="selectedDevice" and (ngModelChange)="onChange($event)", aber wie ich herausgefunden habe, onChange()wird sie für jede Auswahllistenänderung auf diese Weise zweimal aufgerufen.
Mark Rajcok
Okay, danke noch eins. Ich möchte den Wert von: <option *ngFor="#course of course_array #i=index" #newone value={{course.id}} >{{course.course_name}}</option> course.course_nameund course.idbeiden erhalten. Wie kann ich diese beiden über die (Änderungs-) Funktion senden?
Pardeep Jain
1
@ HongboMiao, die spezielle $eventVariable / das spezielle Symbol ist Teil des "Anweisungskontexts", den Angular-Vorlagenanweisungen haben. Wenn stattdessen schrieb ich (ngModelChange)="onChange('abc')"dann newValuewürde die Zeichenfolge erhalten abc. Es ist nur ein normaler JavaScript-Funktionsaufruf.
Mark Rajcok
2
@HongboMiao, verwenden Sie [ngValue], wenn Sie ein Array von Objekten haben. Verwenden Sie [Wert], wenn Sie ein Array primitiver Typen haben (Zeichenfolge, Boolescher Wert, Ganzzahl).
Mark Rajcok
40

Sie können den Wert an die Komponente zurückgeben, indem Sie eine Referenzvariable für das select-Tag erstellen #deviceund diese an den Änderungshandler übergeben onChange($event, device.value), der den neuen Wert haben sollte

<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
quelle
1
Sie sind hier nicht gebunden, sondern ngModelan eine neue Variable namens device.
Lux
4
Was ist die Rolle von [(ngModel)]hier
Pardeep Jain
2
@Brocco Sowohl deine als auch Marks sind korrekt. Ich hoffe, Sie können verstehen, dass ich nur eine Antwort auswählen kann. :)
Hongbo Miao
22

Verwenden Sie einfach [ngValue] anstelle von [Wert] !!

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>
Robert King
quelle
1
Das hat mir geholfen. Ich bin mir nicht sicher, ob mein Fall etwas anders ist, aber für mich (change)="selectOrg(selectedOrg)"ruft die Funktion selectOrg mit der aktuellen / vorherigen Auswahl auf, nicht mit der neu ausgewählten Option. Ich habe herausgefunden, ich brauche nicht einmal das (change)bisschen.
Nick
Gute Beobachtung. Ja, das ist ein seltsames Verhalten, wenn das alte Modell (geändert) übergeben wird. Ich dachte, es wäre wie ng-change, vielleicht ist das ein Fehler in angle2. Ich habe es aktualisiert, um get- und set-Methoden zu verwenden. Auf diese Weise kann ich in der festgelegten Methode selectedOrgMod (value) erkennen, dass sich die Organisation geändert hat, und meine Liste der Organisationsteams aktualisieren.
Robert King
12

Ich bin auf dieses Problem gestoßen, als ich das Angular 2-Formular-Tutorial (TypeScript-Version) unter https://angular.io/docs/ts/latest/guide/forms.html ausgeführt habe

Der Auswahl- / Optionsblock erlaubte nicht, den Wert der Auswahl durch Auswahl einer der Optionen zu ändern.

Das zu tun, was Mark Rajcok vorgeschlagen hat, hat funktioniert, obwohl ich mich frage, ob ich im ursprünglichen Tutorial etwas verpasst habe oder ob es ein Update gab. In jedem Fall hinzufügen

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

zu hero-form.component.ts in der HeroFormComponent-Klasse

und

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

zu hero-form.component.html im <select>Element hat es funktioniert

jarisky
quelle
4

Verwenden Sie selectionChange in Winkel 6 und höher. Beispiel (selectionChange)= onChange($event.value)

Valentinstag
quelle
Ich habe keinen reaktiven Formularansatz verwendet. Ich benötige nur einen ausgewählten Wert, um einen Serviceabruf basierend auf diesem einzelnen Wert auszulösen. Die obige Methode hat mir geholfen.
Anavaras Lamurep
3

Eine andere Möglichkeit besteht darin, das Objekt im Wert als Zeichenfolge zu speichern:

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

Komponente:

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

Dies war die einzige Möglichkeit, die bidirektionale Bindung zum Festlegen des Auswahlwerts beim Laden der Seite zu aktivieren. Dies lag daran, dass meine Liste, die das Auswahlfeld ausfüllt, nicht genau dasselbe Objekt war, an das meine Auswahl gebunden war, und dass es dasselbe Objekt sein muss, nicht nur dieselben Eigenschaftswerte.

kravits88
quelle
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>

Ich habe dies für das eckige Material-Dropdown verwendet. funktioniert gut

Apurv
quelle
1

Die neuesten ionischen Versionen 3.2.0 wurden geändert (ändern) zu (ionChange)

zB: HTML

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

TS

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

}
Schleudern
quelle
1

Winkel 7/8

Ab Winkel 6 wurde die Verwendung der Eingabeeigenschaft ngModel mit der Richtlinie für reaktive Formen in Winkel 7+ veraltet und insgesamt entfernt. Lesen Sie hier das offizielle Dokument.

Mit dem reaktiven Formularansatz können Sie ausgewählte Daten abrufen / festlegen als;

      //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
quelle
0

In Angular 5 habe ich Folgendes getan. Holen Sie sich das Objekt $ event.value anstelle von $ 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);
}
Kumaresan Perumal
quelle
0

In Angular 8 können Sie einfach "selectionChange" wie folgt verwenden:

 <mat-select  [(value)]="selectedData" (selectionChange)="onChange()" >
  <mat-option *ngFor="let i of data" [value]="i.ItemID">
  {{i.ItemName}}
  </mat-option>
 </mat-select>
B.Habibzadeh
quelle