I made a custom directive that retrieves data from a controller.
My variable is visible inside the scope element but when trying to access it, I got undefined
HTML
<map borders="vm.borders"></map>
Directive
angular.module('myApp.directives')
.directive('map', [ function() {
return {
restrict: 'E',
scope: {
borders: '='
},
link: function(scope, element, attrs) {
console.log(scope); //cfr linked image
console.log(scope.borders) //undefined
}
}
}]);
Here is the scope. It contains the borders variable.
What am I missing to retrieve this borders value ?
I could suggest to add an ng-if to the directive, because for example if vm.borders are got from a promise, ng-if is required:
<map borders="vm.borders" ng-if="vm.borders"></map>
Related
See codepen.
What do I have to do to make scope.test visible in my HTML when I give my directive an isolated scope, replacing "scope: false" with "scope: {}"?
My directive:
angular
.module("MyApp", [])
.directive("myDir", () => {
return {
scope: false,
restrict: "A",
link: (scope, element) => {
scope.test = 'my test';
}
};
});
My HTML:
<div ng-app="MyApp">
<div my-dir>{{test}}</div>
</div>
No Controller, only link function in my directive.
Earlier it had work because you had scope: false (shared scope).
In your case adding scope: {} to directive wouldn't reflected test value changes on screen. Because when scope: {} isolated scope created in directive, it binds that scope to the directive template if it present. In your case you don't have any template in your directive.
If you wanted to see input value you could change it by
Either using $parent convention like scope.$parent.test = 'my test'
OR shift the {{test}} inside directive template so that isolated scope will get compiled with directive template.
In basic words scope:false means - directive takes the same scope of controller from where it was called.
On other hand scope:{} is a isolate scope and it uses internal scope of directive and its effected on directive template only
You can try to play with ng-transclude something like:
<div my-dir>{{$parent.test}}</div>
and:
.directive("myDir", () => {
return {
scope: {},
transclude: true,
restrict: "A",
template: '<div ng-transclude></div>',
link: (scope, element) => {
scope.test = 'my test';
}
};
});
Codepan Demo
I can't seem to reach the link function scope variable from inside a function in my directive. The "elem" variable is defined, but the scope isn't. Why is that??
Here's my directive:
function contextMenu($document){
return {
scope: {
target: '=',
},
restrict: 'A',
link: function(scope, elem, attr) {
elem.bind('contextmenu',handleRightClick);
function handleRightClick(event) {
// do something with scope (scope is undefined)
}
}
}
};
How can I user the scope variable?
Thanks!
Uri
EDIT1:
I found I can use this to pass the scope to the function:
Passing parameters to click() & bind() event in jquery?, but this still doesn't explain why the scope variable is undefined.
EDIT2:
For completeness sake, this is how my directive is set up:
app.js
angular
.module('myModule', [])
.directive('contextMenu', ['$document', components.contextMenu])
and in the html:
<div context-menu target="testObject">
Make sure you are using the directive correctly. Since you didn't include the use of the directive in your template, I hope you used it something like this:
<div context-menu target="something"></div>
Then I am confused about the setup of your directive. Try this:
MyDirectiveModule.directive('contextMenu', function(){
return {
restrict: 'A',
scope: {
target: '#'
},
link: function(scope, element){
console.log(scope);
// don't use $scope!
}
};
});
Make sure to use scope instead of $scope in the link: part.
I am trying this:
app.directive('adminTemplate', ['stateService', function (stateService) {
return {
restrict: 'E',
scope: {
src: "="
},
templateUrl: src,
link: function (scope, element, attrs) {
scope.stateService = stateService;
}
};
}]);
But it's giving me an error with Typescript saying "Could not find symbol src".
How can I get the template and how could I call it with this directive?
Scope values are not accessible from within a directive's templateUrl. The attributes are not compiled yet, so from within this context it is not possible to access the scope.
Please check my answer on a similar question or the plunker
What I did there is using a template containing a div with ng-include.
Here is my directive:
return {
restrict: 'E',
scope: {
showBorder: '='
},
link: function (scope, element) {
alert(scope.showBorder);
Here is my directive written inside HTML:
<my-directive showBorder="true"></my-directive>
But alert saying - scope.showBorder is undefined?
What did I miss here?
Atribute names are camelcase.
So if you define showBorder in the scope you need to reference it with show-borderin your directive html.
ex:
<my-directive show-border="true"></my-directive>
I'm implementing a navigation directive that should have a elements for each nav item:
<navigation title="My Web Page">
Home
About
</navigation>
How Can I get access to those anchors? Accessing the element's children in link() only returns the template's children, not the 'a''s that I'm looking for.
.directive('navigation', function () {
return {
template: template,
restrict: 'E',
replace: 'true',
scope: {
title: '#'
},
link: function postLink(scope, element, attrs) {
// This only looks in the directive's template
console.log($(element).find('a'));
}
};
});
What am I missing? I'm looking forward to attatch an array of the anchors in the directive's scope and iterate trough them within the template.
In order to move the original content within the new template you need to use the transclude property. When translude is set to true the directive will delete the original content but also make it available for reinsertion within your template through the ng-translude directive. See example below.
Without transluding the orginal data the anchor tags are removed and that is why your link function cannot find them.
.directive('navigation', function () {
return {
template: '<div>Tansclude data here: <span ng-translude></span></div>',
restrict: 'E',
replace: true,
transclude: true,
scope: {
title: '#'
},
link: function postLink(scope, element, attrs) {
console.log($(element).find('a'));
}
};
});
I am a bit confused where your nav-tems are coming from, but I'll give it a go
I'm assuming your nav elements are defined in a controller that is parent to the directive
function myCtrl ($scope){
$scope.navArray=[{title: 'Link1', href: 'www.example.com'}, {...}];
}
you would them have to declare the array as an attribute in your directive
<navigation nav="navArray"></navigation>
and two-way-bind it to the scope of your directive
.directive('navigation', function () {
return {
template: '<div><a ng-repeat="link in nav" href="link.href">{{link.title}}</a></div>',
restrict: 'E',
replace: 'true',
scope: {
nav: '='
},
link: function postLink(scope, element, attrs) {
}
};
});
Remember, you want to stay away from DOM manipulation in your link function. Instead, I recommend using ng-repeat in your template, and make sure the array of nav items is passed to your directive's scope.
Edit: See Fiddle http://jsfiddle.net/nicolasmoise/8YQPh/3/