How to make dynamically linked AngularJS models inside nested ng-repeat, without throwing an error until the model is provided with data from another place?

Problem

jsFiddle Demonstration of the problem

http://jsfiddle.net/7sfaB/

I had a situation where I used AngularJS where I create a set of nested <ul> using ng-repeat with nested ng-repeat from a configuration service that contains a list structure. Inside this ng-repeat nested, I'm trying to use one complex model object, building the model dynamically based on the properties in the configuration service and binding to the input field. (eg 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 I am facing is that if you try to edit the text field in the list, you will get the Cannot set property 'notes' of undefined error message on the console.

Interestingly, if you create an input field outside of ng-repeat that has an explicit model defined for one of the same bindings that was built dynamically, then the binding starts working even inside dynamically built models.

 <p> Treasure Island Notes (dot syntax):<input type="text" ng-model="data.books.treasure_island.notes"/> </p> 

Question

What is the correct way to install dynamically linked ng models so that it is immediately anchored and edited without the need for explicit model bindings? I was not sure if there was anything I needed to call in order to reregister the bindings after the ng-repeat loops completed.

Thanks in advance for any help you can provide.


For reference

Here is the configuration service that defines the structure of 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 that receives the data from the service:

 app.controller('MainCtrl', function ($scope, configSvc) { $scope.categoryConfig = $.extend({}, configSvc); }); 
+4
source share
1 answer

The problem (at least with your script) is that you are trying to bind to data[category.id][item.id].notes without:

$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 this problem, after loading data from the service, you need to execute the $ scope.data cycle and create each key that you want as an object. You can do the following (tested and working):

 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] = {}; }); }); }); 
+2
source

Source: https://habr.com/ru/post/1484761/


All Articles