i have a template file myfile.html and i'm writing an attribute directive in angular, the purpose of this directive is to insert the elements that are inside myfile.html after the element that the directive attribute was declared on. for example: will insert all the content of myfile.html after that div.
i tried to do it like so:
app.directive('myAngularDirective', function () {
return {
restrict: "A",
link: function(scope, element){
var addMe = angular.element("myfile.html");
element.after($copile(addMe));
scope.$apply();
}
}
});
<h1>myfile.html</h1>
<div ng-controller="myController">
<div ng-click=clickMe()></div>
</div>
<h1>my home page</h1>
<div my-angular-directive></div>
but nothing happens, the content of myfile.html is not added to the home page.
if i write plain html in the after function like so:
element.after("")
it does get added to the dom but angular do not digest it, and ng-click is not working.
thanks for your help.
$compile("<html here>") returns a template function that expects a scope to be passed before you get your DOM back. Change your code to the following and it should work as expected:
app.directive('myAngularDirective', function($compile) {
return {
restrict: "A",
link: function(scope, element){
var addMe = angular.element("<div>Hello World</div>");
element.after($compile(addMe)(scope));
scope.$apply();
}
}
});
If you want to load the template from an external URL. You'll need to do a template request.
app.directive('myAngularDirective', function($compile,$templateRequest) {
return {
restrict: "A",
link: function(scope, element){
$templateRequest('index.html').then(function(tpl){
var addMe = angular.element(tpl);
element.after($compile(addMe)(scope));
scope.$apply();
});
}
}
});
Related
I am trying to call a html page which is given in the templateUrl of my directive when I click a button, below is my code "hi" should be displayed when I click the "click me" button. Please suggest me how to do this.
sample.html:
<div ng-controller="MyController">
<button custom-click="">Click Me</button>
</div>
sample.js:
appRoot.directive('customClick', function() {
return {
link: function(scope, element, attrs) {
element.click(function(){
templateUrl:'/page.html';
});
}
}
});
Page.html:
<div><h4>HI</h4></div>
Update: The Snippet has been updated with getting the code from a URL
Adding onto the above answers:
appRoot.directive('customClick', function($http, $compile) {
return {
link: function(scope, element, attrs) {
element.click(function(){
$http.get("/page.html").then(function(resp){
$(element).html(resp.data);
var fnLink = $compile(element);
fnLink($scope);
});
});
}
}
});
P.S: Needs jQuery to run as using some functions like html() which can be bypassed if you dont want to include jQuery
I don't think that structure is possible, at all.
The easiest way would be to handle a show/hide type of functionality on the directive and have the template be there at all times.
For this you could use either ng-show, ng-hide or ng-if (and some others that I won't dig into).
base directive
appRoot.directive('customClick', function () {
return {
template: '<div><h5>HI</h5></div>',
link: function (scope, el, attrs) {
scope.active = false;
el.on('click', function () {
scope.$apply(function () {
scope.active = !scope.active;
});
});
}
}
});
ng-show
template: '<div ng-show="active"><h5>HI</h5></div>'
ng-hide
template: '<div ng-hide="!active"><h5>HI</h5></div>'
ng-if
template: '<div ng-if="active"><h5>HI</h5></div>'
Edit: If you are using templateUrl, simply put the ng-show/hide/if directive on the root element of the template being referenced, and this should work the same.
Oh, and here's a fiddle.
http://jsfiddle.net/ADukg/5426/
HTML
<div show-orders ng-click="showOrderDetails()" ></div>
Javascript
var ddApp = angular.module('ddApp', []);
ddApp.directive('showOrders', [function ($compile)
{
return {
link: function (scope, element, attrs)
{
scope.showOrderDetails = function ()
{
// How I would normally insert HTML.
element.append('<div order-details>Some text</div>');
// How do you use $compile here???
//el = $compile(tpl)(scope);
}
}
};
} ]);
ddApp.directive('orderDetails', [function ()
{
return {
link: function (scope, element, attrs)
{
// Do something
}
};
} ]);
When you click on the div, the showOrderDetails gets called. I then want to append some html to the div (i.e., insert it into the div). However, the html that I am inserting is a div containing another directive called order-details. How do I compile this html and insert it into the div so that Angular is aware of the order-details directive?
Another question. I'm not sure if placing the html code directly within the click event is the right solution. What if I wanted to have this come from some template, so that I could reuse the template elsewhere. Is it possible to load the html from a service or factory? If so, how? Is this the answer:
https://stackoverflow.com/a/15573493/753632
var template='<div order-details>Some text</div>'
element.append($compile(template)(scope));
yes it possible to load template using services
$http({method: 'GET', url: '/views/template'})
.success(function(data){
element.append($compile(data)(scope));
});
Given this directive:
myApp.directive('someDirective', ['$compile', '$templateCache', function($compile, $templateCache) {
return {
restrict: 'A',
link: function(scope, element, attr) {
// Load a template.
var template = $templateCache.get("partials/foo.html");
$compile(template)(scope);
$(element).append(template);
}
};
}]);
and given foo.html:
<div data-foo>Some Text</div>
and the foo directive:
myApp.directive('foo', [function() {
return {
restrict: 'A',
link: function(scope, element, attr) {
console.log('foo1');
$(element).on('click', function() {
console.log('foo2');
});
}
};
}]);
I will always see foo1 in my console but never foo2 when I click on the added element. In fact, though I can see the added elements just fine and can console.log() them just fine, I am unable to ever bind any handlers to them. What am I missing?
A div will have no height unless you put something in it. Change your div to this:
<div data-foo>Some content</div>
Also you need to make the template an element, do this as well right after you create it:
template = angular.element(template);
Here's a jsFiddle showing you: http://jsfiddle.net/c3Wuu/
As a side note, you should not be wiring up a click event, or building a template like this. Have a look at some videos and do angular tutorial unless you know what you're doing.
Edit
This is how you would wire it up using angular practices
in foo directive html:
<div data-foo>
<span data-ng-click="clickOne()">Click One</span>
<span data-ng-click="clickTwo()">Click Two</span>
</div>
In foo link function:
scope.clickOne = function(){
console.log("click one");
};
scope.clickTwo = function(){
console.log("click two");
};
By wiring up your own click function you are circumventing the point of angular.
I have my custom directive which is defined like this:
.directive("myDirective", [
return {
restrict: "E",
replace: true,
terminal: true, // otherwise we won't be able to compile a template
controller: "MyCtrl",
scope: {
...
},
compile: function (element, attrs) {
element.html("");
element.removeClass();
...
return {
post: function (scope, iElement, iAttrs, controller) {
loadTemplate(templUrl).then(function (templateElement) {
//iElement.replaceWith(templateElement);
iElement.append(templateElement);
var teLinkingFn = $compile(templateElement);
teLinkingFn(scope);
var modal = $("div.modal", templateElement);
if (modal.length > 0) {
scope._modal = modal;
templateElement.removeClass();
if (iAttrs.class) {
$("button", templateElement).eq(0).addClass(iAttrs.class);
}
}
});
...
Now, I use it with ng-if:
<my-directive ... ng-if="some_criteria"/>
The problem is when I replace original element and some_criteria changes I still have my custom html visible. But if I append to the directive it works (disappears). How can I resolve this?
When you replace the original markup <my-directive ... ng-if="some_criteria"/> with whatever's loaded in your template file, you lose the ng-if directive from that original markup. You can either add an ng-if on your template file, or, you can just not use the replace functionality.
Is there a particular reason you want it to be replaced?
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