I have two elements on my page which are not nested in some way. With attributes on the first one, I would like to set the content of the second one, like so:
<body>
<input info="This is some info"></input>
<div>{{info}}</div>
</body>
I know something similar can be done as described in "AngularJS - Attribute directive input value change", but in my situation the content of the attribute is the modelvalue. Moreover, I'm already using the ng-model
to handle the input's value.
Finally I solved the problem like so:
<body>
<input infobox info="This is some info"></input>
<div>{{info}}</div>
</body>
app.directive('infobox', function() {
return {
restrict : 'A',
scope : {
info : '@info'
},
controller: function($rootScope, $scope) {
$rootScope.info = $scope.info;
}
};
});
So I'm transferring the value bypassing any isolated scope by going directly to the $rootScope
, but it feels like a cop out. Essentially I don't know what controller or scope might be up the chain, since I need to be able to use this component anywhere.
One other solution is to have a parent controller for the entire page, but that would simply be a pseudo root scope again. Yet another more cumbersome solution would be to have two directives or controllers and communicate using events almost like a bus. It would work, but let's not do that.
Is there a 'clean' way to do this?
/edit
Here's a clean solution that should work (and in jsfiddle it does):
<body>
<div info="this is some info"></div>
<div>{{info}}</div>
</body>
app.directive('info', function() {
return {
restrict : 'A',
link: function(scope, element, attrs, ngModel) {
scope.info = attrs.info;
}
};
});
In my real life scenario however the value is stuck somewhere in the chain. Is it possible a parent directive with isolated scope is blocking the cascade all the way up?
/edit2
Here's a solution I thought surely would have worked. It involves three directives of which one is the parents to both others. A combination of suggested solutions in the comments:
In my own code, however, it still doesn't work. As simple as it might seem, infoManager.info
remains undefined
.
OK, I got it finally. The last edit had it close, but I was reading info from the controller, not the scope the controller was for.
Solution is as follows:
<body>
<div infomanager>
<div info="'this is some info'"></div>
<div showinfo></div>
</div>
</body>
var app = angular.module('app', []);
app.directive('infomanager', function() {
return {
controller: function($scope) {
this.scope = $scope;
}
};
});
app.directive('info', function() {
return {
restrict : 'A',
require: '^infomanager',
scope : {
info : '=info'
},
link: function(scope, element, attrs, infoManager) {
infoManager.scope.info = scope.info;
}
};
})
app.directive('showinfo', function(){
return {
template:'{{info}}',
require:'^infomanager'
}
})
Here's a better example to demonstrate this with: jsfiddle