The difference between declaring stuff in the scope: {} vs just reading the 
attributes inside the link function has to do primarily with whether we 
want to keep track of the values as they change. Things declared in the 
isolate scope will automatically get watches created to keep them in sync 
with the outside scope or expression.

In general, if you only need a value once when setting up the structure of 
your directive, but don’t need to keep it updated live, then it is better 
to keep it outside of the scope declaration, and simply read it from the 
attributes (usually by either using $scope.$eval() or $interpolate.

This brings us to your second question. The choice between $interpolate()or 
$scope.$eval() really just comes down to how you expect people to use your 
directive. For attributes that you expect people to mostly put literal text 
values directly in the template (rather than using a variable in the 
scope), you would likely chose to $interpolate(). For example, say I have a 
fancy label directive that takes the text to place on the label:

<my-label  text="This is my label" />

This seems like a good candidate for $interpolate(). If you didn’t use 
$interpolate I would force people to have to quote the text:

<my-label text=" 'This is my label' "/>

On the other hand, say I have a hello directive that outputs the name of 
the currently logged in person. This would more likely be a candidate for 
$scope.$eval() since the common usage would be to use something already 
declared in the scope:

<say-hello  to="currentUser.name"/>

If I used interpolation I would have to add some extra braces:

<say-hello to="{{currentUser.name}}"/>

So the basic rule of thumb to me is this:

If the typical case for the attribute is to read a value stored in the 
scope, then use $eval instead of $interpolate.

If the typical case is for the user to have a literal string in the html 
template, use $interpolate instead of $eval.

If the attribute expects a non-string primitive value (e.g. an int or a 
boolean) then you should probably use $eval since $interpolate will always 
return a string.

As far as a use case for “=?”. This is not very common. Remember, plain “=” 
creates a two-way binding between a variable OUTSIDE the isolate scope and 
one INSIDE the isolate scope. This usually means you want to read and write 
to the variable in the OUTSIDE scope by modifying the variable in the 
ISOLATE scope.

If the argument you pass in does not exist, reading will work fine (it will 
just read a blank or undefined value). However, if you tried to write to 
the scope variable, you would get an “Expression ‘undefined’ used with 
directive is non-assignable!” exception.

Using “=?” makes the directive able to work in the case where the variable 
does not exist in the OUTER scope by just reading/writing to a variable in 
the ISOLATE scope (but not synchronizing with the outer scope at all). 

For example you need to use “=?” to make the following directive work if 
you didin’t pass it a name:

app.directive('hello', function(){
  return {
    scope:{
      name: '=?'
    },
    template: '<div>'+
                 '<input ng-model="name"/>'+
                 '<p>Hello {{name}}</p>'+
              '</div>' 
  };
})

A situation where you need this is rare though. For most optional 
parameters you should not need to use it.

-- 
You received this message because you are subscribed to the Google Groups 
"AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to