【问题标题】:How can I get new selection in "select" in Angular 2?如何在 Angular 2 的“选择”中获得新的选择?
【发布时间】:2016-02-15 11:29:24
【问题描述】:

我正在使用 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.
}

【问题讨论】:

    标签: angular typescript html-select


    【解决方案1】:

    您可以通过在选择标记#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);
    }
    

    【讨论】:

    • 这里没有绑定到ngModel,而是绑定到了一个名为device的新变量。
    • [(ngModel)] 的卷在这里
    【解决方案2】:

    如果您不需要双向数据绑定:

    <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 - 不使用 &lt;form&gt;
    Plunker - 使用 &lt;form&gt; 并使用新的表单 API

    【讨论】:

    • anwere 是对的,但是 ngModel 在这里的作用是什么,我还是很困惑,你能解释一下吗?
    • @PardeepJain,使用与 NgModel 的双向数据绑定会导致 Angular 1)在用户选择不同的项目时自动更新 selectedDevice,以及 2)如果我们设置 selectedDevice 的值, NgModel 会自动更新视图。由于我们还希望收到更改通知,因此我添加了(change) 事件绑定。我们不应该这样做......我们应该能够将双向数据绑定分解为[ngModel]="selectedDevice" and (ngModelChange)="onChange($event)",但正如我发现的那样,onChange() 会因为每次选择列表更改而被调用两次.
    • @HongboMiao,特殊的$event 变量/符号是Angular 模板语句所具有的“语句上下文”的一部分。相反,如果我写了(ngModelChange)="onChange('abc')",那么newValue 将得到字符串abc。这只是普通的 JavaScript 函数调用。
    • @HongboMiao,如果您有一个对象数组,请使用 [ngValue]。如果您有一个原始类型数组(字符串、布尔值、整数),请使用 [value]。
    • $event.target.value 类型“EventTarget”上不存在属性“值”??你能为打字稿4提供建议吗
    【解决方案3】:

    我在https://angular.io/docs/ts/latest/guide/forms.html 做 Angular 2 表单教程(TypeScript 版本)时遇到了这个问题

    选择/选项块不允许通过选择其中一个选项来更改选择的值。

    按照 Mark Rajcok 的建议进行操作是可行的,但我想知道我在原始教程中是否遗漏了一些内容,或者是否有更新。无论如何,添加

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

    到 HeroFormComponent 类中的 hero-form.component.ts

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

    &lt;select&gt; 元素中的 hero-form.component.html 使其工作

    【讨论】:

      【解决方案4】:

      只需使用 [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>
      

      【讨论】:

      • 这对我有帮助。不确定我的情况是否略有不同,但对我来说(change)="selectOrg(selectedOrg)" 使用当前/先前选择调用函数 selectOrg,而不是新选择的选项。我想通了,我什至不需要(change) 位。
      • 很好的定位。是的,(更改)通过旧模型是奇怪的行为。我认为这就像 ng-change 也许这是 angular2 中的一个错误。我已将其更新为使用 get 和 set 方法。这样,在 set selectedOrgMod(value) 方法中,我可以知道组织已更改并更新我的组织团队列表。
      【解决方案5】:

      另一种选择是将对象作为字符串存储在值中:

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

      这是我可以让两种方式绑定工作以在页面加载时设置选择值的唯一方法。这是因为填充选择框的列表与我的选择绑定到的对象并不完全相同,它必须是相同的对象,而不仅仅是相同的属性值。

      【讨论】:

        【解决方案6】:

        最新的 ionic 3.2.0 已修改 (change) 为 (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);
        
        }
        

        【讨论】:

          【解决方案7】:
          <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>
          

          我将它用于角度材质下拉菜单。工作正常

          【讨论】:

            【解决方案8】:

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

            【讨论】:

              【解决方案9】:

              在 Angular 6 及更高版本中使用 selectionChange。例子 (selectionChange)= onChange($event.value)

              【讨论】:

              • 我没有使用响应式表单方法。我只需要选择值来触发基于该单个值的服务调用..上述方法帮助了我。
              • 这不再有效,从 Angular 9+ 开始。 $event.value 不再可用
              【解决方案10】:

              Angular 7/8

              从 Angular 6 开始,ngModel 输入属性与反应形式指令的使用已被弃用,并在 Angular 7+ 中完全删除。 Read official doc here.

              使用响应式表单方法,您可以获取/设置所选数据;

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

              【讨论】:

              • 还有没有像 NgModel 这样不被弃用的其他两种方式绑定?
              • 如果你不使用 $event 参数,为什么你的 ts 函数中有这个值?
              【解决方案11】:

              在 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>
              

              【讨论】:

                【解决方案12】:

                我尝试了所有建议,但对我没有任何帮助。

                想象一下这种情况:您需要一个 2-way 绑定,并且您有一个包含 NUMBER 个值的查找,并且您希望使用此查找中的值填充您的 SELECT 并突出显示所选的选项。

                使用 [value] 或 (ngModelChange) 是不行的,因为在用户启动更改后您将无法选择所选选项:[value] 将所有内容视为 字符串,至于 (ngModelChange) - 它显然不应该在用户启动更改时使用,因此它会破坏正确的选择。使用 [ngModel] 保证接收到的 VALUE 的固定格式为 INDEX: VALUE 并且很容易相应地解析它,但是再次 - 它破坏了所选选项。

                所以我们使用 [ngValue](它将处理正确的类型)、(更改)和... [value],它保证处理程序接收 VALUE,而不是 显示值INDEX: VALUE :) 下面是我笨拙的解决方案:

                  <select
                    class="browser-default custom-select"
                    (change)="onEdit($event.target.value)"
                  >
                    <option [value]="">{{
                      '::Licences:SelectLicence' | abpLocalization
                    }}</option>
                    <ng-container *ngIf="licencesLookupData$ | async">
                      <option
                        *ngFor="let l of licencesLookupData$ | async"
                        [ngValue]="l.id"
                        [value]="l.id"
                        [selected]="l.id == selected.id"
                      >
                        {{ l.id }} &nbsp;&nbsp; {{ l.displayName | defaultValue }}
                      </option>
                    </ng-container>
                  </select>
                
                  onEdit(idString: string) {
                    const id = Number(idString);
                    if (isNaN(id)) {
                      this.onAdd();
                      return;
                    }
                    this.licencesLoading = true;
                    this.licencesService
                      .getById(id)
                      .pipe(finalize(() => (this.licencesLoading = false)), takeUntil(this.destroy))
                      .subscribe((state: Licences.LicenceWithFlatProperties) => {
                        this.selected = state;
                        this.buildForm();
                        this.get();
                      });
                  }
                

                【讨论】:

                  【解决方案13】:

                  我也有同样的问题,我用下面的代码解决了:

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

                  【讨论】:

                  • 这在较新版本的 Angular 中不起作用
                  【解决方案14】:

                  从 Angular 7 开始,由于 ngModel 已被弃用,我们可以简单地使用控件以反应方式非常轻松地获取新的选定值。

                  示例:

                  <form [formGroup]="frmMyForm">
                    <select class="form-control" formControlName="fieldCtrl">
                      <option value=""></option>
                      <option value="val1">label val 1</option>
                      <option value="val2">label val 2</option>
                      <option value="val3">label val 3</option>
                    </select>
                  </form>
                  
                  this.frmMyForm.get('fieldCtrl').valueChanges.subscribe( value => {
                    this.selectedValue = value;
                  });
                  

                  通过使用这种完全反应式的方式,我们可以更轻松地将旧 Angular 应用程序版本升级到新版本。

                  【讨论】:

                    猜你喜欢
                    • 2018-06-12
                    • 2016-02-07
                    • 1970-01-01
                    • 2017-10-09
                    • 1970-01-01
                    • 1970-01-01
                    • 2023-04-03
                    • 2019-04-22
                    • 1970-01-01
                    相关资源
                    最近更新 更多