问题
I have created a directive and used it to make two time counters however I am a bit confused about how I can use different scope items for each time counter.
I have made a Plunkr to illustrate.
I am not sure whether I should be adding to scope items to the mainCtrl
controller or the directives scope. And if I add it to the directives scope then how can I make that apart of mainCtrl
so that it could later be saved? hopefully the plunker is a bit clearer.
回答1:
You need to declare an isolate scope to define a property on the directive's scope that is two-way-bound with a property on the parent scope.
For example, your directive code should be:
app.directive('time', function() {
return {
templateUrl: 'time.html',
restrict: 'E',
scope: {
Time: '=value'
},
link: function(scope, element, attrs) {
element.addClass('time');
}
};
});
And the relevant markup becomes:
<h1>Times</h1>
<strong>Timer 1</strong> – I would like this to use the 'Time' scope item
<br>
<time value="Time"></time>
<br>
<br>
<strong>Timer 2</strong> – I would like this to use the 'altTime' scope item
<br>
<time value="altTime"></time>
See my forked Plunkr.
EDIT: A few more comments:
- The general JS convention for naming properties is to use
camelCasing
, withPascalCase
reserved for functions serving as the JS equivalent of classes (i.e. functions you should invoke with thenew
operator). - You made a typo in your original plunkr where you declared the initial scope property as
alTime
but referred toaltTime
in the markup (my Plunkr fixes this). - The thing that does the two-way binding in the directive is the
=
operator. See the Angular docs for more info. - You don't need to use
ng-model
in this case to point to the value. You theoretically could, but it would be harder to do and I don't believe it is necessary in this case. Just use the isolate scope bindings as I described. - Keep in mind what I consider the AngularJS Golden Rule: "Always have a dot (.) in your
ng-model
expressions, unless you have a good reason for omitting it." This will mean that you are always setting the property of an object on the correct scope, even if that scope is several levels up in the hierarchy. In your code, for instance, the use of theng-click="Time = Time + 1"
directive will actually have you creating a new propertyTime
on the directive's scope, even if the property initially exists on a parent scope.
Note I did violate this rule in my Plunkr, but that is because I knew that the isolate scope would have aTime
property that was different to the parent scope'sTime
property, and the two are kept in sync by AngularJS under the covers by the use of the=
specifier on the isolate scope.
回答2:
While @MarkM suggestion works, I suggest adding scope: {}
as it is more inline with Angular's implementation:
app.directive('time', function () {
return {
templateUrl: 'time.html',
scope: {},
restrict: 'E',
link: function (scope, element, attrs) {
element.addClass('time');
// $compile(element)(scope);
}
};
});
回答3:
You can just add scope:true
to your directive. Here's a forked Plunkr. It will make a new scope that should inherit from the enclosing element's scope.
来源:https://stackoverflow.com/questions/25150202/how-to-make-a-directive-have-a-unique-scope-item-for-each-use