Raimonds Raimonds - 2 months ago 7
AngularJS Question

AngularJS - no two way binding for key-value object

Just for note, I know nothing about angularJS, I worked with knockoutJS before and when it comes to angular I am just making assumptions.

I have code like this:

angular.module("umbraco").controller("recallCtrl",
function ($scope, $routeParams) {

$scope.dcList = {
key: "value",
abc: "aaaa",
prop: "tadaa!"
}
});


and markup as follows:

<div ng-controller="recallCtrl">
<table class="table table-sm">
<thead>
<tr>
<td></td>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tr ng-repeat="(key, value) in dcList">
<td>

</td>
<td>
<input ng-model="key" />
</td>
<td>
<input ng-model="value"/>
</td>
</tr>

</table>

<pre>{{dcList | json}}</pre>
</div>


So shouldn't output of
dcList
in the end of html change it's values when I edit corresponding inputs which as I assume are bound to object?

If I am doing something wrong, please advise. I want to create object and be able to change its keys and values.

Answer

The reason your current code isn't working is because inside the ng-repeat "key" and "value" turn into primitives, so no longer refer to the original object.

Keeping the "values" attached is easy, just use dcList[key] instead of value. Adding new keys takes a bit more work; here I've attached an ng-blur to each "key" field which will init a new key when the field blurs. (ng-change would create a new field on every keystroke, which isn't what you want.) Note that when you start typing a new key, its value appears to disappear -- this is because the dcList[key] refers to the new key name immediately. This would be somewhat confusing in a real UI, of course; you'd probably want to code different behavior into the createNewKey function (such copying the old value into the new key, or deleting the original key).

function recallCtrl($scope) {
    $scope.dcList = { 
        key: "value",
        abc: "aaaa",
        prop: "tadaa!"
    }
    
    $scope.createNewKey = function(k) {
      $scope.dcList[k]="";
    }

  }
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<div ng-controller="recallCtrl">
    <table class="table table-sm">
        <thead>
            <tr>
                <th>Key</th>
                <th>Value</th>
            </tr>
        </thead>
        <tr ng-repeat="(key, value) in dcList">
            <td>
                <input ng-model="key" ng-blur="createNewKey(key)"/>
            </td>
            <td>
                <input ng-model="dcList[key]"/>
            </td>
        </tr>
    </table>

    <pre>{{dcList | json}}</pre>
  </div>