10

I am rendering key:value object array with ng-repeat like this:

<div ng-controller="mainCtrl">    
  <div ng-repeat="record in records">
    <div ng-repeat="(key, value) in record">
        <input ng-model="key" />: <input ng-model="value" />
    </div>
  </div>
</div>

JS:

var mainCtrl = function($scope){
$scope.records = [
        {'key1':'val1'},
        {'key2':'val2'}
        ];
}

Problem is that keys and values cannot be updated through input tags. For some reason it becomes one way binding after making ng-repeat iterate over (key,value).

Fiddle: http://jsfiddle.net/BSbqU/1/

How can I make it a two way binding? Or should I approach this problem in a different way then nested ng-repeat?

Sergej Popov
  • 2,933
  • 6
  • 36
  • 53

3 Answers3

7
<div ng-controller="mainCtrl">    
<div ng-repeat="record in records">

        <input ng-model="record.name" />: <input ng-model="record.value" />
    </div>
</div>

And the JS:

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

var mainCtrl = function($scope){
$scope.records = [
{'name':'key1','value':'val1'},
{'name':'key2', 'value':'val2'}
        ];
}
Jason
  • 309
  • 2
  • 14
  • This makes input fields editable, BUT the changed value doesn't update the model. So the binding remains one way. Fiddle: http://jsfiddle.net/BSbqU/2/ – Sergej Popov May 11 '13 at 11:35
  • Gotcha, something to do with using key as ng-model, though I was able to get it to work by assigning name and value and removing the inner repeat, hold on , getting jsfiddle to work. – Jason May 11 '13 at 11:43
  • Very interesting how you do it without inner repeat, but the fiddle you have given isn't updated.. – Sergej Popov May 11 '13 at 11:46
  • Updated answer, jsfiddle isn't cooperating with me this morning. – Jason May 11 '13 at 11:49
  • 1
    Ok, this involves change in model structure . Which I could do but not exactly keen on doing. +1. – Sergej Popov May 11 '13 at 11:53
  • Oh, highly recommend you using that object structure. However, read this: http://stackoverflow.com/questions/15119086/angular-js-cant-edit-dynamically-created-input-fields – Jason May 11 '13 at 11:57
6

This option works with object:

<div ng-controller="mainCtrl">    
  <div ng-repeat="record in records">
    <div ng-repeat="(key, value) in record">
        <input ng-model="key" />: <input ng-model="record[key]" />
    </div>
  </div>
</div>

Not a brilliant, but it works.

vlad
  • 89
  • 1
  • 4
0

After scratching my head to the bone, i find a way to update object key names. It is a bit twisted but it works for me.

replace

<input ng-model="key" />

with

<input type="text" ng-model="key" ng-change="update_key(record,key,$index)" line-key/>

you will need the 'lineKey' directive just to keep focus on your input

var app = angular.module('myApp',[]);
var focus_key=-1;
app.directive('lineKey', function () {
    return function (scope, element, attrs) {
        if(focus_key==scope[attrs.ngModel]){
            focus_key=-1;
            element[0].focus();
        }
    };
});

finally, add the 'update_key' method to your controller

app.controller('mainCtrl',['$scope'],function($scope){
        $scope.records = [
        {'key1':'val1'},
        {'key2':'val2'}
    ];
    $scope.update_key=function(obj,new_key,id){
        var keys    = Object.keys(obj);
        var values  = Object.values(obj);
        var old_key = keys[id];
        if(keys.indexOf(new_key)==-1&&new_key.length>0){
            // clear ...
            for(var i=0,key;key=keys[i];i++){   delete obj[key];    }
            keys[id]=new_key;//... change key value ...
            focus_key=new_key;//... notify to keep focus on modifyed input ...
            // ... and refill to preserve the position in the object list
            for(var i=0,key;key=keys[i];i++){   obj[key]=values[i]; }
        }
    };
}
yorg
  • 600
  • 5
  • 7