I can't get an ng-if to evaluate inside a directive. I was first calling a method that returned a boolean, but whatever the result the ng-if does not pick up the result, it always evaluates to false.
To try and pin point the issue I tried a simple inline expression (below) but even this always evaluates to false. When I remove the ng-if, the div shows. What am I doing wrong?
.directive('handsUpVideoOverlay', function() {
return {
restrict: 'E',
replace: true,
scope: false,
template: '<div class="handsOffOverlay" ng-if="1>0">' +
'</div>',
link: function($scope) {
}
};
})
UPDATE
This code works perfectly as a standalone Jsfiddle. It looks like the problem is something to do with the fact I am adding this directive as a child of another directive. The parent directive is 3rd party and is manually transcluding it's children.
UPDATE
Ok I got this working. The problem was the parent directive was removing any child directive and then adding it back without compiling them. I had to take my own copy of the 3rd party parent directive and change this in the link function:
// Make transcluding work manually by putting the children back in there
ng.element(element).append(oldChildren);
to this:
// Make transcluding work manually by putting the children back in there
for(var i = 0; i < oldChildren.length; i++) {
var template = oldChildren[i].outerHTML;
var linkFn = $compile(template);
var content = linkFn($scope);
$element.append(content);
}
UPD:
Since the question leads to directive in directive, and without $compile, angular won't know about the ng-if directive.So in the link function, build the elements to let template cimpiled.
OLD ANSWER(can ignore)
Your directive isn't end or you didn't post the entire code block.
This work as expected.
var app = angular.module("app", []);
app.controller("myCtrl", function($scope) {
$scope.test = 111;
});
app.directive('handsUpVideoOverlay', function() {
return {
restrict: 'E',
replace: true,
scope: false,
template: `<div class="handsOffOverlay" ng-if="1>0">Test Directive</div>`,
link: function($scope) {
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
<hands-up-video-overlay></hands-up-video-overlay>
</div>
Solved please check Jsfiddle link
Js code
app.directive('handsUpVideoOverlay', function() {
return {
restrict: 'E',
replace: true,
scope: false,
template: '<div class="handsOffOverlay" ng-if="1>0">lol' +
'</div>',
link: function($scope) {
}
};
});
html
<hands-up-video-overlay></hands-up-video-overlay>
Hope this will help you
Related
I want to access the full value of title in my directive.
The title in directive should show as "Hi from Sample".
Right now it's "Hi from".
can someone also explains why it's happening ?
angular code
angular.module('docsTransclusionExample', [])
.controller('Controller', ['$scope', function($scope) {
$scope.title = 'Sample';
}])
.directive('myDialog', function() {
return {
restrict: 'E',
replace: true,
transclude: true,
scope: {},
template: '<div>'+attr.title'</div>',
link: function(scope,title) {
scope.title = attr.title;
}
};
});
HTML
<my-dialog title="Hi from {{title}}"><h2>Hello</h2>
</my-dialog>
I figured it out. I'm posting the answer for anyone facing the same issue.
I assigned the value in a watcher inside my link function.
scope.$watch('somevalue', function(value){
if(value == true){
scope.title = attrs.title;
}
});
Note: somevalue can be any variable which changes. For me it's a value in the model.
Im having a hard time accessing the attributes passed in to my directive from the template of that directive. I want to be able to access 'companyId' from album.tmpl.html but no matter what i try i can't get it. The strangest part is i can see it has made its way in to the controller, but somehow it's not getting from the controller to the template. I know the template is correctly calling the controller as it can succesfully print out the value of 'testVar' which is initialised inside the controller. Any advice would be appreciated.
directive + directive controller
(function () {
'use strict';
angular.module('erCommon')
.directive('erAlbum', albumDirective)
.controller('AlbumController', AlbumController);
function AlbumController() {
var vm = this;
vm.testVar = "test var initiated";
}
function albumDirective($log) {
function albumLink(scope, element, attrs, AlbumController) {
//watch vars in here
}
return {
restrict: 'E',
scope: {
companyId: '=companyId'
},
bindToController: true,
templateUrl: 'components/temp/album.tmpl.html',
controller: 'AlbumController',
controllerAs: 'albumCtrl',
link: albumLink
};
}
})();
template ( album.tmpl.html
<div ng-controller="AlbumController as albumCtrl">
testVar: {{albumCtrl.testVar}}<BR>
companyId:{{albumCtrl.companyId}}<BR>
</div>
usage
<er-album company-id="2"></er-album>
output
test var: test var initiated
companyId:
You need to remove ng-controller from your template:
<div>
testVar: {{albumCtrl.testVar}}<BR>
companyId:{{albumCtrl.companyId}}<BR>
</div>
To achieve the result you wanted i had to modify the structure of your code slightly. Hope this helps you to understand the issue. Look for materials about isolated scopes which Angular uses with directives.
HTML:
<div ng-app="erCommon" ng-controller="AlbumController as albumCtrl">
<er-album company-id="2" test = "albumCtrl.testVar"></er-album>
</div>
Controller:
angular.module('erCommon', [])
.directive('erAlbum', albumDirective)
.controller('AlbumController', AlbumController);
function AlbumController() {
var vm = this;
vm.testVar = "test var initiated";
}
function albumDirective() {
return {
restrict: 'E',
scope: {
test: '=test',
companyId: '#companyId'
},
template: '<div> testVar: {{test}}<BR> companyId:{{companyId}}<BR> </div>', // it will work fine with templateUrl as well, just didn't want to cr8 another file...
link: function(scope, element, attrs){
//do whatever else you might need;
}
};
}
I want to make a directive with a switch between template and templateUrl. I'll write a little example.
HTML:
<my-menu template-url='/admin/my-template'> </my-menu>
JS:
angular
.module('MyModule', [])
.directive('myMenu', function($compile){
var x = false;
var y = function(scope, element){
return (element.templateUrl) : false ? '<div>You should give template-url</div>'
}
return{
restrict: 'E',
replace: true,
template: y,
templateUrl: '/admin/my-template'(i hard coded inhere)
}
})
If i use "template: x" it works. template will be false and i get my templateUrl, but with a simple function that will return false i get an error:
https://docs.angularjs.org/error/$compile/tplrt?p0=myMenu&p1=
Can i do something in this case? I really want to evaluate my directive scopes before. Thx and sorry for not having a plunker
In this example, I have two AngularJS KendoDatePickers. The first one works perfectly, if you click on the button you open the calendar. The second one is within a directive that has the transclude attribute set to true. If you click on the second button, you get an error.
My understanding is that the scope of the transcluded portion inherits from the control scope, so this should work. Where am I wrong?
This is the plunk
HTML
<input kendo-date-picker="picker" />
<button ng-click="openPicker()">Open Date Picker</button>
<my-window>
<input kendo-date-picker="picker2" />
<button ng-click="openPicker2()">Open Date Picker 2</button>
</my-window>
Javascript
var app = angular.module("app", [ "kendo.directives" ]);
app.controller('MyCtrl', function($scope) {
$scope.openPicker = function () {
$scope.picker.open();
};
$scope.openPicker2 = function () {
$scope.picker2.open();
};
});
app.directive('myWindow', function() {
return {
transclude: true,
scope: {
someVar: '='
},
restrict: 'EA',
template: function(element, attrs) {
var html = '<div ng-transclude></div>';
return html;
}
};
});
There are two things about your code:
first: you create an isolatedScope so you do not have access to the controller scope inside the directive scope.
second: transcluded content get their own scope. One way to work around this is by not using transclude at all, like the example below:
return {
transclude: false,
restrict: 'EA',
template: function(element, attrs) {
var html = '<div>'+element.html()+'</div>';
return html;
}
or use the link function and manually transclude the element with the scope of the directive
I have a directive defined as
Application.Directives.directive('listview', function() {
return {
restrict: 'EAC',
templateUrl: 'directives/listview/view.html'
};
});
And then want to include it from the main view like this
<div class="{{directiveName}}">
</div>
where directiveName equals "listview". However, it does not work. It generates the below code, but the listview directive does not get loaded
<div class="listview">
</div>
Yet, when I type the above generated code directly into the main template, it does load the directive. How come? How can I make it work?
So I found a way. What you'd want is something like this
<div {{directiveNameInScope}}></div>
But again, that doesn't work. So I created a directive to do it for you. It works like
<div loaddirective="directiveNameInScope"></div>
where the loaddirective directive looks like
Application.Directives.directive('loaddirective', function($compile) {
return {
restrict: 'A',
scope: { loaddirective : "=loaddirective" },
link: function($scope, $element, $attr) {
var value = $scope.loaddirective;
if (value) {
// Load the directive and make it reactive
$element.html("<div "+value+"></div>");
$compile($element.contents())($scope);
}
},
replace: true
};
});
I put it up on github here: https://github.com/willemmulder/loaddirective