I have an issue with a data binding inside a directive, which call another directive.
Here is the main directive :
var app = angular.module('app');
app.directive("myMainDirective", function ($http) {
return {
scope: {
paramId: '='
},
link: function (scope) {
$http.get('some/url/' + scope.paramId+ '.json'
).success(function (data) {
scope.idFromServer = data;
});
},
template: '<span other-directive id="idFromServer"></span>'
}
});
Here is the other directive :
var app = angular.module('app');
app.directive("otherDirective", ['$http', function(http) {
return {
template: "<span>{{name}}</span>",
scope: {
id: "="
},
link: function(scope) {
http.get('another/url/' + scope.id + '.json').then(function(result) {
scope.name = result.data.name;
}, function(err) {
scope.name = "unknown";
});
}
}
}])
And the html code wich call the main directive :
<span my-main-directive param-id="myObject.id"></span>
When calling "other-directive", the "idFromServer" is not bind, and is "undefined", so it results to diplay "undefined".
I'm probably missing something stupid, but I don't see what ... (My piece of code is probabley not the best, I'm pretty new to angularjs, and specially the directives, and I tried a lot of ways to accomplish what I want.)
Per my comments, here's one way that might work, using a scope.$watch:
scope.$watch('id', function(id) {
$http.get('some/url/' + id + '.json')
.success(function (data) {
scope.idFromServer = data;
});
};
This would go inside the link function on the nested directive.
One of the way I'd suggest is don't use two way( =
) binding on idFromServer
variable, use {{idFromServer}}
Interpolation directive to assign value to attribute, & then use $attr.$observe
it will call when interpolation is evaluated.
myMainDirective
app.directive("myMainDirective", function ($http) {
return {
scope: {
paramId: '='
},
link: function (scope) {
$http.get('some/url/' + scope.paramId+ '.json'
).success(function (data) {
scope.idFromServer = data;
});
},
template: '<span other-directive id="{{idFromServer}}"></span>'
}
});
otherDirective
app.directive("otherDirective", ['$http', function(http) {
return {
template: "<span>{{name}}</span>",
scope: true, //isolated scope
link: function(scope, element, attr) {
attr.$observe(attr.id, function(newVal) {
http.get('another/url/' + newVal + '.json').then(function(result) {
scope.name = result.data.name;
}, function(err) {
scope.name = "unknown";
});
});
}
}
}])
Since javascript is asynchronous, your two ajax requests are running at basically the same time and id
is undefined
when the request in other-directive
runs.
If you want to try testing this, just set a default value for idFromServer
. The request in other-directive
will run with the default value.
EDIT: in response to your comment, that is quite a broad question and there are many solutions. The best answer I can give you is simply, never ever run any logic in your link function, just define the directive's behavior and properties - that's what the link function is for. The template is used right away and you can't change that.
In this case, you could get the data prepared in a parent scope and pass the data in attributes.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.