嵌套指令/控制器的角度

时间:2014-12-02 18:14:39

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

刚刚开始围绕Angular - 我没有理解一些概念,因为我来自Backbone学派。

我选择了一个随机项目开始:纸牌游戏。

假设我想要定义一个hand控制器和一个card控制器。为简单起见,我希望将它们作为指令。

这是卡指令:

app.directive('card', function(){

    return {
        restrict:'E',
        templateUrl:'card.html',
        controller:function($scope){
            this.suit = 'clubs';
            this.rank = 'a';
            this.suitClass = function(){
                return this.suit + '-' + this.rank;
            }
        },
        controllerAs:'card'
    };
});

这是手指令:

app.directive('hand', function(){

    return {
        restrict:'E',
        template:'hand.html',
        controller:function($scope){
            this.cards = [
                {suit:'clubs', rank:'a'},
                {suit:'spades', rank:'10'},
                {suit:'hearts', rank:'2'},
                {suit:'diamonds', rank:'k'}
            ];
        },
        controllerAs:'hand'
    }
});

使用following plunker,我希望能够简单地放入<hand></hand>元素并让角度为我完成所有工作。在我看来,应该有代表嵌套在<hand>指令中的不同套装的牌。我错过了什么?目前,正如您在plunker中所知,嵌套的控制器/指令不能正确地实例化视图。

我是否考虑过过多的MVC方式? OOP困扰我吗?或者角度设计得很糟糕?

2 个答案:

答案 0 :(得分:0)

我不是百分百肯定我理解你的问题,但我认为这是一个更好的写作方式:

var app = angular.module('app', []);

app.directive('card', function(){

    return {
        restrict:'E',
        templateUrl:'card.html',
        replace: true,
        link: function ($scope, element, attrs){
            $scope.suit = 'clubs';
            $scope.rank = 'a';
            $scope.suitClass = function(){
                return this.suit + '-' + this.rank;
            }
        }
    };
});

app.directive('hand', function($compile){

    return {
        restrict:'E',
        templateUrl:'hand.html',
        link:function($scope, element, attrs){
            $scope.cards = [
                {suit:'clubs', rank:'a'},
                {suit:'spades', rank:'10'},
                {suit:'hearts', rank:'2'},
                {suit:'diamonds', rank:'k'}
            ];
        }
    }
});

html可以是这样的: (手工指令模板)

<div>
  <card ng-repeat="card in cards"></card>
</div>

(卡指令模板)

<div ng-class="card.suitClass()">
{{ suit }}
</div>

答案 1 :(得分:0)

我将通过自上而下调整将要调用的元素/对象的顺序来解释这个问题:

手指令:

目前该指令还可以。但是$ compile参数和$ scope参数未被使用,应该被删除。为了更清楚,我将它应用于变量指针,但它不会改变应用程序的行为。

app.directive('hand', function(){

  return {
    restrict:'E',
    templateUrl:'hand.html',
    controller:function() {
      var hand = this;
      hand.cards = [
        {suit:'clubs', rank:'a'},
        {suit:'spades', rank:'10'},
        {suit:'hearts', rank:'2'},
        {suit:'diamonds', rank:'k'}
      ];
    },
    controllerAs:'hand'
  }
});

<强> hand.html:

您从未将ng-repeat的当前卡传递给卡指令。 这样,您只能生成卡片模板乘以卡片数量但从不使用实际值。

我删除了过时的div标签并将hand.html增强到:

<card ng-repeat="card in hand.cards" card-model="card"></card>

这样我就可以从卡片指令中的手牌视图中获取每张卡片。

卡指令:

首先我删除$ scope变量,因为它从未使用过,并且不会在这里使用。

此功能相当不完整。至少它缺少你想要使用的卡值。但是这里的一个主要问题是这个上下文与调用者绑定。更确切地说,您在suitClass函数中使用了这个,但是您想要使用控制器的套装和等级值。这并不是指向控制器功能,而是指向新创建的suitClass函数,该函数不知道这些值中的任何一个。对于该问题,您应该引入一个保存上下文的变量并以这种方式访问​​值。然后我添加绑定到element属性的范围变量cardModel以获得所需的值。我添加bindToController:true来访问传入的模型作为card.cardModel而不是纯cardModel:

app.directive('card', function(){
  return {
    restrict:'E',
    scope: {
      cardModel: '='
    },
    templateUrl:'card.html',
    controller:function(){
      var card = this;
      console.log(card.cardModel)
        card.suitClass = function(){
            return card.cardModel.suit + '-' + card.cardModel.rank;
        }
    },
    controllerAs:'card',
    bindToController: true
  };
});

<强> card.html:

这个观点没问题。我只应用了我的更改:

<div ng-class="card.suitClass()">{{ card.cardModel.rank }}</div>

我希望它对任何人都有用。