Speedy059
Speedy059

Reputation: 669

AngularJS : directive ng-repeat doesn't work in link function

I'm trying to create a directive that will eventually be an "auto complete" and display data underneath the form element.

I'm having a problem getting the ng-repeat in the inserted html to display the array of information that it gets from an attr.

In the directive i'm monitoring the attr waiting for data to be populated, and once it's populated, I set it to a variable in the directive and try to ng-repeat the data in the ul html. Nothing is being shown, even though the variable is populated in the directive.

Any ideas why? I've tried doing a lot of things, i'm sure it's a parent/child scope issue, just not sure what I need to change? I'm trying to keep the directive scope isolated so I can reuse this directive multiple times.

Plunker: http://plnkr.co/edit/XoXli0OyRP6xObsDImOe

    //Directive
    function autoComplete($parse, $compile, $timeout) {
        var directive = {
            restrict: 'EA',
        //  scope: true,
            require: '?ngModel',
            link: link
        };

        return directive;

        function link(scope, elem, attr, ngModel) {
            var cdata = [];

            var modelGet    = $parse(attr['ngModel']);
            var modelSet    = modelGet.assign;


            scope.$watch(function() {
                return elem.attr('data');
            }, function(newVal) {
                cdata = newVal;
                console.log(cdata);
            });

            $timeout(function(){

                //var ewidth        = elem.outerWidth(); //Doesn't work in Plunker for some reason
                var ewidth  = '100%';
                var html        = '<div><ul class="list-group" style="position: absolute; width: '+ewidth+'px;"><li class="list-group-item" ng-repeat="codes in cdata track by $index">{{codes.code}}</li></ul></div>';
                elem.after($compile(html)(scope));
                scope.$apply();
                console.log("DIV has been added");
            });



            scope.$watch(function() {
                return modelGet(scope);
            }, function() {
                var string = modelGet(scope);
                if (string != undefined && string.length >= 6) {
                    console.log("Will do something later");
                }

            });
        }
    }

Upvotes: 2

Views: 1044

Answers (1)

floribon
floribon

Reputation: 19183

Ok, I found a combination of errors in this code that makes it not work. See below:

  • In your link, cdata is not on the scope, so cannot be accessed by the HTML
  • data contains an array and not a string, so you cannot interpolate as data="{{stuff}}"
  • Instead, you need to $watch for attr.data
  • Since you add information to the scope, it should be a new one using scope: true

That may be it, See fixed plunkr: http://plnkr.co/edit/K9D9h8SYaqNw3uKui1xT?p=preview

Upvotes: 2

Related Questions