Reputation: 1073
OK this is a contrived example, but...
Say I have a controller like this:
app.controller('TestCtrl', function() {
this.testString;
this.otherString;
});
And I have a template like this:
<div ng-controller='TestCtrl as test'>
<input demo type='text' ng-model='test.testString'>
{{test.otherString}}
</div>
And then I have a directive like this:
app.directive('demo', function() {
return {
require:'ngModel',
link: function(scope, elem, attrs, ctrl) {
scope.$watch(attrs.ngModel, function(newVal) {
/* How do I get otherString without knowing the controller alias?
This works but is not good practice */
scope.test.otherString = newVal + ' is cool!';
/* This doesn't work, but would if the property was in scope
instead of the controller */
scope[attrs.demo] = newVal + ' is cool!';
});
}
}
});
How do I get otherString without knowing the controller alias? I could just break apart attrs.ngModel to get it, but is there an 'angular' way to get the property?
EDIT
While this example didn't exactly reflect the issues I was having with my real scenario, I did find out how to get the controller's property in the link function, allowing me to update the model:
link: function(scope, elem, attrs, ctrl) {
var otherString = scope.$eval(attrs.demo);
scope.$watch(attrs.ngModel, function(newVal) {
otherString = newVal + ' is cool!';
}
}
Upvotes: 2
Views: 697
Reputation: 2700
A directive should have zero knowledge of anything outside of itself. If the directive depends on an outside controller having defined some arbitrary property, things will break very easily.
Defining a "scope" property on the directive lets you expose an explicit API for binding data to the directive.
myModule.directive('demo', function() {
return {
scope: {
demoString: '=demo',
},
link: function(scope, element, attrs) {
// You can access demoString here, or in a directive controller.
console.log(scope.demoString);
}
};
});
And the template
<div ng-controller='TestCtrl as test'>
<input demo="test.otherString" ng-model='test.testString'>
{{test.otherString}}
</div>
This isn't the only way to facilitate passing data or setting up bindings to a directive, but it is the most common way and should cover the majority of use-cases.
Upvotes: 3
Reputation: 1210
If you are trying to be more angular-like I would just use the $scope in the controller and pass that to the directive like so:
app.directive('demo', function() {
return {
scope: {strings: '='},
link: function(scope, elem, attrs, ctrl) {
scope.$watch('strings.test', function(newVal) {
/* How do I get otherString without knowing the controller alias? */
scope.strings.other = newVal + ' is cool!';
});
}
}
});
then in the html:
<div ng-controller='TestCtrl as test'>
<input demo type='text' strings="strings" ng-model="strings.test" />
{{strings.other}}
</div>
In the controller you would assign:
$scope.strings = {
test: '',
other: ''
}
Upvotes: 0