问题 angular.js,无法编辑动态创建的输入字段


使用angular.js,我有一个动态的表单字段列表,我想显示给用户进行编辑(以及以后的提交):

var app = angular.module('app', []);
app.controller('Ctrl', function($scope) {
    $scope.fields = {
        foo: "foo",
        bar: "bar",
        baz: "baz"
    };
});

和HTML:

<div ng-app="app" ng-controller="Ctrl">
    <table>
        <th>key</th>
        <th>value</th>
        <th>fields[key]</th>
        <tr ng-repeat="(key,value) in fields">
            <td>{{key}}:</td>
            <td><input type="text" ng-model="value"/></td>
            <td><input type="text" ng-model="fields[key]"/></td>
        </tr>
    </table>
</div>

看到 这个小提琴。由于我不理解的原因,文本输入框不可编辑。我已经尝试了两种不同的方法,如上所示: value 和 fields[key]value 根本不可编辑,并且 fields[key] 会允许  击键,然后它模糊。我究竟做错了什么?谢谢。


2781
2018-02-27 18:03


起源

它是可编辑的,但在每个键之后按下你的文本字段失去焦点,这样你就必须再次点击它以放入另一个字符 - SET
这种情况发生在整个模板中,在每个模型中的每次更改后都会重新渲染。模板重新渲染后,目前无法知道应该关注哪个输入。所以你应该创建这种方式,你可能想写指令来关注选定的输入。 - SET
谢谢@SET,这完全有道理,你应该做出答案! - Steve Kehlet
可能重复 ng-model,ng-repeat和输入有困难 - Mark Rajcok
谢谢@Mark Rajcok,我的问题肯定是那个问题的一个子集,并且有一些很好的解释。 - Steve Kehlet


答案:


它是可编辑的,但在每个键之后按下你的文本字段失去焦点,这样你就必须再次点击它以放入另一个字符。

这是因为整个模板在任何模型中的每次更改后都会重新渲染。模板重新渲染后,目前无法知道应该关注哪个输入。所以你应该创建这种方式,你可能想写指令来关注选定的输入。


3
2018-02-27 18:42



在我提供的答案中(它使用一组对象),输入字段在输入时不会失去焦点,但模型正在改变。你知道为什么吗 fields[key] 导致重新渲染,但不是 field.value? - Mark Rajcok
@MarkRajcok,这实际上是我要问你的。不,我不愿意,但不愿意。此外,在我找到真正有效的阵列解决方案之后,我想我的帖子不应该被选为答案。 - SET
@SET你的答案立即解释了问题所在并回答了我的问题“我做错了什么?”所以我会把答案归功于你。再次感谢! - Steve Kehlet


SET回答了为什么会发生这种情况,但实现所需行为的解决方法是维护一个单独的密钥数组,然后运行ng-repeat off这些密钥。我添加了一些文本字段用于测试以添加更多属性 $scope.fields

如果您的要求是字段数可能会发生变化,您可以使用$ watch在属性计数更改时动态设置密钥。

http://jsfiddle.net/aERwc/10/

标记

<div ng-app="app" ng-controller="Ctrl">
    <table>
        <th>key</th>
        <th>value</th>
        <tr ng-repeat="key in fieldKeys">
            <td>{{key}}:</td>
            <td><input type="text" ng-model="fields[key]"/></td>
        </tr>
    </table>
    <div><h6>Add a field</h6>
        key: <input type="text" ng-model="keyToAdd" /><br />
        value: <input type="text" ng-model="valueToAdd" />
        <button ng-click="addField()">Add Field</button>
    </div>
</div>

调节器

var app = angular.module('app', []);

app.controller('Ctrl', function($scope) {
    $scope.fields = {
        foo: "foo",
        bar: "bar",
        baz: "baz"
    };
    $scope.fieldKeys = [];

    $scope.setFieldKeys = function() {
        var keys = [];
        for (key in $scope.fields) {
            keys.push(key);
        }
        $scope.fieldKeys = keys;
    }

    $scope.addField = function() {
        $scope.fields[$scope.keyToAdd] = $scope.valueToAdd;
        $scope.setFieldKeys();
        $scope.keyToAdd = '';
        $scope.valueToAdd = '';
    }

    $scope.setFieldKeys();
});

5
2018-02-27 18:52



这正是我要做的解决方法。太棒了谢谢! - Steve Kehlet
+1:这解决了问题,而无需更改数据模型。该 setFieldKeys方法可以替换为 $scope.fieldKeys = Object.keys(data); 我相信。 - mnemosyn


您需要使用一组对象。希望你可以修改你的模型:

$scope.fields = [
   {label: "foo", value: "foov"},
   {label: "bar", value: "barv"},
   {label: "baz", value: "bazv"}
];

<tr ng-repeat="field in fields">
  <td>{{field.label}}:</td>
  <td><input type="text" ng-model="field.value">

小提琴


3
2018-02-27 18:42



谢谢!我也喜欢这种方式,作为@ Coder1给出的答案的更多封装替代方案。无论我现在看到什么,我都必须以某种方式从服务器转换数据。我担心这种方法是利用有意或无意的Angular,它不会对观察者进行深入检查 fields 数组(我可能不正确的结论如何工作),这可能会在未来发生变化。 - Steve Kehlet