te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>javascript - Angularjs: transclude directive template - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angularjs: transclude directive template - Stack Overflow

programmeradmin3浏览0评论

How to use transclusion in the below case. The intention is to use markup in the html (partials) file, than defining it in template (within the directive).

I found a great tree directive here. (source) Original: /

Instead of defining the template in the directive, I was trying to use a transcluded content. I also updated Angular to 1.2.0.rc2. Updated: /

got below error

TypeError: Property '$transclude' of object [object Object] is not a function

code:

module.directive("tree", function($pile) {
    return {
        restrict: "E",
        transclude: true,
        scope: {family: '='},
        template:       
            '<ul>' + 
                '<li ng-transclude></li>' +
                '<li ng-repeat="child in family.children">' +
                    '<tree family="child"></tree>' +
                '</li>' +
            '</ul>',
        pile: function(tElement, tAttr) {
            var contents = tElement.contents().remove();
            var piledContents;
            return function(scope, iElement, iAttr) {
                if(!piledContents) {
                    piledContents = $pile(contents);
                }
                piledContents(scope, function(clone, scope) {
                         iElement.append(clone); 
                });
            };
        }
    };
});

<div ng-app="myapp">
    <div ng-controller="TreeCtrl">
        <tree family="family">
            <p>{{ family.name }}</p>
        </tree>
    </div>
</div>

Edit:

With David's suggestion, made some changes. / now, it prints, Parent. changing, family -> treeFamily didn't work though

How to use transclusion in the below case. The intention is to use markup in the html (partials) file, than defining it in template (within the directive).

I found a great tree directive here. (source) Original: http://jsfiddle/n8dPm/

Instead of defining the template in the directive, I was trying to use a transcluded content. I also updated Angular to 1.2.0.rc2. Updated: http://jsfiddle/aZx7B/2/

got below error

TypeError: Property '$transclude' of object [object Object] is not a function

code:

module.directive("tree", function($pile) {
    return {
        restrict: "E",
        transclude: true,
        scope: {family: '='},
        template:       
            '<ul>' + 
                '<li ng-transclude></li>' +
                '<li ng-repeat="child in family.children">' +
                    '<tree family="child"></tree>' +
                '</li>' +
            '</ul>',
        pile: function(tElement, tAttr) {
            var contents = tElement.contents().remove();
            var piledContents;
            return function(scope, iElement, iAttr) {
                if(!piledContents) {
                    piledContents = $pile(contents);
                }
                piledContents(scope, function(clone, scope) {
                         iElement.append(clone); 
                });
            };
        }
    };
});

<div ng-app="myapp">
    <div ng-controller="TreeCtrl">
        <tree family="family">
            <p>{{ family.name }}</p>
        </tree>
    </div>
</div>

Edit:

With David's suggestion, made some changes. http://jsfiddle/aZx7B/3/ now, it prints, Parent. changing, family -> treeFamily didn't work though

Share Improve this question edited Oct 3, 2013 at 19:39 bsr asked Oct 1, 2013 at 15:36 bsrbsr 58.7k88 gold badges217 silver badges321 bronze badges 4
  • 1 A couple issues with this: you're referencing family.name inside the transclusion, but family is part of the directive scope and won't be available. You'd have to use treeFamily.name. Also, your nested trees won't have the transcluded content. You might get further along if you use the transclude function provided to the pile function (3rd parameter) instead of ngTransclude. – David Bennett Commented Oct 1, 2013 at 18:44
  • thanks david, update with some changes. – bsr Commented Oct 1, 2013 at 18:55
  • I've just been doing something similar and wanted to keep my html in a template. But the recursion wouldn't work (infinite digest - I think) unless I piled it manually inside the link function. I'd really like to know why this is the case so I can actually make coding decisions based on knowledge and not 'because thats the way it is' – Stevo Commented Oct 3, 2013 at 21:49
  • Does my edited answer explain why the template want outputting properly? With my last version of the code you should be able to pass whatever you want to into the your custom directive, inducing other custom directives with templates of their own. – Erstad.Stephen Commented Oct 3, 2013 at 22:06
Add a ment  | 

3 Answers 3

Reset to default 8 +100

You need to output the name of the family in the template as well: http://jsfiddle/roadprophet/DsvX6/

module.directive("tree", function($pile) {
    return {
        restrict: "E",
        transclude: true,
        scope: {family: '='},
        template:       
            '<ul>' + 
                '<li ng-transclude></li>' +
                '<li ng-repeat="child in family.children">' +
                    '<tree family="child">{{family.name}}</tree>' +
                '</li>' +
            '</ul>',
        pile: function(tElement, tAttr, transclude) {
            var contents = tElement.contents().remove();
            var piledContents;
            return function(scope, iElement, iAttr) {
                if(!piledContents) {
                    piledContents = $pile(contents, transclude);
                }
                piledContents(scope, function(clone, scope) {
                         iElement.append(clone); 
                });
            };
        }
    };
});

EDIT

You could also simplify by doing this: http://jsfiddle/roadprophet/DsvX6/2/

<div ng-app="myapp">
    <div ng-controller="TreeCtrl">
        <tree family="treeFamily">           
        </tree>
    </div>
</div>


module.directive("tree", function($pile) {
    return {
        restrict: "E",
        transclude: true,
        scope: {family: '='},
        template:       
            '<ul>' + 
                '<li ng-transclude></li>' +
                '<p>{{ family.name }}</p>' + 
                '<li ng-repeat="child in family.children">' +
                    '<tree family="child"></tree>' +
                '</li>' +
            '</ul>',
        pile: function(tElement, tAttr, transclude) {
            var contents = tElement.contents().remove();
            var piledContents;
            return function(scope, iElement, iAttr) {
                if(!piledContents) {
                    piledContents = $pile(contents, transclude);
                }
                piledContents(scope, function(clone, scope) {
                         iElement.append(clone); 
                });
            };
        }
    };
});

EDIT Same source of the problem though. No template being passed to the inner tree directive. http://jsfiddle/roadprophet/DsvX6/3/

<div ng-app="myapp">
    <div ng-controller="TreeCtrl">
        <tree family="treeFamily">           
                <p>{{ family.name }}</p>
        </tree>
    </div>
</div>

 template:       
            '<ul>' + 
                '<li ng-transclude></li>' +
                '<li ng-repeat="child in family.children">' +
                    '<tree family="child"><div ng-transclude></div></tree>' +
                '</li>' +
            '</ul>'

You want to pile the transcluded DOM against the parent scope; you can do this automatically with the injectable $transclude function in a directive's controller definition:

module.directive("tree", function($pile) {
  return {
    restrict: "E",
    transclude: true,
    scope: { family: '=' },
    template: '<ul>' + 
                '<li ng-repeat="child in family.children">' +
                  '<tree family="child">' +
                    '<p>{{ child.name }}</p>' +
                  '</tree>' +
                '</li>' +
              '</ul>',
    controller: function($element, $transclude) {
      $transclude(function(e) {
        $element.append(e);
      });
    },
    pile: function(tElement, tAttr, transclude) {
      var contents = tElement.contents().remove();
      var piledContents;
      return function(scope, iElement, iAttr) {
        if(!piledContents) {
          piledContents = $pile(contents);
        }
        piledContents(scope, function(clone) {
          iElement.append(clone);
        });
      };
    }
  };
});

This allows you to use the parent scope property treeFamily in your root template (also notice the use of child in the directive's template, above):

<div ng-app="myapp">
  <div ng-controller="TreeCtrl">
    <tree family="treeFamily">
      <p>{{ treeFamily.name }}</p>
    </tree>
  </div>
</div>

You can see an example here: http://jsfiddle/BinaryMuse/UzHeW/

Very very late to the party. I needed this for a project so after dwelling into it and finding other great approaches and directions, finally came up with this:

Same code as the ng-transclude directive, but with small addition of context binding that the directive watch and sets on the transcluded generated scope each time it changes. Same as ng-repeat does, but this allows:

  1. using the customize ng-transclude with ng-repeat without the hassle of rewriting ng-repeat and like angular/2 template outlet.
  2. Having the transcluded content keep access the grandparent scope while receiving direct context data from the parent. Same as template outlet again.

The augmented ng-transclude function:

return function ngTranscludePostLink(
   ...
  ) {
  let context = null;
  let childScope = null;
  ...
  $scope.$watch($attrs.context, (newVal, oldVal) => {
    context = newVal;
    updateScope(childScope, context);
  });
  ...
  $transclude(ngTranscludeCloneAttachFn, null, slotName);
  ...
  function ngTranscludeCloneAttachFn(clone, transcludedScope) {
     ...                                 
     $element.append(clone);
     childScope = transcludedScope;
     updateScope(childScope, context);
     ...
  }
  ...
  function updateScope(scope, varsHash) {
    if (!scope || !varsHash) {
      return;
    }
    angular.extend(scope, varsHash);
  }
}

And it's usage:

App

<my-list items="$ctrl.movies">
   <div>App data: {{ $ctrl.header }}</div>
   <div>Name:{{ name }} Year: {{ year }} Rating: {{ rating 
          }}</div>
</my-list>

MyList

<ul>
  <li ng-repeat="item in $ctrl.items track by item.id">
   <div>Ng repeat item scope id: {{ $id }}</div>
   <cr-transclude context="item"></cr-transclude>
  </li>
</ul>

Full directive code can be found here on GitHub

发布评论

评论列表(0)

  1. 暂无评论