I expect that function step
will be evaluated and its result will be passed right to the link
function. But, when link
function get called it has nothing in $scope.name
variable. $args.checkStep
is empty also. Is is by design?
HTML
<!DOCTYPE html>
<html ng-app="app" lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>angularjs link function doesn not get evaluated paramter</title>
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<br>
<br>
<div class="container">
<custom-include src="inc/homepage.html" prefix="homepage" suffix="" tag="release"></custom-include>
</div>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js"></script>
<script src="app.js" type="text/javascript"></script>
</body>
</html>
JS
(function () {
var app = angular.module('app', []);
app.directive('customInclude', function () {
return {
restrict: 'E',
scope: {
type: '@'
},
link: function ($scope, $elem, $attr) {
var prefix = $attr.prefix || '',
suffix = $attr.suffix || '';
$scope.step = function (s) {
console.log('step', prefix, s, suffix);
return prefix + s + suffix;
};
},
template: function (elem, attr) {
return `
<h2>Fusce lorem ante</h2>
<ul>
<li check-step="{{step(1)}}">Vestibulum efficitur</li>
<li check-step="{{step(2)}}">Arcu vitae iaculis sodales</li>
<li check-step="{{step(3)}}">Ligula ex interdum neque</li>
<li check-step="{{step(4)}}">Ac iaculis felis lectus in purus.</li>
</ul>
`;
}
};
});
app.directive('checkStep', function () {
return {
restrict: 'A',
scope: {
name: '@checkStep'
},
link: function ($scope, $elem, $attr) {
console.log('link', $scope.name);
}
};
});
})();
—- Update —-
Why did the following code works:
<li check-step="{{1+step(1)}}">Vestibulum efficitur</li>
But this doesn’nt:
<li check-step="{{step(1)}}">Vestibulum efficitur</li>
?
2
Answers
It wont' work because
link
of an inner component get called always before of alink
function of an outer component. The right place for exposing API for descendants iscontroller
.The question
is incorrect. This is not working, at least as expected. When AngularJS evaluates
1+step(1)
it yields just1
instead of1 + <result of step(1)>
. This is due to the fact thatstep
function is not defined yet! Although isolated or inherited scope might be created (if it was specified).Here is what happened:
custom-include
. An isolated one withtype
field will be created, as it was specified in DDO ({scope: {type: '@'}}
).custom-include.controller
. This is the time where you can add some API for children components. But it was not specified in DDO, so it won't be called.check-step
. An isolated one withname
field will be created, as it was specified in DDO ({scope: {name: '@checkStep'}}
).check-step.controller
. Again, since it was not specified in DDO, nothing will be called.check-step.link
. This time you can add some event listeners.custom-include.link
.The solution is to move
$scope.step = function (s) {...}
intocontroller
. That way, whencheck-step.link
function will be called,step
function will be defined in parent scope and will be called. The drawback of this methods is that whencheck-step.name
get changed,check-step.link
wont be notified about it....
To summarize:
The attribute value is computed and put on the isolate scope after invocation of the link function. Use a
$watch
to see the eventual value:The DEMO on PLNKR