Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error: [$compile:nonassign] Expression 'undefined' used with directive 'myFacebook' is non-assignable

I am writing a directive in angularjs and get the above mentioned error. I am using the code from a book.

.directive('myFacebook', [function(){
return {
    link: function(scope,element,attributes) {
        (function(d) {
                var js, id = 'facebook-jssdk',
                    ref = d.getElementsByTagName('script')[0];
                if (d.getElementById(id)) {
                    return;

                }
                js = d.createElement('script');
                js.id = id;
                js.async = true;
                js.src = "//connect.facebook.net/en_US/all.js";
                ref.parentNode.insertBefore(js, ref);
            }(document));
            // Initialize FB
            window.fbAsyncInit = function() {
                FB.init({

                    appId: 'xxxx', //birthday reminder
                    status: true, // check login status
                    cookie: true, // enable cookies to access the session
                    xfbml: false // parse XFBML
                });
                //Check FB Status
                FB.getLoginStatus(function(response) {
                     xxxx
                });
            };
        scope.username='';
    },
    scope: {
            permissions: '@',
            myFriends: '=friends'
        },
    controller: function($scope) {
        $scope.loadFriends = function() {
            FB.api('/me/friends?fields=birthday,name,picture', function(response) {
                    $scope.$apply(function() {
                        $scope.myFriends = response.data;
                    });
                });
        }
    },

    template:'Welcome {{username}}'
   }}])

I get error at

 $scope.$apply(function() {
            $scope.myFriends = response.data;
 });

The HTML code

<div my-facebook></div>
<h1> My Friend's Birthday Reminder</h1>
<div ng-repeat="friend in myFriends">
     {{friend.name}}
</div>
like image 807
harshit Avatar asked Sep 02 '14 16:09

harshit


4 Answers

My solution was harder to find out here, but easier to implement. I had to change it to the equivalent of (Note that the question mark makes the attribute optional. Prior to 1.5 this apparently wasn't required).

scope: {
    permissions: '@',
    myFriends: '=?friends'
}
like image 57
Louis Avatar answered Nov 12 '22 03:11

Louis


The problem is that you are not defining the attribute friends in the directive element <div my-facebook></div>.

When you define the directive's scope like this:

scope: {
    permissions: '@',
    myFriends: '=friends'
}

You are basically saying:

  • Bind to the local scope's permissions property the value of DOM attribute with the same name
  • Set up bi-directional binding between the local scope's myFriends property and the parent scope's friends property

Since you are not defining the attribute friends in the DOM, Angular cannot create the bi-directional binding and throws the error. More information here.

Define the friends attribute on your DOM and it should fix the problem:

<div my-facebook friends="friendList"></div>

And, for example, on the controller:

app.controller('Ctrl', function($scope) {
  $scope.friendList = [];
});
like image 43
bmleite Avatar answered Nov 12 '22 03:11

bmleite


Not a direct answer to OPs question, but this just happened to me so for anyone else that might Google this error in the future. This is similar to JohnP's answer.

This error can also appear if you have a camelCase attribute in your directive.

So if you have:

<div my-facebook myFriends></div>

It will throw the error.

This is because (taken from the angular documentation):

Angular normalizes an element's tag and attribute name to determine which elements match which directives. We typically refer to directives by their case-sensitive camelCase normalized name (e.g. ngModel). However, since HTML is case-insensitive, we refer to directives in the DOM by lower-case forms, typically using dash-delimited attributes on DOM elements (e.g. ng-model).

The normalization process is as follows:

Strip x- and data- from the front of the element/attributes.

Convert the :, -, or _-delimited name to camelCase.

so <div my-facebook myFriends></div>

will need to become <div my-facebook my-friends></div>

like image 20
Matt Lishman Avatar answered Nov 12 '22 03:11

Matt Lishman


I run to this same issue and for me the problem was upper case characters in DOM name.

<div my-facebook FRIENDS="friendList"></div>

did not work, but

<div my-facebook friends="friendList"></div>

worked. I spent a day working on this and found the solution by accident.

like image 4
JohnP Avatar answered Nov 12 '22 04:11

JohnP