Angular 2数据绑定中断

时间:2017-02-06 16:04:29

标签: angular

我正在编写一个由多行组成的小组件,每行包含:

  1. 下拉有两个可能的选择 - 将其命名为“type”
  2. 输入框 - 将其命名为“key”
  3. 输入框/下拉列表取决于“类型”(第一个下拉列表中的值) - 将其命名为“value”
  4. 预期的行为是:

    1. 当用户从第一个下拉列表中选择“常量”时,第三个元素应该是一个输入框。如果它是“变量”,它应该成为一个下拉列表。
    2. 如果用户输入“key”和“value”字段,则新行应显示为另一个条目。只要“密钥”或“值”发生变化,就应该触发这种行为。
    3. 如果用户从不是最后一行的行中删除“key”或“value”,则应删除此行。只有当“键”或“值”失去焦点时才会发生这种情况。
    4. 我创建了这样的东西: sample on plunker

      @Component({
        selector: 'my-app',
        template: `
      <div *ngFor="let rec of records">
        <select style="width: 75px;" class="select-field" [(ngModel)]="rec.type" (ngModelChange)="onTypeChange(rec)">
          <option *ngFor="let type of rec.types">{{type}}</option>
        </select>
      
        <input type="text" class="input-fields" [(ngModel)]="rec.key" (ngModelChange)="onValueChange(rec)" (blur)="onFocusLost(rec)"/>
      
        <input *ngIf="rec.type == 'Constant'" type="text" class="input-fields" [(ngModel)]="rec.value" (ngModelChange)="onValueChange(rec)" (blur)="onFocusLost(rec)"/>
        <span *ngIf="rec.type == 'Variable'">
            <select style="width: 75px;margin-left: 10px;" class="select-field" [(ngModel)]="rec.value" (ngModelChange)="onValueChange(rec)" (blur)="onFocusLost(rec)">
              <option></option>
              <option *ngFor="let field of fields">{{field}}</option>
            </select>
          </span>
      </div>
        `,
      })
      
      export class App {
      records: FieldSelectionRecord[] = [new FieldSelectionRecord()];
      fields: string[] = ['foo1', 'foo2'];
      
        onTypeChange(record: FieldSelectionRecord) {
          record.value = "";
        }
      
        onValueChange(changedRecord: FieldSelectionRecord) {
          if (this.isLastElement(changedRecord) && this.isRecordFullyFilled(changedRecord)) {
            this.records.push(new FieldSelectionRecord());
          }
        }
      
      
      
        onFocusLost(changedRecord: FieldSelectionRecord) {
          if (!this.isLastElement(changedRecord) && !this.isRecordFullyFilled(changedRecord)) {
            this.records = this.records.filter(record => record != changedRecord);
          }
        }
      
        private isLastElement(record: FieldSelectionRecord): boolean {
          let index = this.records.indexOf(record);
          return this.records.length - 1 === index;
        }
      
        private isRecordFullyFilled(record: FieldSelectionRecord): boolean {
          return record.value.length > 0 && record.key.length > 0;
        }
      
      }
      

      虽然它并没有按预期工作。例如,如果您同时放置键和值,则会显示新行。当您单击上一行并将其“类型”更改为变量时,它不会将“值”更改为下拉列表。同时删除前一行也不起作用。我正在调试它,我相信基础值正在改变,但视图没有更新。

      令人惊讶的是,我有一个不同的组件,完全相同,没有使用“键” - 只有“类型”和“价值”,它的工作完美。 Working sample here

      唯一的区别是缺少这一行:

      <input type="text" class="input-fields" [(ngModel)]="rec.key" (ngModelChange)="onValueChange(rec)" (blur)="onFocusLost(rec)"/>
      

      和isRecordFullyFilled方法。

      我尽量不使用双向绑定,但它也没有帮助。我在这做错了什么?

1 个答案:

答案 0 :(得分:1)

如果您查看浏览器控制台,您会发现错误:

  

VM3717 core.umd.js:3066 ORIGINAL EXCEPTION:无法读取属性   &#39;长度&#39;未定义的

因此,在阅读value

之前,请尝试检查length
private isRecordFullyFilled(record: FieldSelectionRecord): boolean {
  return record.value && record.value.length > 0 && record.key.length > 0;
}

https://plnkr.co/edit/MbmX6G5ufr5HNGWzyMZv?p=preview