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] позволит один нажатие клавиши, а затем оно размывается. Что я делаю не так? Спасибо.

Ответ 1

Это редактируется, но после каждого нажатия клавиши ваше текстовое поле теряет фокус, так что вам нужно снова щелкнуть по нему, чтобы добавить еще один char.

И это происходит потому, что весь ваш шаблон повторно отображается после каждого изменения в любой из моделей. И после повторной обработки шаблона, в настоящее время нет способа узнать, какой вход должен быть сфокусирован. Таким образом, вы должны создать этот путь, и вы можете захотеть написать директиву, чтобы сосредоточиться на выбранном входе.

Ответ 2

SET ответил на вопрос, почему это происходит, но для достижения желаемого поведения нужно поддерживать отдельный массив ваших ключей и запускать ng-repeat с этих клавиш. Я добавил некоторые текстовые поля для тестирования, чтобы добавить дополнительные свойства в $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();
});

Ответ 3

Вам нужно использовать массив объектов. Надеюсь, вы сможете переделать свою модель:

$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">

Fiddle.