Làm cách nào tôi có thể nhận được lựa chọn mới trong các lựa chọn trên bầu trời trong Angular 2?


372

Tôi đang sử dụng Angular 2 (TypeScript).

Tôi muốn làm một cái gì đó với lựa chọn mới, nhưng những gì tôi nhận onChange()được luôn là lựa chọn cuối cùng. Làm thế nào tôi có thể có được lựa chọn mới?

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

Câu trả lời:


749

Nếu bạn không cần ràng buộc dữ liệu hai chiều:

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

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

Đối với liên kết dữ liệu hai chiều, hãy tách các ràng buộc thuộc tính và sự kiện:

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

Nếu deviceslà mảng của các đối tượng, liên kết với ngValuethay vì 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- không sử dụng <form>
Plunker- sử dụng <form>và sử dụng API biểu mẫu mới


anwere là đúng nhưng vai trò của ngModel ở đây là gì tôi vẫn bối rối, bạn sẽ làm mất nó chứ?
Pardeep Jain

1
@PardeepJain, sử dụng liên kết dữ liệu hai chiều với NgModel khiến Angular thành 1) tự động cập nhật selectedDevicekhi người dùng chọn một mục khác và 2) nếu chúng tôi đặt giá trị selectedDevice, NgModel sẽ tự động cập nhật chế độ xem. Vì chúng tôi cũng muốn được thông báo về sự thay đổi, tôi đã thêm (change)ràng buộc sự kiện. Chúng ta không nên làm theo cách này ... chúng ta sẽ có thể phá vỡ liên kết dữ liệu hai chiều [ngModel]="selectedDevice" and (ngModelChange)="onChange($event)", nhưng như tôi phát hiện ra, onChange()được gọi hai lần cho mỗi danh sách chọn thay đổi theo cách đó.
Mark Rajcok

được rồi thanx một điều nữa xin vui lòng. tôi muốn nhận giá trị của: <option *ngFor="#course of course_array #i=index" #newone value={{course.id}} >{{course.course_name}}</option> course.course_namecourse.idcả hai làm thế nào tôi có thể gửi hai hàm này qua chức năng (thay đổi)?
Pardeep Jain

1
@HongboMiao, $eventbiến / ký hiệu đặc biệt là một phần của "bối cảnh câu lệnh" mà các câu lệnh mẫu Angular có. Nếu thay vào đó tôi đã viết (ngModelChange)="onChange('abc')"thì newValuesẽ nhận được chuỗi abc. Đó chỉ là chức năng gọi JavaScript bình thường.
Mark Rajcok

2
@HongboMiao, sử dụng [ngValue] nếu bạn có một mảng các đối tượng. Sử dụng [value] nếu bạn có một mảng các kiểu nguyên thủy (chuỗi, boolean, số nguyên).
Mark Rajcok

40

Bạn có thể chuyển giá trị trở lại vào thành phần bằng cách tạo biến tham chiếu trên thẻ chọn #devicevà chuyển nó vào trình xử lý thay đổi onChange($event, device.value)sẽ có giá trị mới

<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);
}

1
Bạn không ràng buộc ngModelở đây, bạn đang ràng buộc với một biến mới được gọi device.
lux

4
cuộn phim [(ngModel)]ở đây là gì
Pardeep Jain

2
@Brocco Cả của bạn và Mark đều đúng. Hy vọng bạn có thể hiểu tôi chỉ có thể chọn một câu trả lời. :)
Hongbo Miao

22

Chỉ cần sử dụng [ngValue] thay vì [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
Điều này đã giúp tôi. Không chắc trường hợp của tôi có hơi khác không, nhưng đối với tôi, hãy (change)="selectOrg(selectedOrg)"gọi hàm selectOrg với lựa chọn hiện tại / trước đó, không phải là tùy chọn mới được chọn. Tôi nhận ra, tôi thậm chí không cần một (change)chút.
Nick

Tốt đốm. vâng, đó là hành vi kỳ quặc với (thay đổi) vượt qua mô hình cũ. Tôi nghĩ rằng nó sẽ giống như thay đổi ng có lẽ đó là một lỗi trong angular2. Tôi đã cập nhật nó để sử dụng các phương thức get và set. Theo cách đó, trong phương thức được chọnOrgMod (value) tôi có thể biết rằng tổ chức đã thay đổi và cập nhật danh sách các nhóm tổ chức của tôi.
vua robert

12

Tôi gặp vấn đề này trong khi thực hiện hướng dẫn biểu mẫu Angular 2 (phiên bản TypeScript) tại https://angular.io/docs/ts/latest/guide/forms.html

Khối chọn / tùy chọn không cho phép thay đổi giá trị của lựa chọn bằng cách chọn một trong các tùy chọn.

Làm những gì Mark Rajcok đề xuất có hiệu quả, mặc dù tôi tự hỏi liệu có điều gì tôi đã bỏ lỡ trong hướng dẫn ban đầu hoặc nếu có bản cập nhật. Trong mọi trường hợp, thêm

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

tới hero-form.component.ts trong lớp HeroFormComponent

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

to hero-form.component.html trong <select>phần tử làm cho nó hoạt động


4

sử dụng selectChange trong góc 6 trở lên. thí dụ (selectionChange)= onChange($event.value)


Tôi đã không sử dụng phương pháp tiếp cận dạng phản ứng. Tôi chỉ cần giá trị được chọn để kích hoạt cuộc gọi dịch vụ dựa trên giá trị duy nhất đó .. phương pháp trên đã giúp tôi.
anavara lamurep

3

Một tùy chọn khác là lưu trữ đối tượng theo giá trị dưới dạng chuỗi:

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

thành phần:

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

Đây là cách duy nhất tôi có thể làm việc ràng buộc hai chiều để đặt giá trị chọn khi tải trang. Điều này là do danh sách của tôi điền vào hộp chọn không phải là cùng một đối tượng như lựa chọn của tôi bị ràng buộc và nó cần phải là cùng một đối tượng, không chỉ là các giá trị thuộc tính giống nhau.


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>

Tôi đã sử dụng điều này cho thả xuống Vật liệu góc. hoạt động tốt


1

ion 3.2.0 mới nhất đã sửa đổi (thay đổi) thành (ionChange)

ví dụ: 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

Góc 7/8

Kể từ góc 6, việc sử dụng thuộc tính đầu vào ngModel với chỉ thị dạng phản ứng đã không được chấp nhận và loại bỏ hoàn toàn trong 7+ góc. Đọc tài liệu chính thức ở đây.

Sử dụng phương pháp tiếp cận biểu mẫu phản ứng, bạn có thể nhận / đặt dữ liệu đã chọn như;

      //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);
  }

0

Trong Angular 5 tôi đã làm theo cách sau. lấy đối tượng $ event.value thay vì $ 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

Trong Angular 8, bạn chỉ cần sử dụng "selectChange" như thế này:

 <mat-select  [(value)]="selectedData" (selectionChange)="onChange()" >
  <mat-option *ngFor="let i of data" [value]="i.ItemID">
  {{i.ItemName}}
  </mat-option>
 </mat-select>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.