问题
The Problem
jsFiddle Demonstrating the problem
http://jsfiddle.net/7sfaB/
I have a situation I've run into in using AngularJS where I'm building a set of nested <ul>
using ng-repeat
with a nested ng-repeat
from a config service that contains the structure of the lists. Within this nested ng-repeat
, I am attempting to use a single complex model object by building the model dynamically based on properties within the config service and binding to an input field. (e.g. ng-model="data[category.id][item.id].notes"
)
Here is the HTML template:
<ul>
<li id="{{category.id}}" ng-repeat="category in categoryConfig.categories">
<h3>{{category.title}}</h3>
<ul>
<li ng-repeat="item in category.items">
<p>{{item.title}} : Notes: <input type="text" ng-model="data[category.id][item.id].notes"/></p>
<p>{{data[category.id][item.id].notes}}</p>
</li>
</ul>
</li>
</ul>
The problem that I'm experiencing is that if you try to edit the text field within the list, you will get Cannot set property 'notes' of undefined
error on the console.
Interestingly, if you create an input field outside of the ng-repeat
that has an explicit model defined to one of the same bindings that was built dynamically, then the binding starts working even within the dynamically built models.
<p>
Treasure Island Notes (dot syntax):<input type="text" ng-model="data.books.treasure_island.notes"/>
</p>
The Question
What is the proper way to setup dynamically bound ng-models so that it is immediately bound and editable without having to create explicit model bindings? I wasn't sure if there was something I needed to call to make it reregister the bindings after the ng-repeat
loops were finished.
Thanks in advance for any help you can provide.
For Reference
Here is the config service that defines the structure of the nested lists:
var app = angular.module('testApp', []);
app.factory('configSvc', function(){
return {
categories: [
{
id: 'books',
title: 'Books',
items:[
{
id: 'treasure_island',
title: 'Treasure Island'
},
...
]
},
{
id: 'appliances',
title: 'Household Appliances',
items:[
{
id: 'toaster',
title: 'Toaster'
},
...
]
}
]
}
})
And the Controller which gets the data from the service:
app.controller('MainCtrl', function ($scope, configSvc) {
$scope.categoryConfig = $.extend({}, configSvc);
});
回答1:
The problem (at least with your Fiddle) is that you are trying to bind to data[category.id][item.id].notes
without either:
$scope.data
existing or being an object
without $scope.data[category.id]
existing or being an object
and without $scope.data[category.id][item.id]
existing and being an object.
To solve it, after you load your data from the service, you need to loop through $scope.data and create every key you want as an object. You can do the following (verified and it works):
app.controller('MainCtrl', function ($scope, configSvc) {
$scope.data = {};
$scope.categoryConfig = $.extend({}, configSvc);
angular.forEach($scope.categoryConfig.categories, function (category) {
$scope.data[category.id] = {};
angular.forEach(category.items, function (item) {
$scope.data[category.id][item.id] = {};
});
});
});
来源:https://stackoverflow.com/questions/16954396/how-to-make-dynamically-bound-angularjs-models-within-nested-ng-repeat-not-throw