append template partial on click event in directive - angularjs

I would like to be able to append a template from a partial on the click event of a button multiple times.
I've managed to add a div in the link function below, but I'm stuck. How do i replace it with a template?
Fiddle: http://jsfiddle.net/LPUZG/1/
app.directive('clicker', function($compile) {
'use strict';
return {
restrict: "A",
replace:false,
link: function(scope, element, attributes) {
element.bind("click", function(e){
element.parent().append('<div>hi</div>');
});
}
}
});
<div clicker>Click me</div>
EDIT: This partial contains some form input fields that will be filled out by the user and saved later on.
Thank you

Specifying template or templateUrl in a directive makes the directive replace the element with the content of the template. So your clicker div wont be in existence anymore.
Instead you can use ng-include:
<div ng-include="'partials/template.html'" ng-repeat="item in items"></div>
<!-- on click the add method adds to the items -->
<div ng-click="add()">Click Me To Add</div>

Related

Angular: template from inner html and add existing data

Trying to add li from template and add items from $scope.menuItems (controller)
Items don't display
http://plnkr.co/edit/Jo7Vml?p=preview
app.directive("menuDemo", function(){
return {
templateUrl: 'tree-renderer.html'
}
});
Here you go : http://plnkr.co/edit/8YV6cdCIPCjEOq3DtjAz?p=preview
First : added the following to the directive :
scope:{
menuItems:"=menuDemo"
},
This enable the two-way binding on the data you pass to the menu-demo attribute when using your directives, without this you can't pass data to your directive.
Second : remove the script tag in the tree-renderer.html and sub-tree-renderer.html. Script tag is only usefull when using ng-include along with it. You were just define a template part without using it like this.
Third adding a top level ng-repeat for the 1st level in tree-renderer.html and remove the one from index.html.
<div ng-repeat="menuItem in menuItems">
As you can see menuItems match with what i have defined in the scope:{} part.
Fourth : I added the binding of the function addItem and addSubItem so you can define your own way of adding items to the tree outisde of the directive.
EDIT : Another plnkr where i move out the <div ng-repeat="menuItem in menuItems"> http://plnkr.co/edit/MZ3nsY6WTG3EiNKhXjAv?p=preview.
As you can see i put the menu-demo call in a <span> tag within the <li> tag. This is because they both use isoled scope and if i want to use data from the ng-repeat loop the easiest way is to move the other directive in a child DOM element.
Note that i also change the name of the binding element to menuItem (i remove the 's').
That is not a correct way to declare a directive try something like this:
angular.module('myModule')
.directive('menu', [function () {
return {
restrict: 'A',
scope: true,
templateUrl: 'tree-renderer.html',
link: function ($scope, $element, $attrs) {
//here some functions that do something
}
};
}]);
By the way, try improve your questions!

Angular directive for simple animation

I have a template, inside that template is div with the class big-box and it's inside a div container called .movie-container.
Template,
.movie-container
.big-box
I want to animate the .big-box element to a height of 300px (from 0px) when a user clicks on the .movie-container.
I've tried to setup a directive with a click function but it's not working. When I click on the .big-box div it doesn't show the click in the console log.
app.directive('big-box', [function() {
return {
link: function(scope, elem, attrs) {
elem.bind('click', function() {
console.log ('click')
});
}
}
}]);
So I could use some tips.
The naming convention used for the directive is not correct. You have to use camel case while defining your custom directives.
app.directive('bigBox', [function() { // Use camel case
return {
link: function(scope, elem, attrs) {
elem.bind('click', function() {
console.log ('click')
});
}
}
}]);
and in your html you need to use it like this :
<div class="movie-container">
<div big-box> <!-- using the directive -->
click here
</div>
</div>
The name must be written using dashes and each dash represents a capital letter from the directive definition. It is a angularjs convention.
Here is a working fiddle.

how to make custom directive in angular?

I am trying to make custom directive in angular .I try to add input field in my view when I click on button .In other words I am trying to make one custom directive in which when user press the button it add one input field in the browser .I think it is too easy if I am not use custom directive Mean If I use only controller then I take one array and push item in array when user click on button and button click is present on controller.
But when need to make custom directive where I will write my button click event in controller or directive
here is my code
http://play.ionic.io/app/23ec466dac1d
angular.module('app', ['ionic']).controller('appcontrl',function($scope){
$scope.data=[]
}).directive('inputbutton',function(){
return {
restrict :'E',
scope:{
data:'='
},
template:'<button>Add input</button> <div ng-repeat="d in data"><input type="text"></div>',
link:function(s,e,a){
e.bind('click',function(){
s.data.push({})
})
}
}
})
I just need to add input field when user click on button using custom directive ..could you please tell me where i am doing wrong ?
can we make button template and click event inside the directive
The reason it doesn't work is because your registering your click handler with jQuery. So when the click handler fires it is out of the scope of angular so angular does not know it needs to update its bindings.
So you have two options, the first is to tell angular in the click handler, 'yo buddy, update your bindings'. this is done using $scope.$apply
$apply docs: https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$apply
e.bind('click',function(){
s.$apply(function() {
s.data.push({});
});
});
However angular already has built in directive for handling things like mouse clicks you can just use that and let angular do the work for you. This would be the better option.
so first in your view register a click handler on your button
<button ng-click="add()">Add input</button> <div ng-repeat="d in data"><input type="text"></div>
Then in your link simply add the add() method of your scope
s.add = function () {
s.data.push({});
}
Heres a working fiddle showing both examples. http://jsfiddle.net/3dgdrvkq/
EDIT: Also noticed a slight bug in your initial click handler. You registering a click but not specifying the button to apply it to. So if you clicked anywhere in the directive, not just the button, the handler would fire. You should be more specific when registering events manually, using ids, class names attributes etc.
The e or element property of the link function is a jqlite or full jQuery object of the entire directive. If you have jQuery included before angular it will be a full jQuery object. If not it will a jqlite object. A thinned out version of jQuery.
Here is a basic example for your logic .
var TestApp = angular.module('App', []);
// controller
TestApp.controller('mainCtrl', function mainCtrl($scope) {
$scope.data = [];
$scope.addDataItem = function () {
$scope.data.push({
someFilield: 'some value'
});
console.log('pushing value ... ');
}
});
// view
<div ng-app="App" class="container" ng-controller="mainCtrl">
<button type="button" ng-click="addDataItem()">Add an input</button>
<div ng-repeat="d in data track by $index">
<custom-directive model="d"></custom-directive>
</div>
</div>
// directive
TestApp.directive('customDirective', function customDirective() {
return {
restrict: 'E',
scope: {
model: '='
},
template: 'item -> <input type = "text" />',
link: function (scope, elem, attrs) {
console.log('scope.model', scope.model);
},
controller: function ($scope) {
// do staff here
}
}
});

AngularJs DOM manipulation in directive

I have a directive which shows a list of Users with their names as links.
Inside the the template of this directive I have following loop:
<ng-repeat="user in myctrl.users />
<a href="" >{{user.name}}</a>
Now I want to add an attribute directive to all the anchor tags with
with name edit-confirm-popup as shown below.
<ng-repeat="user in myctrl.users />
<a href="" edit-confirm-popup>{{user.name}}</a>
What I want to do is whenever user click on link of user's name I want to show a popup with popup's html inserted as sibling of the anchor element. I don't want to repeat the popup html when directive is compiled rather I want to insert it dynamically when user clicks on the link.
I am able to achieve following things :
1) attaching click event listener on directive element that is anchor element in directive's link function.
Don't know
i) how I should insert the template as I want to?
ii) I want the current user to be available in event listener so that I can check some conditions before I show the popup.
Here is my directive code :
function editConfirmPopup() {
function linkFunction(scope, iElement, iAttrs){
console.log(iElement);
iElement.on('click',function onEditUser(e){
console.log(e);
console.log('in event handler');
});
}
var directiveDefinitionObject = {
restrict: 'A',
scope: {
user: '=',
populateUser : '&'
},
controller: 'UserEditConfirmController',
controllerAs: 'userEdit',
link : linkFunction,
bindToController: true
};
return directiveDefinitionObject;
}
angular
.module('mymodule')
.directive('editConfirmPopup', editConfirmPopup);
ng-if directive conditionally appends (or removes) - not just shows/hides - the elements on which it operates.
Using the fact that ng-repeat creates a child scope for each iteration, you can then just use a simple toggle variable to decide whether to show/hide the additional HTML (that you call "popup"):
<div ng-repeat="user in myctrl.users">
<a ng-click="showPopup = !showPopup">{{user.name}}</a>
<div ng-if="showPopup">
The "popup" HTML
</div>
</div>

Replace the html of an element with the content of an external template in a directive?

I'm trying to create a directive which is a sidebar in my shell page that will change accordingly whenever a new route is hit, and will populate itself with the sub menu items relevant to that parent route. I have 4 different menus which are external templates and i want the contents of those html files to replace the menu, the link function of my directive looks like this so far:
link: function(scope, element, attrs, ngModel) {
scope.$on("$routeChangeSuccess", function (event, current, previous) {
element.html('<div ng-include=\'enterprisesMenu.html\'></div>');
});
};
But the element is not updating, however when i use inline templates the elements updates according, but because each template is complex i prefer not to have that html inside my directive, I've also tried element.html('<div ng-include src=\'enterprisesMenu.html\'></div>');
Any ideas?
Try $compile:
element.html($compile('<div ng-include=\'enterprisesMenu.html\'></div>')
(scope));
You could achieve this result by dynamically ng-including the desired template. For instance:
HTML:
<div class="your-sidebar" ng-controller="SidebarCtrl">
<div ng-include="sidebar.url" ></div>
</div>
Controller:
app.controller("SidebarCtrl", function($scope) {
$scope.sidebar = {
url: "initial-url"
};
$scope.$on("$routeChangeSuccess", function(event, current, previous) {
// decide potentially new value for $scope.sidebar.url
$scope.sidebar.url = newValueCalculatedAbove;
});
});
This solution does not require a directive, only an extra controller. It can be done with directive too, the HTML above is the template of the directive and the JS code the controller (no link function required).

Resources