4

I've been following the docs and reading other questions on SO, but I'm completely baffled. I have an AngularJS 1.3.14 app. I am using ng-route with controller-as syntax to get to my page. I have a large page that is working great. However, I'm trying to create a directive and I cannot get a JS object to pass into the directive properly.

This is the HTML:

<timechart itemsToPlot="memberData.data.adcs" title="Tares" xprop="time" yprop="tare"></timechart>

The variable memberData is my controller-as name. The nested object memberData.data.adcs is used just above that line to build a table, and if I insert {{ memberData.data.adcs }} into the HTML page it prints out the JS object, so I know that there is data there.

This is the directive:

 myModule.directive('timechart', function() {
    var linker = function(scope, element, attrs) {
        var xprop = attrs['xprop'];
        var yprop = attrs['yprop'];
        var title = attrs['title'];
        console.log(typeof itemsToPlot);
        console.log(typeof scope.itemsToPlot);
        // blah blah blah elided
    };
    return {
        restrict: 'EA',
        scope: { 
            itemsToPlot: '=',
            title: '@',
            xprop: '@',
            yprop: '@'
        },
        link: linker
    };
});

When I set a breakpoint right after the console.log() statements, I see that xplot, yplot, and title are all available, either through the attrs array (as shown in the code) or in the scope object. The itemsToPlot variable, however, is always undefined. There is an itemsToPlot variable defined in the scope object, but it's always undefined.

I've tried fifteen ways of forming the scope, naming the attributes, trying to get the variable to populate. I've looked at all the questions on SO and it seems I'm doing it correctly. I'm hoping someone here can see my error!

Ken DeLong
  • 341
  • 2
  • 5
  • 16

2 Answers2

2

It's likely that the variable is indeed being set, but not right away. So what you need to do is add a watch on your directive scope.

myModule.directive('timechart', function() {
    var linker = function(scope, element, attrs) {
        var xprop = scope.xprop;
        var yprop = scope.yprop;
        var title = scope.title
        var itemsToPlot = scope.itemsToPlot

        scope.$watch('itemsToPlot', function(newVal){
            itemsToPlot = newVal;
            // Just as a proof of concept:
            if( typeof itemsToPlot !== 'undefined' ) console.log(itemsToPlot);
        });
    };
    return {
        restrict: 'EA',
        scope: { 
            itemsToPlot: '=',
            title: '@',
            xprop: '@',
            yprop: '@'
        },
        link: linker
    };
});
chrisboustead
  • 1,573
  • 12
  • 17
  • Thanks, that was it! The code above still didn't work, although others had similar issues [here](http://stackoverflow.com/questions/13980896/watching-for-data-changes-in-an-angular-directive) and [here](http://stackoverflow.com/questions/18139375/scope-watch-in-a-directive-isnt-being-called-after-ajax-request). I had to go up one level and pass in `memberData.data` instead of `memberData.data.adcs`. But finally it worked! – Ken DeLong Apr 05 '16 at 17:28
  • Great! without knowing the structure of the data it would have been hard to determine to pass the parent object but glad this got you to the solution – chrisboustead Apr 05 '16 at 19:35
2

change in your html itemsToPlot by items-to-plot

<timechart items-to-plot="memberData.data.adcs" title="Tares" xprop="time" yprop="tare"></timechart>