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.