Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular.js: directive object in scope is always undefined

EDIT: Forked @EliteOctagon's plunker and oddly it's working! Can't understand why the code below isn't. http://plnkr.co/edit/y8uvulA9RHQ1Y9mwzin1

EDIT2: Forked the previous plunker and added a $timeout to controller's logic and it stopped working! Guess it's really loading order. Check it out: http://plnkr.co/edit/ivmGQmEHTatNzBWhppyf

I'm new to angular and can't get my head wrapped around directive isolate scopes.

I need to create a directive to print out a <span/> in my page with info regarding and object in the view controller.

What I was trying to do is isolate the directive scope and pass the object through an attribute with two-way binding (see code below). However, when trying to access the object in the link function of the directive it always comes out as undefined.

What am I missing here?

Thank you in advance guys.

Directive use in html view template:

<party-starts party="party"></party-starts>

Directive JS code

.directive('partyStarts', function(){
    return {
        restrict: 'E',
        template: '<div id="partyStart><i class="icon ion-pin"></i> </div>',
        scope: {
            party: '='
        },
        link: function(scope, el) {
            var party = scope.party;
            var icon = el.find('i');
            var statusStr = angular.element('<span/>');
            var final;

            console.log('scope '+scope);

            if(party.Diatodo){
                if(party.datahora.isSame(moment(), 'day') || party.datahora.isSame(moment().add(1, 'd'), 'day')){
                    icon.css({
                        'color': 'green'            
                    });
                    statusStr.text(' É hoje');
                    el.append(statusStr);
                }else{
                    icon.css({
                        'color': '#999'            
                    });
                    statusStr.text(' Começa em '+party.datahora.fromNow());
                    el.append(statusStr);
                }
                return;
            }

            if(party.datahora.unix() == party.datahoraf.unix()){
                final = party.datahora.clone().add(1, 'd').hour(6);
            }else{
                final = party.datahoraf;
            }

            if(party.datahora.twix(final).isCurrent()){
                icon.css({
                    'color': 'green'            
                });
                statusStr.text(' Começou há '+party.datahora.fromNow());
                el.append(statusStr);
            }else if(party.datahora.twix(final).isFuture()){
                icon.css({
                    'color': '#999'            
                });
                statusStr.text(' Começa em '+party.datahora.fromNow());
                el.append(statusStr);
            }else{
                icon.css({
                    'color': 'red'            
                });
                statusStr.text(' Já terminou');
                el.append(statusStr);
            }
        }
    };
})
like image 280
GNSPS Avatar asked Nov 12 '14 18:11

GNSPS


2 Answers

I don't think this is an issue with load order. From what I can tell the code you provided should function. Here is a plunker with a working example: http://plnkr.co/edit/Bsn3Vyjrmb311b8ykzU1 There is also logging to the console, which verifies that scope.party is initialized with the correct value on load.

Click on the live preview (the Eye Icon on the right sidebar) to view the example.

Also, here is a diagram that showed up in my twitter feed the other day that I found very useful for explaining isolate scope in an understandable way. Hope this helps :-)

enter image description here

like image 70
pje Avatar answered Oct 21 '22 00:10

pje


Wrap the directive's party scope variable in a watcher and wait for it to be initialized. In your case you don't do this and so all your logic is being run before scope.party is assigned.

link: function(scope, el) {

  var watcher = scope.$watch('party', function() {
    if(scope.party === undefined) return;

    // at this point it is defined, do work

    // delete watcher if appropriate
    watcher();
  })
}
like image 35
user12121234 Avatar answered Oct 21 '22 00:10

user12121234