I have a directive defined in angular, which function look like this:
function(){
'use strict';
return {
restrict: 'E',
replace: 'true',
scope: {reusableScope: '='},
template: '<div>' +
'<cool-directive></cool-directive>' +
'</div>',
};
coolDirective is an outside directive, that is working fine in this setup. But at the moment that I put my template in a .html file and call it throught templateUrl attribute, the directive the was defined inside the template just stop working at all.
function(){
'use strict';
return {
restrict: 'E',
replace: 'true',
scope: {reusableScope: '='},
templateUrl: 'template.html',
};
being template.html this:
<div>
<cool-directive></cool-directive>
</div>
Why this is happening and how to fix this issue? is there a workaround for this?
Related
I have created a directive like this
.directive('optionLabel', function() {
'use strict';
return {
replace: true,
restrict: 'AE',
template: '<div class="error-msg col-xs-12 intelligent-group col-centered"><h1 translate>{{ optionLabel }}</h1></div>'
};
})
Right now the Scope optionLabel is set in each of the controllers that uses this directive as such.
$scope.optionLabel = labelService.getOptionLabel(search.searchType);
How could I set this in the directive directly, rather than doing this code repeated in like 5 controllers ?
You can use link in which you have access to your scope :
.directive('optionLabel', function() {
'use strict';
return {
replace: true,
restrict: 'AE',
template: '<div class="error-msg col-xs-12 intelligent-group col-centered"><h1 translate>{{ optionLabel }}</h1></div>',
link: function(scope, element, attrs) {
scope.optionLabel = labelService.getOptionLabel(search.searchType);
};
})
Don't forget to inject labelService in your directive.
I'm using directive to display html snippets.
And templateUrl inside the directive,
to be able to include snippets as html file.
The directive does not work, if I try to call
inside a builtin ng-repeat directive
({{snip}} is passed as is, without substitute):
div ng-repeat="snip in ['snippet1.html','snippet2.html']">
<my-template snippet="{{snip}}"></my-template>
</div>
For reference, here is the directive:
app.directive("myTemplate", function() {
return {
restrict: 'EA',
replace: true,
scope: { snippet: '#'},
templateUrl: function(elem, attrs) {
console.log('We try to load the following snippet:' + attrs.snippet);
return attrs.snippet;
}
};
});
And also a plunker demo.
Any pointer is much appreciated.
(the directive is more complicated in my code,
I tried to get a minimal example, where the issue is reproducible.)
attrs param for templateUrl is not interpolated during directive execution. You may use the following way to achieve this
app.directive("myTemplate", function() {
return {
restrict: 'EA',
replace: false,
scope: { snippet: '#'},
template: '<div ng-include="snippet"></div>'
};
});
Demo: http://plnkr.co/edit/2ofO6m45Apmq7kbYWJBG?p=preview
Check out this link
http://plnkr.co/edit/TBmTXztOnYPYxV4qPyjD?p=preview
app.directive("myTemplate", function() {
return {
restrict: 'EA',
replace: true,
scope: { snippet: '=snippet'},
link: function(scope, elem, attrs) {
console.log('We try to load the following snippet:' + scope.snippet);
},
template: '<div ng-include="snippet"></div>'
};
})
You can use ng-include, watching the attrs. Like this:
app.directive("myTemplate", function() {
return {
restrict: 'E',
replace: true,
link: function(scope, elem, attrs) {
scope.content = attrs.snippet;
attrs.$observe("snippet",function(v){
scope.content = v;
});
},
template: "<div data-ng-include='content'></div>"
};
});
Just made changes in directive structure. Instead of rendering all templates using ng-repeat we will render it using directive itself, for that we will pass entire template array to directive.
HTML
<div ng-init="snippets = ['snippet1.html','snippet2.html']">
<my-template snippets="snippets"></my-template>
</div>
Directive
angular.module('myApp', [])
.controller('test',function(){})
.directive("myTemplate", function ($templateCache, $compile) {
return {
restrict: 'EA',
replace: true,
scope: {
snippets: '='
},
link: function(scope, element, attrs){
angular.forEach(scope.snippets, function(val, index){
//creating new element inside angularjs
element.append($compile($templateCache.get(val))(scope));
});
}
};
});
Working Fiddle
Hope this could help you. Thanks.
it seems you are trying to have different views based on some logic
and you used templateUrl function but Angular interpolation was not working, to fix this issue
don't use templateUrl
so how to do it without using templateUrl
simply like this
app.directive("myTemplate", function() {
return {
link: function(scope, elem, attrs) {
$scope.templateUrl = '/ActivityStream/activity-' + $scope.ativity.type + '.html'
},
template: "<div data-ng-include='templateUrl'></div>"
};
});
hope this is simple and esay to understand
DEMO
Here is a simplified version of the two directives I have, my-input and another-directive:
HTML:
<body ng-controller="AppCtrl">
<another-directive>
<my-input my-input-model="data.firstName"></my-input>
</another-directive>
</body>
JS:
.directive('myInput', function() {
return {
restrict: 'E',
replace: true,
scope: {
model: '=myInputModel'
},
template: '<input type="text" ng-model="model">'
};
}).directive('anotherDirective', function($compile) {
return {
restrict: 'E',
scope: {},
compile: function(element) {
var html = element.html();
return function(scope) {
var output = angular.element(
'<div class="another-directive">' +
html +
'</div>'
);
$compile(output)(scope);
element.empty().append(output); // This line breaks the binding
};
}
};
});
As you can see in the demo, if I remove element.empty().append(output);, everything works fine, i.e. changes in the input field are reflected in controller's data. But, adding this line, breaks the binding.
Why is this happening?
PLAYGROUND HERE
The element.empty() call is destroying all child nodes of element. In this case, element is the html representation of another-directive. When you are calling .empty() on it, it is trying to destroy its child directive my-input and any scopes/data-bindings that go with it.
A somewhat unrelated note about your example. You should look into using transclusion to nest html within a directive, like you are doing with another-directive. You can find more info here: https://docs.angularjs.org/api/ng/service/$compile#transclusion
I think a little bit context as to what you are trying to do well be helpful. I am assuming you want to wrap the my-input directive in another-directive ( some sort of parent pane ). You could accomplish this using ng transclude. i.e
angular.module('App', []).controller('AppCtrl', function($scope) {
$scope.data = {
firstName: 'David'
};
$scope.test = "My test data";
}).directive('myInput', function() {
return {
restrict: 'E',
replace: true,
scope: {
model: '=myInputModel'
},
template: '<input type="text" ng-model="model">'
};
}).directive('anotherDirective', function($compile) {
return {
restrict: 'E',
transclude: true,
scope: {},
template : '<div class="another-directive"><div ng-transclude></div></div>'
};
});
It works if you require ngModel
}).directive('anotherDirective', function($compile) {
return {
restrict: 'E',
require:'ngModel',
scope: {},
...
I am working on multiple directive, this is already existing framework so I dont want to disturb the existing components.
This is my HTML
<div title="test" mydirective>
This is my directive, this has templateUrl with it and this template has another directive getting loaded.
.directive('myDirective', function ($filter) {
restrict: 'A',
replace: true,
transclude: true,
scope: {
title: '#'
},
templateUrl: 'partial/partialtemplate.tpl.html'
});
My Partial Template html looks like this
<div newdirective title="{{title}}"></div>
This is my newdirective
.directive('newDirective', function ($filter) {
restrict: 'A',
replace: true,
transclude: true,
scope: {
title: '#'
},
templateUrl: 'partial/newpartialtemplate.tpl.html',
controller: function ($scope, $attrs) {
//here if I try to print my title I still get {{title}}
console.log($attrs.title);
}
});
So what could the issue be, I the second directive being called even before the template data is written or anything wrong?
I have a directive in isolated scope and i define a couple of variables in link function of the directives so the template fails to bind to these variables but templateUrl seems to bind to these variables easily... what is the reason for this?
mymodule.directive("directive1", function () {
return {
require: '^widget',
// template: '<div><h1 > {{editMessage}}</h1></div>',
templateUrl: "dummy.htm",
scope: {
},
link: function (scope, element, attrs) {
scope.editMessage = "Click to edit";
});
}
});
my dummy.htm has the same piece of code as in template contents:-
<div><h1 > {{editMessage}}</h1></div>
the binding happens when i use templateUrl but not when i use template why is it so? is the execution flow different for both of these?
the problem is you're not integrating well the scope variable, it should be and this example:
mymodule.directive('myAlertaSeguimientoButton', function() {
return {
restrict: 'A',
scope: {
myParamElemento: '=',
myParamUrl: '#',
myParamSeguir: '#',
myParamDejarSeguir: '#',
myParamSiguiendo: '#',
myParamRefrescaMapa: '#'
},
template: '<button ng-class="(!myParamElemento.siguiendo)?\'btn btn-default seguir\':\'btn btn-default seguir siguiendo activeButtonAzul\'" class="btn btn-default seguir" ng-click="seguirNoSeguir(myParamUrl)"><span class="icon-seguir estadoUno">[[myParamSeguir]]</span><span class="icon-siguiendo icon-w estadoDos">[[myParamSiguiendo]]</span><span class="estadoTres">[[myParamDejarSeguir]]</span></button>',
controller: ['$scope', 'Service', function($scope, Service) {...
And in the html:
<span my-param-elemento="angular-var" my-param-url="angular-var" my-alerta-seguimiento-button></span>