How to make dynamically bound AngularJS models within nested ng-repeat not throw an error until the model is supplied data from somewhere else?

廉价感情. 提交于 2019-12-22 09:18:10

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!