I start learning AngularJS today with directive ... I can't get directive work. Please help
<html ng-app="ngBasic">
<head>
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script>
var app = angular.module('ngBasic', []);
app.controller('ngBasicCtrl', function($scope) {
$scope.age = 20;
});
app.directive('myDirective', function($scope) {
return {
template: '<h1>{{age}}</h1>'
}
});
</script>
</head>
<body ng-controller="ngBasicCtrl">
<h1>{{age}}</h1>
<my-directive></my-directive>
<div my-directive></div>
<div class='my-directive'></div>
</body>
</html>
https://jsfiddle.net/bigzidane/t8Lv3mpg/2/
Currently, the page onlys show 20. Expecting tag but not displaying yet.
Use the scope option to create an isolated scope the template can refer to :
app.directive('myDirective', function() {
return {
scope: {
age: '='
},
template: '<h1>{{age}}</h1>'
}
});
Now you can pass the controller $scope's age to the directive scope, for example this way :
<my-directive age="age+1"></my-directive>
Will render out 21. Updated fiddle -> https://jsfiddle.net/t8Lv3mpg/3/
You have to remove the $scope from the function returning your directive as it does not take a $scope parameter.
app.directive('myDirective', function() {
return {
template: '<h1>{{age}}</h1>'
}
});
Related
I have a simple directive with transcluded html.
I want to be able to inject directive scope params to the transclude.
I wrote a simple example in plunker :
https://plnkr.co/edit/jqyiQdgQxbeTrzyidZYF?p=preview
I know in angular 4 it can be done, but I can't find a good way to do it in angularjs.
// Code goes here
var app = angular.module("app", []);
app.controller("mainCtrl", function($scope) {
$scope.users = ["tal", "oren", "orel", "shluki"];
$scope.deleteUser = (user) => {alert("trying to delete", user);}
});
app.directive('myList', function myList() {
return {
restrict: 'E',
transclude: true,
template: "<div><table><tr ng-repeat='item in collection'><td> This is inside myList - user name: {{item}} <ng-transclude></ng-transclude></td></tr></table></div>",
scope: {
collection: "="
},
replace: true
};
});
<!DOCTYPE html>
<html>
<head>
<script data-require="angularjs#1.6.2" data-semver="1.6.2" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="app" ng-controller="mainCtrl">
<h1>Hello Plunker!</h1>
<my-list collection="users">
<h2>This is transclude</h2>
<button ng-click="deleteUser(user)">Delete user: {{user ? user : "User name should be here"}}</button>
</my-list>
</body>
</html>
Will really appreicate some help.
plunker: https://plnkr.co/edit/jqyiQdgQxbeTrzyidZYF?p=preview
Here's a working plunker with your example.
http://plnkr.co/edit/BjSowyQdLXd0xoCZFqZ6?p=preview
The idea is to pass it as contents and not html as string. $compile is here because the link is done after ng-repeats already has transcluded its own template.
var template = '<h1>I am foo</h1>\
<div ng-repeat="item in users">\
<placeholder></placeholder>\
<hr>\
</div>';
var templateEl = angular.element(template);
transclude(scope, function(clonedContent) {
templateEl.find("placeholder").replaceWith(clonedContent);
$compile(templateEl)(scope, function(clonedTemplate) {
element.append(clonedTemplate);
});
});
If you want a proper explanation of what the problem was you should check the detailed answer here : Pass data to transcluded element
Hope this helped you out
I would like to create a custom directive to which I can pass an object (created on the fly) with interpolated values.
Example:
Newly created array as a parameter:
{userName: vm.data.name}
vm.data.name should be replaced with controller data.
Here is my code:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Custom directive</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.1/angular.min.js"></script>
<script>
(function(angular) {
'use strict';
angular.module('testDirectiveApp', [])
.controller('testController', ['$scope', function($scope) {
var data = {
name: 'ABC'
}
var vm = this;
vm.data = data;
}])
.directive('customDirective', ['$interpolate', function($interpolate) {
return {
scope: {
customParam: '='
},
link: function(scope, element, attributes){
scope.$watch('customParam', function() {
console.log(attributes.customParam, $interpolate(attributes.customParam)(scope), scope.$eval(attributes.customParam));
});
}
};
}]);
})(window.angular);
</script>
</head>
<body ng-app="testDirectiveApp">
<div ng-controller="testController as vm">
Name: <input ng-model="vm.data.name"> <hr/>
<div custom-directive custom-param="{userName: vm.data.name}"></div>
<p>{{vm.data.name}}</p>
</div>
</body>
</html>
Is this doable? What I'm doing wrong?
Best Regards,
The problem is that you are trying to access a scope variable with the attributes object, and not the scope object.
In your directive, change attributes.customParam to scope.customParam
http://plnkr.co/edit/1o4746GamtIcwHekoKyl?p=info
I have the following directive:
angular.module("example_module", [])
.directive("example_directive", function() {
return {
compile: function(element) {
element.html('{{example}}');
return function($scope) {
$scope.example = "Hello world";
};
}
};
});
and the following HTML code:
<!DOCTYPE html>
<html ng-app="example_module">
<head>
<meta charset="utf-8">
<title>Example title</title>
<script src="lib/angular/angular.min.js"></script>
<script src="js/example.js"></script>
</head>
<body>
<div example_directive></div>
</body>
</html>
I would expect the directive to compile to Hello world, but it compile to an empty string instead. Where is the error?
I could use template or a link function, but my goal here is to understand how the compile function works.
This has to do with how angular handles directive names. I've changed your example to match angular's naming conventions and put together a Plunk
angular.module("example_module", [])
.directive("exampleDirective", function() {
return {
compile: function(element) {
element.html('{{example}}');
return function($scope) {
$scope.example = "Hello world";
};
}
};
});
<body>
<div example-directive></div>
</body>
I have a directive that works fine when used in isolation, but when it is used inside an ng-repeat it quits working. I know that ng-repeat creates it's own isolate scope, but that shouldn't matter since I'm not trying to do anything outside of the isolate scope of my directive. I've created a plunker to demonstrate the problem which you can see here: http://plnkr.co/edit/Y4ADmznnDCZvuxJrcZQ0?p=preview.
In the compile function of the directive I am adding an ng-click attribute to the element. Notice that the "This works" link (which is not in an ng-repeat) works fine but the other links (which are inside ng-repeat) do not work.
Here is the directive from the plunker:
var app = angular.module('plunker', []);
app.controller("AppCtrl", function($scope) {
$scope.users = [{
name: 'John',
id: 1
}, {
name: 'anonymous'
}];
});
app.directive("myDir", function($compile) {
return {
controller: 'directiveController',
compile: function(el) {
el.removeAttr('my-dir');
el.attr('ng-click', 'fxn()');
var fn = $compile(el);
return function(scope){
fn(scope);
};
}
};
})
.controller("directiveController", function($scope) {
$scope.fxn = function() {
alert('It works');
};
});
And here is the html:
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.2.x" src="http://code.angularjs.org/1.2.12/angular.js" data-semver="1.2.12"></script>
<script src="app.js"></script>
</head>
<body>
<div>
<a my-dir>This works</a>
<a my-dir ng-repeat="id in [1,2]"><br>This does not work</a>
</div>
</div>
</body>
</html>
Try it with binding the event in the link function instead of adding another attribute that has to be compiled (DEMO):
app.directive("myDir", function($compile) {
return {
controller: 'directiveController',
compile: function(el) {
el.removeAttr('my-dir');
var fn = $compile(el);
return function(scope, el){
el.bind('click', scope.fxn);
fn(scope);
};
}
};
})
Below is my code
I created a simple page and include a directive in it. And on ng-click in directive i want to call parent scope's method.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Directive Page</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"> </script>
</head>
<body>
<div ng-app="myapp" ng-controller="myController">
<ul-dir on-item-click="itemClick(obj)"></ul-dir>
</div>
</body>
</html>
<script>
var myapp = angular.module("myapp", []);
myapp.directive('ulDir', function() {
return {
restrict: 'E',
replace: 'true',
template: '<div id="container"><ul><li ng-repeat="content in contents">{{content.name}}</li></ul></div>',
controller: function ($scope) {
$scope.contents = [{'name':'Nishu', 'age':'20'},{'name':'Nidhi', 'age':'21'},{'name':'Kirti', 'age':'24'}];
},
scope: {
onItemClick: '&' // Pass a reference to the method
}
}
});
myapp.controller('myController', function($scope) {
$scope.itemClick = function(content){
console.log("Success : "+content);
};
});
</script>
So my console log print as "success : undefined"
So content object not passing from directive scope to parentscope.
Please help me.
I believe your call inside template should either be:
<a href="#" ng-click="onItemClick({'content':content})">
or
<a href="#" ng-click="onItemClick({'obj':content})">
Can you try. For more details see this SO post Can an angular directive pass arguments to functions in expressions specified in the directive's attributes?