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
Criteria:
element[0].querySelectorAll('ul>li')
or something, It only has to work on Chrome).The ng-transclude directive facilitates AngularJS to capture everything that is put inside the directive in the markup and use it somewhere in the directive's template.
Directives that Create Scopes In most cases, directives and scopes interact but do not create new instances of scope. However, some directives, such as ng-controller and ng-repeat, create new child scopes and attach the child scope to the corresponding DOM element.
Definition and Usage. The ng-repeat directive repeats a set of HTML, a given number of times. The set of HTML will be repeated once per item in a collection. The collection must be an array or an object. Note: Each instance of the repetition is given its own scope, which consist of the current item.
transclude:true mean to add all element that is defined in your directive with template element of your directive. if transclude:false the these elements are not included in your final html of directive only template of directive is rendered.
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.
<div ng-app="myApp"> <div ng-controller="ctrl"> <mylist element="myItem in items">{{myItem}}</mylist> </div> </div>
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); } } } });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With