Angular directive template switch - angularjs

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

Related

ng-if not evaluating inside directive

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

Cant use directive controller values in directive template

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;
}
};
}

How to change the value of a $scope.variable in a controller from a directive in angularJS?

I am very new to the concepts of angularJS. The problem I am facing is I have declared a variable $scope.myVariable = true in my controller. I need to toggle the the value of $scope.myVariable from the directive. Is it possible to do that.. if yes how??
Please help..
From a directive, you can access the scope through the link function:
app.directive('myDirective', function() {
return {
restrict: 'E',
transclude: true,
scope: {},
controller: 'MyController',
templateUrl: 'my-template.html',
link: function (scope, element) {
scope.name = 'Jeff';
}
};
});
See https://docs.angularjs.org/guide/directive
If you want to use Angularjs Directive, you can use 3 methods of it's scope
1) true (inherit)
2) false (not inherit)
3) {} (Isolated)
if you use 1) method, you have to work with it's parent scope, because that variable is in parent scope
if you use 2) method you don't have to do anything else.You are working with current scope
if you want more with examples here is a cool link
http://www.w3docs.com/snippets/angularjs/bind-variable-inside-angularjs-directive-isolated-scope.html
You can pass the reference of "myVariable" from your main controller to the directive like this :
//index.html
<my-directive myvar="myVariable"></my-directive>
//myDirective.js
app.directive('myDirective', [function () {
return {
restrict: "E",
require: 'myvar',
scope: {
myvar:"=" //"=" mean, you can set the variable (your toggle function needs that)
},
templateUrl: "./directives/myDirective/myDirectiveView.html",
controller: "myDirectiveController as myDirectiveCtrl"
}
}]);
With this solution, myvar in the directive contains the reference to myVariable of the main controller and you can use it with $scope.myvar in the directive.
EDIT :
for example, if you have a list for object contains src and compression var like this :
{ src:"path/to/img", compressed:false}
<div ng-repeat="imgObj in imgObjList">
<my-directive myvar="imgObj"></my-directive>
</div>
In the my-directive view :
<img ng-src="myvar.src" ng-show="myvar.compressed == true"/>
In your my-directive Controller :
you can set myvar.compressed to true when encoding is finished

Directive inside directive. Compile is not working?

I am still rather new to angular JS, and wanted to learn about directives. I want to make a nested directives, kind like menu such as this:
<myDirective>Hello</myDirective>
Pretty simple, and I've put it like this with $compile:
.directive('myDirective', function($compile) {
return {
restrict: 'E',
transclude: true,
template: '<dialog2><div ng-transclude></div></dialog2>',
link: function (scope, element, attrs) {
$compile(element.contents())(scope);
}
};
})
.directive('dialog2', function() {
return {
restrict: 'E',
transclude: true,
template: '<b>Hi</b><div ng-transclude></div> there'
};
});
Now, it only shows as
Hello
And it should say
Hi Hello there
Where did I do wrong?
Thank you
Just simple thing to note when declare a directive in html use my-directive instead of myDirective
<my-directive>Hello</my-directive>
Also no need to complie in same contents again without modifying DOM.If you any directive/custom directive applied in template or templareUrl angularjs will complie for us before handover to us.
Demo link

Load angular directive in view, based on $scope value

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

Resources