2014-10-16 105 views
0

使用动态名字,我有很多的东西基本上是重复的代码模板。我想用一个指令,包括我可以操纵每个重复的代码“块”的部分模板。AngularJS:访问模型模板

模板目前看起来是这样的:

<div class="column book"> 
    <div class="header"> 
     <input type="text" id="book_query" ng-model="book_query.name" /> 
    </div> 
    <div class="content"> 
     <div class="row" ng-repeat="book in books | filter:book_query"> 
      {{book.name}} 
     </div> 
    </div> 
</div> 
.... 
<div class="column game"> 
    <div class="header"> 
     <input type="text" id="game_query" ng-model="game_query.name" /> 
    </div> 
    <div class="content"> 
     <div class="row" ng-repeat="game in games | filter:game_query"> 
      {{game.name}} 
     </div> 
    </div> 
</div> 
.... 

而且控制器只是获取数据,并把它添加到的范围如

$scope.books = data.books; 
$scope.games = data.games; 

我开始用一个指令,它发生在一个参数(例如书籍,游戏等),这样做我然后知道哪种模式(S)使用。我遇到的问题是如何使用参数来访问模板中的模型?该指令本身,目前,很简单:

<div item-column item="book"></div> 
<div item-column item="game"></div> 

app.directive('itemColumn', function() { 
    return { 
     scope: { 
      item: '@' 
     }, 
     replace: true, 
     templateUrl: 'item_column.html' 
    }; 
}); 

在item_column.html,我希望我可以替代项目的说法,这显示了arg的值工作正常,但不能更换其中“书'或'游戏'用于模型,例如

<div class="column {{item}}"> 
    <div class="header"> 
     <input type="text" id="{{item}}_query" ng-model="{{item}}_query.name" /> 
    </div> 
    <div class="content"> 
     <div class="row" ng-repeat="item in ??? | filter:{{item}}_query"> 
      {{item.name}} 
     </div> 
    </div> 
</div> 

有人可以告诉我这样做的最好方法吗?我不怀疑我会以完全错误的方式去做!

编辑:上面的原问题是现在使用下面JoseM的回答几乎完全解决。一个突出问题是每个元素上的on-click函数不再从隔离范围内触发父范围。

我的控制器布局就像这样:

app.controller('ItemsCtrl', ['$scope', '$http', 'CONFIG', function($scope, $http, CONFIG) { 

    var items = ['books', 'games']; 

    items.forEach(function(item) { 
     $scope[item] = []; 
     $scope['selected_'+item] = null; 
    }) 

    $scope.getItem = function(item) { 

     $http.get('?action=get_item&id='+item.id+'&type='+item.type) 
      .success(function(data) { 
       // update model 
      }) 
      .error(function(data, status) { 
       // do something 
      }); 
    } 
}]); 

$ scope.getItem不再可访问在视图中的项目,这类似于实施JoseM的回答后,点击以下时:

<div class="row" ng-repeat="item in array | filter:query"> 
    <div class="text" ng-click="getItem(item)"> 
     {{item.name}} 
    </div> 
</div> 

是否有可用做父作用域功能从隔离范围内的一个简单的方法?或者这些功能有更好的地方吗? (我的感受是)非常基本的问题 - 我仍然试图让我的头在Angular!

+0

您可以将函数传递给模板并动态创建自己的模板 – JoseM 2014-10-16 16:12:09

+0

这是真的,它应该可以工作。问题是,这个问题并不明显,因为我已经简化了它,但是模板中有大量的代码。理想情况下,我真的不希望这在一个JS文件 - 我宁愿它包含在一个单独的HTML文件。 – thor 2014-10-16 17:46:33

回答

1

之一来完成你想要什么样的方式是在你的指令使用小孩的范围,然后做你自己使用父范围值的手表父作用域变量的“链接”。

app.directive('itemColumn', function() { 
    return { 
     scope: true, 
     templateUrl: 'item_column.html', 
     link: function(scope,elem,attrs) { 
      var varName = scope.varName = attrs.item; 
      var parScope = scope.$parent; 
      parScope.$watch(varName + 's', function(newVal){ 
      scope.theArray = newVal; 
      }); 
      parScope.$watch(varName + '_query', function(newVal){ 
      scope.theQuery = newVal; 
      }); 
     } 
    }; 
}); 
在你的模板

在你的指令

<div class="column {{varName}}"> 
    <div class="header"> 
     <input type="text" ng-attr-id="{{varName}}_query" ng-model="theQuery.name" /> 
    </div> 
    <div class="content"> 
     <div class="row" ng-repeat="item in theArray | filter:theQuery"> 
      {{item.name}} 
     </div> 
    </div> 
</div> 

如果你想使用一个孤立的范围,你可以,但那么你就必须提供至少3个属性如果你使用与上面相同的属性。我个人认为使用隔离范围是一个更好的方法。请参阅下面的隔离方案是如何简单:

指令隔离版本

app.directive('itemColumn2', function() { 
    return { 
     scope: { 
      label: '@', 
      array: '=', 
      query: '=' 
     }, 
     templateUrl: 'item_column2.html' 
    }; 
}); 

隔离和版本模板的

<div class="column {{label}}"> 
    <div class="header"> 
     <input type="text" ng-attr-id="{{label}}_query" ng-model="query.name" /> 
    </div> 
    <div class="content"> 
     <div class="row" ng-repeat="item in array | filter:query"> 
      {{item.name}} 
     </div> 
    </div> 
</div> 

使用

<div item-column2 label="book" array="books" query="book_query"></div> 
<div item-column2 label="game" array="games" query="game_query"></div> 

终于在这里是一个示例plunker :http://plnkr.co/edit/OyEHR4ZhzYKvs4jeDfjD?p=preview

+0

独立作用域方法非常有效,非常感谢!我现在唯一遇到的问题是,当点击UI中的元素时,会在父范围中调用一些函数,而这些元素不再适用于隔离范围。有没有简单的方法将它们链接起来?我会用一些细节更新原始问题。 – thor 2014-10-19 21:07:35

+0

其实它都很好。我似乎通过将函数作为另一个参数来排序问题。谢谢你的帮助! – thor 2014-10-20 11:12:03