关于 javascript:AngularJS ngChange 指令触发两次

AngularJS ngChange directive firing twice

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

在链接的 plunker 中,我列出了 3 个产品,每个产品都有一个选择框。

每个产品都有一组记录。如果我要从"产品一"行中选择一条记录,我希望在其他两个产品行选择框中禁用"记录一",但这并没有发生。

似乎 ngChange 指令被触发了两次,但我不确定为什么。也许是因为我正在更改禁用状态?

如果它应该触发两次是正确的,那么我不确定它为什么取消选择该值并将该字段再次设置为空白?

HTML:

1
2
3
4
5
6
7
8
9
10
11
  <head>
    <script data-require="[email protected]" data-semver="1.6.5" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js">
    <link rel="stylesheet" href="style.css" />
  </head>

  <body>
    <my-component></my-component>
    <script src="script.js">
  </body>

</html>

JS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
angular
  .module('app', [])
  .component('myComponent', {
    template: `
     
       
         {{ productField.label }}
       
       
          <select
            ng-model="productField.recordKey"
            ng-options="recordField.key as recordField.label disable when recordField.disabled for recordField in productField.recordFields"
            ng-change="$ctrl.mappingFieldChange()">
          </select>
       
     
    `,
    controller: function() {
      $ctrl = this

      this.selectedProduct = {
        productFields: [
          {
            key: 'one',
            label: 'Product One',
            recordFields: [
              {
                key: 'one',
                label: 'Record One',
                disabled: false,
              },


    {
            key: 'two',
            label: 'Record Two',
            disabled: false,
          },
          {
            key: 'three',
            label: 'Record Three',
            disabled: false,
          },
        ],
      },
      {
        key: 'two',
        label: 'Product Two',
        recordFields: [
          {
            key: 'one',
            label: 'Record One',
            disabled: false,
          },
          {
            key: 'two',
            label: 'Record Two',
            disabled: false,
          },
          {
            key: 'three',
            label: 'Record Three',
            disabled: false,
          },
        ],
      },
      {
        key: 'three',
        label: 'Product Three',
        recordFields: [
          {
            key: 'one',
            label: 'Record One',
            disabled: false,
          },
          {
            key: 'two',
            label: 'Record Two',
            disabled: false,
          },
          {
            key: 'three',
            label: 'Record Three',
            disabled: false,
          },
        ],
      },
    ]
  }

  $ctrl.mappingFieldChange = () => {
    console.log('mappingFieldChange')
    const fieldsMapped = getSelectedFields()

    $ctrl.selectedProduct.productFields.forEach((productField) => {
      // Disable the record keys that are selected and enable any others
      productField.recordFields.forEach(recordField => {
        if (fieldsMapped.indexOf(recordField.key) >= 0) {
          recordField.disabled = true
        }
        else {
          recordField.disabled = false
        }
      })
    })
  }

  function getSelectedFields() {
    let fieldsMapped = []

    // Create an array of record field keys that are already selected
    $ctrl.selectedProduct.productFields.forEach((productField) => {
      if (productField.recordKey) {
        fieldsMapped.push(productField.recordKey)
      }
    })

    return fieldsMapped
  }
},

})


因为我禁用了被选中的值,AngularJS 然后 null 输入值(null 禁用值是在 1.6 中引入的),因此选择框将保持空白。

为了解决这个问题,我为选择它的产品行保留了启用值,但在其他行中禁用了它。

更新后的 mappingChange 函数现在如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ctrl.mappingFieldChange = () => {
  console.log('mappingFieldChange')
  const fieldsMapped = getSelectedFields()

  $ctrl.selectedProduct.productFields.forEach((productField) => {
    // Disable the record keys that are selected and enable any others
    productField.recordFields.forEach(recordField => {
      if (productField.recordKey === recordField.key) {
        recordField.disabled = false
      }
      else if (fieldsMapped.indexOf(recordField.key) >= 0)
        recordField.disabled = true
      }
      else {
        recordField.disabled = false
      }
    })
  })
}