This is probably a stupid question, but I have been stuck on it for days and neither of the googled solutions panned out for me.
I'm writing an angular 1.4 app following a directive driven approach, so for any entity I have one or more widgets:
- isolated scope
- controller as
- bindToController true
The problem is of the "user has stuff" variety.
<user-widget>
<stuff-widget userid="user._id"></stuff-widget>
</user-widget>
The userid passes nicely into the widget, but I would like to use it inside the stuff widget's link function, because stuff is really complicated and in the real world I need to grab various other parts as well.
I tried various methods to get to the userid value (as suggested in various other stackoverflow discussions and elsewhere on the web)
- use bidrectional binding -> not effective
- tried via scope and controller -> userid, uid not defined
- require ^userWidget -> lost access to my controller
- use attrs.$observe('userid', ....) -> js error: userid not defined
- passed it via pre link of the parent -> did work, but not a good idea/limited merits
I have a plunker with the various things I tried: http://plnkr.co/edit/SqlhYSteCDxMaAVZWCsy?p=info
The widgets look like this (working pre link variant)
function userWidget() {
return {
restrict: 'EA',
scope:{},
template: '<h2>User</h2> {{user.name}}<stuff-widget userid="user._id"></stuff-widget>',
replace: false,
controllerAs: 'userCtrl',
bindToController: true,
controller: 'UserCtrl',
link: { // this actually works, not sure wether this a good idea
pre: function preLink(scope, element, attrs, ctrl) {
var uid = 1;
scope.user = ctrl.findById(uid);
scope.userid = scope.user._id;
},
post: function postLink(scope, element, attrs, ctrl) {}
}
};
}
function stuffWidget() {
return {
restrict: 'EA',
scope: {
uid: '=userid'
},
template: '<h3>User stuff</h3>stuffCtrl.userid inside widget: {{stuffCtrl.userid}}<div ng-repeat="stuff in stuffCtrl.userStuff">\
User id: {{stuff.userid}}: {{stuff.stuff}}\
</div>',
replace: false,
controller: 'StuffCtrl',
controllerAs: 'stuffCtrl',
bindToController: {
userid: '='
},
link: function (scope, element, attrs, ctrl) {
console.log('stuff ctrl userid:', ctrl.userid); // not defined
console.log('stuff scope uid:', scope.uid); // not defined
console.log('Scope parent userid: ',scope.$parent.userid); // undefined
// didn't work either - userid not defined
/* attrs.$observe('userid', function(value) {
if (value) {
ctrl.userid = userid;
console.log('stuff ctrl userid observed:', ctrl.userid);
}
}); */
ctrl.userStuff = ctrl.findByUserId(ctrl.userid);
}
};
}
I'm an angular beginner (first serious project) and so far my experience has been: "if it's hard to figure out, you are probably doing it the wrong way".
So,
- Did I miss an obvious way to access the param inside the link function?
- Did I screw up the ways I tried (especially $observe) because I incorrectly transferred them to my setting?
- Should I just stick the controller calls inside the template and be done with it?
- Should I go about it in an entirely different way? compile function? controller function? whatever other angular depths I'm not yet familiar with?