在指令中使用 ng-transclude 进行 ng-repeat [英] ng-repeat with ng-transclude inside a directive

查看:28
本文介绍了在指令中使用 ng-transclude 进行 ng-repeat的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在内容更改时创建一个具有自定义行为的列表.我尝试为此创建一个指令,但我对如何将 ng-transclude 与 ng-repeat 指令结合起来有点迷茫.有人能让我走上正轨吗?

HTML:

<div ng-controller="ctrl"><mylist items="myItem in items"><span class="etc">{{myItem}}</span></mylist>

Javascript:

angular.module('myApp', []).controller('ctrl', function ($scope) {$scope.items = ['one', 'two', 'three'];}).directive('mylist', function () {返回 {限制:'E',嵌入:'元素',替换:真的,范围:真实,模板: ['
    ','<li ng-repeat="WhatGoesHere in items";ng-transclude></li>','</ul>'].加入(''),链接:函数(范围、元素、属性){var parts = attr.items.split(' in ');var itemPart = 零件[0];var itemsPart = part[1];scope.$watch(itemsPart, function (value) {scope.items = 值;});}}});

我在这里

标准:

  • 项的模板必须在视图中定义,而不是在指令中定义,并且它必须能够访问子作用域中的项属性.理想情况下,我想像在 ng-repeat 指令中那样定义它
  • 指令必须有权访问列表,以便我可以设置适当的监视和更改内容.如果可能的话,我希望能够轻松访问生成的 DOM 项(我也可以使用 element[0].querySelectorAll('ul>li') 或其他东西来做到这一点,它只需要处理铬).
  • 如果可能,我想重用 ng-repeat 指令中的逻辑,因为它已经做了很多我想做的事情.最好我不想复制代码.我只是想增强它的行为,而不是改变它

解决方案

自己解决了问题:

我可以在编译步骤(jsfiddle)中添加ng-repeat 属性,当模板被编译并将我的属性内容提供给它时​​.

HTML:

<div ng-controller="ctrl"><mylist element="myItem in items">{{myItem}}</mylist>

Javascript:

var myApp = angular.module('myApp', []).controller('ctrl', function ($scope) {$scope.items = ['one', 'two', 'three'];}).directive('mylist', function ($parse) {返回 {限制:'E',嵌入:'元素',替换:真的,范围:真实,模板: ['
    ','<li ng-transclude></li>','</ul>'].加入(''),编译:函数(tElement,tAttrs,transclude){var rpt = document.createAttribute('ng-repeat');rpt.nodeValue = tAttrs.element;tElement[0].children[0].attributes.setNamedItem(rpt);返回函数(范围,元素,属性){var rhs = attr.element.split(' in ')[1];scope.items = $parse(rhs)(scope);控制台日志(范围.项目);}}}});

I want to create a list with custom behavior when it's content changes. I try to create a directive for this but I get a bit lost with how to combine the ng-transclude with the ng-repeat directive. Can somebody put me on track?

Html:

<div ng-app="myApp">
  <div ng-controller="ctrl">
    <mylist items="myItem in items">
       <span class="etc">{{myItem}}</span>
    </mylist>
  </div>
</div>

Javascript:

angular.module('myApp', [])    

.controller('ctrl', function ($scope) {
  $scope.items = ['one', 'two', 'three'];
})    

.directive('mylist', function () {
  return {
    restrict:'E',
    transclude: 'element',
    replace: true,
    scope: true,
    template: [
      '<ul>',
        '<li ng-repeat="WhatGoesHere in items" ng-transclude></li>',
      '</ul>'
    ].join(''),
    link: function (scope, element, attr) {
      var parts = attr.items.split(' in ');
      var itemPart = parts[0];
      var itemsPart = parts[1];
      scope.$watch(itemsPart, function (value) {
        scope.items = value; 
      });      
    }
  }
});

I've got part of this somewhat working here

EDIT:

Criteria:

  • The template of the item must be defined in the view, not in the directive and it must have access to an item property in a child scope. Ideally I want to define this like it is done in the ng-repeat directive
  • The directive must have access to the list so I can set proper watches and change things. If possible I would like to have easy access to the generated DOM items (I can also do it with element[0].querySelectorAll('ul>li') or something, It only has to work on Chrome).
  • If possible I would like to reuse the logic in the ng-repeat directive because it does already do a lot of what I want. Preferably I don't want to copy the code. I just want to augment its behavior, not change it

解决方案

Solved the problem myself:

I am able to do it in the compile step (jsfiddle) by adding the ng-repeat attribute when the template is compiled and feeding it the content of my attribute.

Html:

<div ng-app="myApp">
  <div ng-controller="ctrl">
    <mylist element="myItem in items">{{myItem}}</mylist>
  </div>
</div>

Javascript:

var myApp = angular.module('myApp', [])

.controller('ctrl', function ($scope) {
  $scope.items = ['one', 'two', 'three'];
})

.directive('mylist', function ($parse) {
  return {
    restrict:'E',
    transclude: 'element',
    replace: true,
    scope: true,
    template: [
      '<ul>',
      '<li ng-transclude></li>',
      '</ul>'
    ].join(''),
    compile: function (tElement, tAttrs, transclude) {
      var rpt = document.createAttribute('ng-repeat');
      rpt.nodeValue = tAttrs.element;
      tElement[0].children[0].attributes.setNamedItem(rpt);
      return function (scope, element, attr) {
        var rhs = attr.element.split(' in ')[1];
        scope.items = $parse(rhs)(scope);
        console.log(scope.items);
      }        
    }
  }
});

这篇关于在指令中使用 ng-transclude 进行 ng-repeat的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆