如何从嵌套的ng-repeat

时间:2017-02-21 20:10:31

标签: javascript angularjs angularjs-ng-repeat angularjs-service

我正在AngularJs制作一个简单的体育用品购物应用程序。

我的情况是我有三个嵌套的ng-repeats。

第一次循环:获取品牌名称。我写了angularjs服务,调用其余端点来获取品牌列表(Adidas,Yonex,Stiga等)。我在页面(控制器)加载后立即调用此服务。

第二次循环:对于每个品牌,我想显示他们提供的产品类别。在这个循环中,我想要执行一个功能/服务,它将品牌名称作为输入,并获得该品牌的所有类别。为此,我还有一个angularjs服务,它调用其余端点来获取给定品牌名称的类别列表。

第三次循环:对于每个品牌和类别,我想显示该类别中的产品。在这个循环中,我想执行一个函数,它将品牌名称和类别作为输入,并获得该类别中的所有产品。我是一个angularjs服务调用,它将调用其余端点来获取给定品牌名称和类别的产品。

示例数据集

Adidas
-----T-Shirts
----------V-Neck
----------RoundNeck
-----Shoes
----------Sports Shoes
----------LifeStyle Shoes
Yonex
-----Badminton Racquet
----------Cabonex
----------Nanospeed
-----Shuttlecocks
----------Plastic
----------Feather
Stiga
-----Paddle
----------Procarbon
----------Semi-carbon
-----Ping Pong Balls
----------Light Weight
----------Heavy Weight

请注意,由于某些限制,我不能在REST端拥有域对象来模仿上面显示的数据结构。

我希望以类似树的方式显示上述数据(可能与展开/折叠选项相同,如上所示)。 以下是代码段。

控制器:

(function () {
    'use strict';
    angular.module('SportsShoppingApp.controllers').controller('sportsController', ['sportsService', '$scope', function (sportsService, $scope) {

        $scope.brands = [];
        $scope.categories = [];
        $scope.products = {};

        $scope.getBrands = function () {
            sportsService.getBrands()
                .then(loadBrands, serviceError);
        };

    var loadBrands = function(response) {
        $scope.brands= response.data;
    };


        $scope.getCategories = function(brand) {
            sportsService.getCategories(brand)
                .then(loadCategories, serviceError);
        };

    var loadCategories = function (response) {
            $scope.categories = response.data;
        };


        $scope.getProducts = function(brand, category) {
            sportsService.getProducts(brand, category)
                .then(loadProducts, serviceError);
        };

    var loadProducts = function (response) {
            $scope.products = response.data;
        };

        var serviceError = function (errorMsg) {
            console.log(errorMsg);
        };

    $scope.getBrands();

    }]);
}()); 

HTML:

<div class="well">
    <div class="row">
        <div id="sportsHeader" class="col-md-3">
            <div ng-repeat="brand in brands.data">
                <div class="row">
                    <div class="col-md-9">{{brand}}</div>
                </div>
                <div ng-repeat="category in categories.data" ng-init="getCategories(brand)">
                    <div class="row">
                        <div class="col-md-9">{{category}}</div>
                    </div>
                    <div ng-repeat="product in products.data" ng-init="getProducts(brand, category)">
                        <div class="row">
                            <div class="col-md-9">{{product}}</div>
                        </div>
                    </div>  
                </div>  
            </div>
        </div>
    </div>
</div> 

当我使用上述HTML时,UI上只显示品牌名称。不显示类别及其相应的产品。我知道正在发生一些重叠。我不确定我是否正确地做到了这一点。我的方法可能完全错了。我是AngularJS的新手。我想知道如何在嵌套的ng-repeat中循环,以便每个ng-repeat可以调用angularjs服务,并且我还想以树形方式显示数据,如上所示。有人可以帮助我吗?

2 个答案:

答案 0 :(得分:0)

我认为ng-init必须放在ng-repeat s的单独标签上:

<div class="well">
    <div class="row">
        <div id="sportsHeader" class="col-md-3">
            <div ng-repeat="brand in brands.data">
                <div class="row">
                    <div class="col-md-9">{{brand}}</div>
                </div>
                <div ng-init="getCategories(brand)">
                    <div ng-repeat="category in categories.data">
                        <div class="row">
                            <div class="col-md-9">{{category}}</div>
                        </div>
                        <div ng-init="getProducts(brand, category)">
                            <div ng-repeat="product in products.data">
                                <div class="row">
                                    <div class="col-md-9">{{product}}</div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div> 

你可能也需要同时处理你的引导类,移动ng-init只是为了修复角部分。

答案 1 :(得分:0)

ng-init指令移到他们提供数据的ng-repeat之外。

<div class="well">
    <div class="row">
        <div id="sportsHeader" class="col-md-3">
            <!-- MOVE init of categories here -->
            <div ng-repeat="brand in brands.data"  ng-init="getCategories(brand)">
                <div class="row">
                    <div class="col-md-9">{{brand}}</div>
                </div>
                <!-- MOVE init of products here -->
                <div ng-repeat="category in categories.data"  ng-init="getProducts(brand, category)">
                    <div class="row">
                        <div class="col-md-9">{{category}}</div>
                    </div>
                    <div ng-repeat="product in products.data">
                        <div class="row">
                            <div class="col-md-9">{{product}}</div>
                        </div>
                    </div>  
                </div>  
            </div>
        </div>
    </div>
</div> 

ng-init指令的优先级为450; ng-repeat,优先级为1000.这意味着当它们位于同一元素上时ng-init执行 ng-repeat指令后的ng-repeat的{​​{1}}不会执行其categories.data,直到它有一个类别。因此,ng-init不能用于填充ng-init数组。

  

快速提问。我的方法是否正确?

该方法有效,但它违反了Zen of AngularMV* Model View Whatever框架的原则。

  

模型是Single Source of Truth

     

因为视图只是模型的投影,所以控制器与视图完全分离并且不知道它。这使得测试变得简单,因为在没有视图和相关的DOM /浏览器依赖性的情况下,可以轻松地单独测试控制器。

     

--AngularJS Developer Guide -- Data-Binding

使用categoriesng-repeat指令构建模型会创建一个依赖项,使测试和调试变得困难。 (正如这个问题所证明的那样。)

我的建议是学习如何chaining promises并使用$q.all来构建模型。