I am new to AngularJs. I am writing my custom angular directive which contains a template of some html content. When I use the template with the below code it works fine.
demoApp.directive('demoCarousel', function() {
return {
restrict: 'E',
replace:'true',
template: "<h1>This is from the custom directive..</h1>"
};
});
But when I replace the template with templateUrl pointing to a html inside a partial I am getting error.
demoApp.directive('demoCarousel', function() {
return {
restrict: 'E',
replace:'true',
templateUrl: "/partials/carousel.html"
};
});
The javascript error is something like:
Error: [$compile:tplrt] http://errors.angularjs.org/1.2.15/$compile/tplrt?p0=glassCarousel&p1=%2Fpartials%2Fcarousel.html
Please let me know where I am going wrong and what the correct way to use the templateUrl
Note: I am using only pure html code inside the carousel.html file.
The error sais: Template for directive 'glassCarousel' must have exactly one root element. /partials/carousel.html
this means that you have something like this in your template:
<div>...</div>
<div>...</div>
It is not allowed, you should have one root element:
<div>
<div>...</div>
<div>...</div>
</div>
Related
I have a little directive and I have troubles to make it working.
here is my directive :
angular
.module('thermofluor')
.directive('myCustomer', function() {
return {
restrict: 'E',
template: 'table_plate.html'
};
});
The template is just a paragraph with "Test" inside.
In my main HTML in call the directive with this :
<my-customer></my-customer>
but nothing appear on the screen, and in the html the directive is not replace with the directives output html
The template have the same name and is in the same folder.
What am I doing wrong ?
Thanks.
It should be templateUrl
return {
restrict: 'E',
templateUrl: 'table_plate.html'
};
If you only need the template to show, you can use ng-include instead directive:
<ng-include
src="string"
[onload="string"]
[autoscroll="string"]>
...
</ng-include>
There is also the version for any element available:
<ANY
ng-include="string"
[onload="string"]
[autoscroll="string"]>
...
</ANY>
For even more info glance on https://docs.angularjs.org/api/ng/directive/ngInclude
Under either src or ng-include put the reference to the template you wish to load (depending on what version you use). For only 1 restrict it's kinda overkill to use a directive, rest you get from this approach as well.
NOTE: in above definitions, attributes in brackets are not needed for your example.
I'm having problems with angular directives. I created a custom directive but it's not appearing and i don't know why. I can access the view specified in templateUrl with using localhost.
If somebody could help me that would just be great.
Thanks.
messageListDirective.js
angular.module('neat')
.directive('message-list', function() {
return {
restrict: 'E',
templateUrl: '/views/utils/messageList.html'
}
});
messageList.html
<h4>MESSAGE LIST</h4>
And the view where I'm using the directive:
messageBoard.html
<message-list></message-list>
change directive:
.directive('message-list', function() {
to
.directive('messageList', function() {
angular normalize element tags. Read this for more info
Did you import ng-controller="neat" in your messageBoard.html ?
If yes I think you should check the url to template.
I'm creating an angularJs application in MVC 5. I've created a directive as given below.
app.directive('clusterButton', function () {
return {
restrict: 'E',
scope: {
clusterInfo: '=info'
},
templateUrl: function(elem, attr){
return 'ClusterButtonTemplate';
}
};
});
I have .cshtml file named ClusterButtonTemplate.cshtml and I created a partial view method in the controller class to return this view. So the angular js directive is binding the template.
I need to remove the method in mvc controller class and need to refer the template file directly. I don't want to use a cshtml file. I need a html file for template. I have created a ClusterButtonTemplate.html file. But while setting the template as below the browser shows a 404 error.
app.directive('clusterButton', function () {
return {
restrict: 'E',
scope: {
clusterInfo: '=info'
},
templateUrl: function(elem, attr){
return 'ClusterButtonTemplate.html';
}
};
});
I didn't use angular js routing in my project. Everything is managed using the MVC routing. How can I fix this issue. Do I need to use Angular routing and MVC routing?
You'll need to put in in a place where MVC will not try to map the URL to a controller. By default, the /Content folder is ignored, so you could create a folder under it called "Templates" and use that for the URL.
templateUrl: function(elem, attr){
return '/Content/Templates/ClusterButtonTemplate.html';
You may try to use a leading slash since it's loaded using a relative path.
templateUrl: function(elem, attr){
return '/ClusterButtonTemplate.html';
}
That's very simple! Just put an html file template (as content) in the folder that you prefer (ie. app/phone-list/ in project root) then assign
templateUrl: '/app/phone-list/phone-list.template.html'
to controller templateUrl property.
Avoid the views, model or controller folders...
I had a working angular app, but I want to restructure it a bit. I had a pile of directives that weren't really doing anything, and although the entire app was supposed to be encapsulated by a single directive, I still had my two main controller declarations outside that directive.
I merged those two controllers, because although they take care of different concerns (one handles functional data, the other navigation state), they are both necessary for the entire app.
Secondly, I wanted to get rid of the loose declaration and go from:
<div ng-app="myApp" class="myApp" ng-cloak ng-controller="myController">
<myAppdirective ng-controller="myNavigationController"></myAppdirective>
</div>
to:
angular.module('myApp').
directive('myAppDirective', ['myController', function(myController) { {
return {
restrict: 'AE',
replace: true,
scope: true,
controller: myController,
template: '<div>' +
'<ng-include src="\'partials/navigation.html\'">' +
'<ng-view></ng-view>' +
'</div>'
};
}]);
Mysteriously, this doesn't work. Shouldn't this work?
I get this error: https://docs.angularjs.org/error/$injector/unpr?p0=myControllerProvider%20%3C-%20myController%20%3C-%20myAppDirective
I tried using ngController inside the template, but that gave me TypeError: Cannot read property 'insertBefore' of null somewhere deep in angular code.
I'm at a loss. I'm probably doing somthing fundamentally wrong. But what?
Solution: I reverted the merging of my two controllers. This restores the separation of concerns I originally had, and it fixes that mysterious TypeError.
My directive now looks like this:
(function() {
'use strict';
/*global angular */
angular.module('myApp').
directive('myAppDirective', function() {
return {
restrict: 'AE',
replace: true,
scope: true,
controller: 'myController',
template: '<div ng-controller="myNavigationController">' +
'<ng-include src="\'partials/navigation.html\'"></ng-include>' +
'<ng-view></ng-view>' +
'</div>'
};
});
})();
This seems to work fine.
I don't think you can inject controller instances. That's probably where the error is coming from (based on that error, it looks like you renamed your actual controller name when posting the question). You should just need to use a string for the controller property.
angular.module('myApp').
directive('myAppDirective', [function() { {
return {
restrict: 'AE',
replace: true,
scope: true,
controller: 'myController',
template: '<div>' +
'<ng-include src="\'partials/navigation.html\'">' +
'<ng-view></ng-view>' +
'</div>'
};
}]);
See How can I use a registered controller in my angular directive?
By default, the scope property of every directive is set to false unless other specified. You are setting your scope to true, then applying the same controller that the directive is located in.
Simply put, remove scope: true, and controller: myController - your directive will inherit the scope from the parent controller and all will be well.
I have a directive that has a dynamic template, now I want the directive to have the ability to use different controllers. Is it possible to dynamically assign a controller to a directive? If possible, would that be the same "ctrlr" then passed to the link function?
.directive('myDirective',['$compile',function($compile){
return {
restrict: 'AE',
replace: true,
transclude: true,
scope: {},
templateUrl: function(el,attrs){
return (angular.isDefined(attrs.template)) ? attrs.template : '/tmpls/default';
},
link : function(scope,el,attrs,ctrlr,transFn){
[... Do Stuff Here ...]
},
controller: [ DYNAMIC CONTROLLER ASSIGNMENT?? ]
};
}]);
While I didn't find the corresponding documentation for it in the official API, you can dynamically pass in the name of the controller you want to use by utilizing the "name" attribute in conjunction with providing the "controller" attribute with a value that uses the similar syntax you'd use for an isolate scope.
Using your sample code, assuming a controller called "myController":
HTML:
<my-directive ctrlr="myController"></my-directive>
JS:
.directive('myDirective',['$compile',function($compile){
return {
restrict: 'AE',
replace: true,
transclude: true,
scope: {},
templateUrl: function(el,attrs){
return (angular.isDefined(attrs.template)) ? attrs.template : '/tmpls/default';
},
link : function(scope,el,attrs,ctrlr,transFn){
[... Do Stuff Here ...]
},
controller: '#',
name: 'ctrlr'
};
}]);
This is how it is done:
Inside your directive element all you need is an attribute which gives you access to the name of the controller:
<card-dealer ng-repeat="card in cards" card="card"></card-dealer>
in my case my card attribute holds a card object which has a name property.
In the directive you set the isolate scope to:
scope: { card: '=' }
This isolates and interpolates the card object to the directive scope. You then set the directive template to:
template: '<div ng-include="getTemplateUrl()"></div>'
this looks to the directive's controller for a function named getTemplateUrl and allows you to set the templateUrl dynamically as well.
In the directive controller the getTemplateUrl function looks like this:
controller: ['$scope', '$attrs', function ($scope, $attrs) {
$scope.getTemplateUrl = function () {
return '/View/Card?cardName=' + $scope.card.name;
};
}]
I have an mvc controller which links up the proper .cshtml file and handles security when this route is hit, but this would work with a regular angular route as well.
In the .cshtml/html file you set up your dynamic controller by simply putting
<div ng-controller="CardContactController"></div>
as the root element. The controller will differ for each template. This creates a hierarchy of controllers which allows you to apply additional logic to all cards in general, and then specific logic to each individual card. I still have to figure out how I'm going to handle my services but this approach allows you to create a dynamic templateUrl and dynamic controller for a directive using an ng-repeat based on the controller name alone. It is a very clean way of accomplishing this functionality and it is all self-contained.