网站搜索

angularjs - 尝试让一个子视图使用 ui-router 调用另一个子视图


我有两个子视图,一个用于类别,一个用于产品,所以用于该类别的产品。我希望用户能够选择一个类别并查看该类别的所有产品。

所以当在分类行上点击 View 按钮时,我会在分类控制器中调用一个函数。

这是函数:

   self.$scope.viewSalonProducts = function (categoryNumber: string) {
       alert(categoryNumber + "   " + self.dataSvc);
       self.dataSvc.category = categoryNumber;
       self.state.go("salonproducts");
   }

这就是我的状态定义的样子:

   .state('master.categoryinfo', {
          url: '/categories',
          views: {
              '': { templateUrl: 'Templates/SalonCategoryMain.html', controller: 'SalonCategoryProductCntrl' },
              "[email ": { templateUrl: 'Templates/SalonCategoryList.html', controller: 'SalonCategoryCntrl' },
              "[email ": { templateUrl: 'Templates/SalonProductList.html', controller: 'SalonProductCntrl' }
           }
     })

在我的 HTML 文件中,我是这样定义这个按钮的:

   <input type="button" name="edit" value="View" class="btn btn-default" ng-click="viewSalonProducts(x)" />

如果有任何差别的话,这是这个视图的俯视图:

Categories
<div ui-view="saloncategories"></div>
Products
<div ui-view="salonproducts"></div>

我的产品控制器是这样定义的,所以

export class SalonProductCntrl {
    private $scope: Extensions.IProductsDisplayScope;
    private dataSvc: giftCertDataSvc;

    private init(): void {
        var self = this;
        self.dataSvc.getProductsBySalon().then(function (data) {
            self.$scope.products = data;
        });
    }

    constructor($scope: Extensions.IProductsDisplayScope, giftCertDataSvc: giftCertDataSvc) {
        this.$scope = $scope;
        this.dataSvc = giftCertDataSvc;
        this.init();
    }
}

所以,如果用户点击按钮,我想将类别名称(即我按钮的 ng-click 中 x 的值)传递给产品控制器,然后让它调用 Web 服务来获取并显示信息。

是否会让 scope.watch,https://docs.angularjs.org/api/ng/type/$rootScope.Scope,那么我只需要看看如何将类别放入产品控制器的作用域中。

答案#1

使用 UI-Router 我们不必使用 $scope.watch 在 list-detail 视图之间进行通信。

这里的原生 UI-Router 解决方案是使用 父子状态 定义。因此,状态定义应该像这样:

.state('master.categoryinfo', {
      url: '/categories',
      views: {
          '': { 
             templateUrl: 'Templates/SalonCategoryMain.html', 
             controller: 'SalonCategoryProductCntrl' 
          },
          // these views will be replaced by child state
          "[email ": { 
             template: 'here will be category details', 
          },
          "[email ": {
             template: 'here will be salon product details', 
          }
       }
 })

.state('master.categoryinfo.detail', {
      url: '/:productId',
      views: {
          // this notation in a child
          // "[email ": {  
          // is the same as this
          "saloncategories": { 
             templateUrl: 'Templates/SalonCategoryList.html', 
             controller: 'SalonCategoryCntrl' 
          },
          "salonproducts": {
             templateUrl: 'Templates/SalonProductList.html', 
             controller: 'SalonProductCntrl' 
          }
       }
 })

这将是新的控制器定义:

export class SalonProductCntrl 
{    
    private init(): void 
    {
        this.dataSvc
            // here we can pass the product Id
            .getProductsBySalon(this.$stateParams.productId)
            // here we use arrow function 
            // which does take care for us about this
            .then((data) => {
                this.$scope.products = data;
            });
    }
    // this notation will do the same - all params will be private
    // available via this.
    constructor(private $scope: Extensions.IProductsDisplayScope
              , private $stateParams: ng.ui.IStateParamsService
              , private giftCertDataSvc: giftCertDataSvc) 
    {
        this.init();
    }

    static $inject = ['$scope', '$stateParams', 'giftCertDataSvc'];
}

这样我们就可以把它挂接到 AngularJS 中:

angular
   .module('MyModule')
   .controller('SalonProductCntrl', SalonProductCntrl); 

这只是一个草稿版本,但重点是——将列表视图(用户选择项目ID的地方)和详细视图分成独立的状态。

好处应该很清楚,因为任何 productId 的变化都会触发新的状态转换。子数据会被改变(更新),而列表会保持不变……我会说,这就是 UI-Router 的本质