i'm trying to include directives in my application, but even basic directives aren't rendering. what am i doing wrong?
angularloader.js:
var main = angular.module('ngMain', [])
.directive('myScrollable', function () {
return {
restrict: 'AE',
template: '<h3>Hello World!!</h3>'
};
});
My HTML:
<html ng-app dir="auto">
<head>
<meta name="viewport" content="width=device-width" />
<title>#Model.Title</title>
<script src="/Scripts/Libs/angular.js"></script>
<script src="/Scripts/Custom/angularloader.js"></script>
</head>
<body dir="auto">
<my-scrollable></my-scrollable>
</body>
</html>
tried also using tag or attribute ..
you should use module name in ng-app="moduleName"
like:
<html ng-app="ngMain" dir="auto">
if you assign angular module in a variable then use that variable like bellow:
var main = angular.module('ngMain', []);
main.directive('myScrollable', function () {
return {
restrict: 'AE',
template: '<h3>Hello Worlds!!</h3>'
};
});
Working PLUNKER Link
You have define your module but forget to use in html with ng-app= "you module Name". One extra thing you don't need to declare a variable main your code will work without that also.
angular
.module('myModule', [])
.directive('myDir', function{
your code
});
Related
Directive code:
.directive('replace', function($compile) {
return function (scope, element) {
element.html(element.html().replace("Hej", "Hey!"));
$compile(element.contents())(scope);
}
});
})
HTML
<div ng-controller="GreeterController">
<div replace>Hej <div ng-repeat="e in arr">{{ e }}</div>
</div>
</div>
Controller
app.controller('GreeterController', ['$scope', function($scope) {
$scope.arr = [1, 2, 3, 4];
}]);
Live example
As the title says, ng-repeat doesn't work when I'm using the directive from above on HTML which contains it.
But once I remove that line which uses .replace() command to replace part of HTML then ng-repeat starts working for some reason.
Does anyone know where's the actual problem?
I have tried everything and I still seem to not get it why it doesn't work as it should.
The manipulation can also be done in the compile phase:
app.directive("replace", function(){
return {
compile: function(element){
element.html(element.html().replace('Hej', 'Hey!'));
/*return {
pre: function(scope, element){
element.html(element.html().replace('Hej', 'Hey!'));
}
}*/
}
};
});
The original problem was caused because the linking of the ng-repeat directive was done before the element with that directive is replaced with the replace operation. The watchers associated with the ng-repeat directive then operate on elements that are no longer attached to the visible DOM.
By moving the replace operation to either the compile phase or the preLink phase, the replacing of the element that has the ng-repeat directive is done before the ng-repeat directive is linked. The watchers associated with ng-repeat directive then work with the replaced DOM.
You should let Angular and its change detection cycle do the HTML manipulation for you, instead of directly changing it yourself.
I've edited your example to use scope bindings to achieve what you wanted:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-compile-production</title>
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
</head>
<body ng-app="compileExample">
<script>
angular.module('compileExample', [], function($compileProvider) {
// configure new 'compile' directive by passing a directive
// factory function. The factory function injects the '$compile'
$compileProvider.directive('replace', function($compile) {
return {
link: function (scope, element) {
scope.greeting = 'Hey!';
$compile(element.contents())(scope);
}
}
});
})
.controller('GreeterController', ['$scope', function($scope) {
$scope.test = [1, 2, 3, 4];
$scope.greeting = 'Hej';
}]);
</script>
<div ng-controller="GreeterController">
<div replace>{{greeting}} <div ng-repeat="e in test">{{ e }}</div></div>
</div>
</body>
</html>
<!--
Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
-->
Note: I removed "scope: false" as that is the default behaviour.
EDIT:
Since you must replace HTML in place here's a solution with jQuery:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-compile-production</title>
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script
src="https://code.jquery.com/jquery-3.1.1.min.js"
integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
crossorigin="anonymous"></script>
</head>
<body ng-app="compileExample">
<script>
angular.module('compileExample', [], function($compileProvider) {
// configure new 'compile' directive by passing a directive
// factory function. The factory function injects the '$compile'
$compileProvider.directive('replace', function($compile) {
return function (scope, element) {
$(element).find( ".translation" ).replaceWith("Hey!");
}
});
})
.controller('GreeterController', ['$scope', function($scope) {
$scope.arr = [1, 2, 3, 4];
}]);
</script>
<div ng-controller="GreeterController">
<div replace><span class="translation">Hej</span> <div ng-repeat="e in arr">{{ e }}</div></div>
</div>
</body>
</html>
<!--
Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
-->
Solved it like this:
.directive("replace", function(){
return {
compile: function(){
return {
pre: function(scope, element){
element.html(element.html().replace('Hej', 'Hey!'));
}
}
}
};
});
Live example
I tried to pass the directive attribute value to template id and that can be used in another directive
Here is my index.html
<my-value name="jhon"></my-value>
Here is my js code
.directive('myValue',function(){
return {
restrict:"E",
templateUrl:"myname.html",
scope: {
name:"="
},
link:function(scope,element,attr) {
}
}
});
here is my myname.html
<div>
<p slide heading="name"></p>
</div>
In this above code "slide" is another directive
here is slide Directive code
.directive('slide',function(){
return{
restrict:"A",
link:function(scope,elem,attr){
console.log(attr.heading);
// Here i want the name first i assigned in index.html as like "attr.heading = jhon"
}
}
})
my problem is i assigned name="jhon" to my-value directive i want to send that name dynamically to my-value directive template and from there i have to assign that name to slide directive attribute heading= name and that have to use in slide directive link because i want to pass the name dynamically from one directive to that directive template and from there i have to assign to another directive attribute and that name have to use in slide directive link function
Thanks in advance
var app = angular.module("my-app",[]);
app.directive('myValue',function(){
return {
restrict:"E",
template:'<div><p slide heading="{{name}}"</p></div>',
scope: {
name:"="
},
link:function(scope,element,attr) {
}
}
});
app.directive('slide',function(){
return{
restrict:"A",
link:function(scope,elem,attr){
console.log(attr.heading);
// Here i want the name first i assigned in index.html as like "attr.heading = jhon"
}
}
})
app.controller('demoCtrl',['$scope',function($scope) {
$scope.myname = "john"
}]);
<!DOCTYPE html>
<html lang="en" ng-app="my-app">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
</head>
<body>
<div ng-controller="demoCtrl">
<my-value name="myname"></my-value>
</div>
</body>
</html>
just change the below lines.
myname.html
<div>
<p slide heading="{{name}}"></p>
</div>
index.html
<my-value name="myname"></my-value>
here asign some controller variable instead of static name "john" for two way data binding to work. e.g
app.controller("...",function($scope){
$scope.myname = "john"
})
In the following simple example I am printing the name model from controller by directive on the view. The example is running fine, but what is the use of transclude I cannot understand. Can someone explain its usage?
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js" ></script>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<people></people>
<script>
//module declaration
var app = angular.module("myApp",[]);
//controller declaration
app.controller('myCtrl',function($scope){
$scope.name = "Peter";
});
//directives declaration
app.directive('people',function(){
return{
restric: 'E',
template: '<div>{{name}}</div>',
transclude: true
}
});
</script>
</body>
</html>
Your code doesn't really demonstrate what transclude does:
Look at this plunk and change the true/false value:
Plunk
You will notice the effect now hopefully. The source from plunkr, with a couple of modifications.
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#1.5.3" data-semver="1.5.3" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<people>HI there</people>
<script>
//module declaration
var app = angular.module("myApp",[]);
//controller declaration
app.controller('myCtrl',function($scope){
$scope.name = "Peter";
});
//directives declaration
app.directive('people',function(){
return{
restric: 'E',
template: '<div><ng-transclude></ng-transclude>: {{name}}</div>',
transclude: false
}
});
</script>
</body>
</html>
So when it is true, you will see that the contents are transcluded,
So it says HI There: Peter
When False, it removes the HI There, but keeps the name and my colon:
: Peter
Essentially, these are wrappers around any arbitrary content.
Supposing I have an accordion directive that shows or hides any content that you use it with with an animation.
app.directive('akordion', [function() {
return {
restrict: 'A',
replace: true,
transclude: true,
template: '<div class="accordion-wrapper">'
+'<div class="transcluded" ng-transclude></div>'
+'</div>',
link: function(scope, elem, attrs) {
scope.$watch(attrs.show, function(newVal){
toggle(newVal);
});
function toggle(show) {
var h = (show) ? 0 : '600px';
$(elem).css({ maxHeight: h });
}
}
}
}]);
You'd use it like this:
<div akordion="" id="league-admin">
<div>
foo
</div>
<my-directive></my-directive>
</div>
And the result (generated HTML) is:
<div class="accordion-wrapper" id="league-admin">
<div class="transcluded">
<div>
foo
</div>
<div id="my-directive">...</div>
</div>
</div>
The point is that by calling the akordion="", you take whatever is inside it and put it in the template (<div class="transcluded" ng-transclude>). In other words, the akordion directive wraps over (transcludes) the content you use it on.
Another example would be modal windows. You don't want to repeat the code that defines the modal each time you want to use it, so you define it once, and use transclusion to put any content into it. Check out modal in Bootstrap UI.
Basically If you have some content inside your directive it will be automatically replaced by the directive content
For Example, if you have<people>Test transclude</people> The Test transclude string will be automatically replace by angular when it process the directive. But what if you want 'Test transclude ' also to be displayed ? Here is where transclude come in to action.
Consider the following
app.directive('people',function(){
return{
restric: 'E',
template: '<div><div ng-transclude></div>{{name}}</div>',
transclude: true
}
});
Now the string 'Test transclude' will be also displayed inside tag
And this is the plunker link Plunk
I am trying to create a custom directive..
<head>
<script type="text/javascript" src="../Scripts/angular.min.js"></script>
<script type="text/javascript" src="../Scripts/DataDirectives.js"></script>
</head>
<body style="overflow: hidden" >
<div ng-app="myApp">
<SampleData></SampleData>
</div>
</body>
In a separate Javascript File called DataDirectives.js the followung code is present..
var app = angular.module('myApp', []);
app.directive('SampleData', function () {
return {
restrict: 'E',
template: '<div>Sample Div,To test angular Directives</div>'
};
});
So when I run the page,I cannot see any text on that page of that of the div element.What could be wrong with my above code.
Thanks for the help in Advance... :)
You have 2 ng-app as well as you are not following the required naming convensions
var app = angular.module('myApp', []);
app.directive('sampleData', function() {
return {
restrict: 'E',
template: '<div>Sample Div,To test angular Directives</div>'
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<sample-data></sample-data>
</div>
in html write directive name: sample-data
in js sampleData
var app = angular.module('myApp', []);
app.directive('sampleData', function () {
return {
restrict: 'E',
template: '<div>Sample Div,To test angular Directives</div>'
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp" style="overflow: hidden" >
<div ng-app="myApp">
<sample-data></SampleData>
</div>
</body>
You are defining the angular directive in your template using camelcase naming convention. The angular directive should be declared in template like sample-data. Then in javascript file you can reference it like sampleData.
Taking these into consideration, you should change the code in the following manner:
<div ng-app="myApp">
<sample-data></sample-data>
</div>
Another alternative would be to declare the directive inside an existing element. For example:
<div sample-data="exp"></dir>
And in javascript:
var app = angular.module('myApp', []);
app.directive('sampleData', function () {
return {
restrict: 'E',
template: '<div>Sample Div,To test angular Directives</div>'
};
});
Please see the lower cased version of sampleData.
I'm trying to create a directive that will output a HTML-template that is using data from a controller.
In sample.js I've added a module, controller and directive
var app = angular.module("myApp", []);
app.controller("MyCtrl", function($scope) {
$scope.someProperty = true;
})
app.directive("myElement", function() {
return {
restrict: "E",
scope: {name: "#"},
template:
'<div ng-show="someProperty">' +
' <p>This element is called {{name}}</p>' +
'</div>',
replace : true,
transclude : false
}
})
I'm using the element with the following HTML
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="angular.min.js"></script>
<script type="text/javascript" src="sample.js"></script>
</head>
<body ng-controller="MyCtrl">
<div><my-element name="Mark"></my-element></div>
<div><my-element name="Vink"></my-element></div>
</body>
</html>
Since the controller is created in the body, I would expect the child-element to be able to use it's properties/methods. But there's no data showing up (without the ng-show, the data shows fine).
In this simplified sample I could move the ng-show to the DOM-element in the HTML, but in my actual application this wouldn't be an option. I really need my directive to be able to use properties (and methods) from my controller.
Is this possible? And what did I miss to get it to work?
Since you are using an isolated scope you have to declare someProperty to use it like this
app.directive("myElement", function() {
return {
restrict: "E",
scope: {
name: "#",
someProperty: "="
},
template:
'<div ng-show="someProperty">' +
' <p>This element is called {{name}}</p>' +
'</div>',
replace : true,
transclude : false
}
});
and you can use it like this
<my-element name="Vink" some-property="someProperty"></my-element>