• why is ng-repeat not working in custom directive?

    122 Views Asked by At

    I am new to AngularJS and I cannot get ng-repeat to work when embedded in a directive as follows

    <settings-widget>
        <ul class="ul-border">
         <li class="box" ng-repeat="item in list">{{item}}</li>
        </ul>
    </settings-widget>
    
    app.directive("settingsWidget", function ($compile, $timeout) {
        return {
            restrict: "E",
            replace: "true",
            scope: { },
            transclude: true,
            templateUrl: "/Settings.html",
            compile: function (element, attrs, transclude) {
                return function (scope) {
                    transclude(scope, function (clone) {
                        var html = angular.element("<div>").append(clone).html();
                        scope.template = html;
                    });
                };
            },
            controller: ['$scope', '$element', '$attrs', '$rootScope', function ($scope, $element, $attrs, $rootScope) {
                $scope.list = ['item1', 'item2'];
            }]
        };
    });
    

    Settings.html

    <div>
            <form id="settingsForm" name="settingsForm" novalidate ng-submit="save(settingsForm)" ng-model-options="{ allowInvalid: true}">
                <div compile="{{template}}"></div>
            </form>
    </div>
    

    for some reason when I run my app <li> tags are not being created.

    Could someone please help me out?

    1

    There are 1 best solutions below

    0
    Petr Averyanov On

    1. Normal transclusion (passed html uses parent scope): You define list in parent controller!

    <settings-widget>
        <ul class="ul-border">
         <li class="box" ng-repeat="item in list">{{item}}</li>
        </ul>
    </settings-widget>
    
    app.directive("settingsWidget", function () {
        return {
            restrict: "E",
            replace: "true",
            scope: { },
            transclude: true,
            templateUrl: "/Settings.html"
        }
    });
    
    <div>
            <form id="settingsForm" name="settingsForm" novalidate ng-submit="save(settingsForm)" ng-model-options="{ allowInvalid: true}">
                <ng-transclude></ng-transclude>
            </form>
    </div>
    

    2. No transclusion (passed html uses directive scope):

    <settings-widget additional-tpl="'myTemplate'">
    </settings-widget>
    <script type="text/ng-template" id="myTemplate">
        <ul class="ul-border">
         <li class="box" ng-repeat="item in list">{{item}}</li>
        </ul>
    </script>
    
    app.directive("settingsWidget", function () {
        return {
            restrict: "E",
            scope: { 
              additionalTpl: '<'
            },
            templateUrl: "./settings.html",
            controller: ['$scope', function ($scope) {
                $scope.list = ['item1', 'item2'];
            }]
        };
    });
    
    <div>
            <form id="settingsForm" name="settingsForm" novalidate ng-submit="save(settingsForm)" ng-model-options="{ allowInvalid: true}">
                <div ng-include="additionalTpl">
                </div>
            </form>
    </div>
    

    2. Transclusion+ (passed html want to use both directive and parent scopes): This one seems to be tricky and I never actually did that, I guess quite easy way is using $parent ref cause you dont have this compile manual calls:

    <settings-widget>
        <div>By default I take value from parent scope {{parentCtrlValue}} 
        </div>
        <ul class="ul-border">
           <li class="box" ng-repeat="item in $parent.list">{{item}}</li>
        </ul>
    </settings-widget>
    
    app.directive("settingsWidget", function () {
        return {
            restrict: "E",
            scope: { },
            transclude: true,
            templateUrl: "./settings.html",
            controller: ['$scope', function ($scope) {
                $scope.list = ['item1', 'item2'];
            }]
        };
    });
    
    <div>
        <form id="settingsForm" name="settingsForm" novalidate ng-submit="save(settingsForm)" ng-model-options="{ allowInvalid: true}">
            <ng-transclude></ng-transclude>
        </form>
    </div>