Unable to render directive template properly in angularjs? - javascript

Here is the directive
module.exports = ()=>{
return {
restrict: 'E',
templateUrl: "/components/event/event.html",
scope: {index: '#'},
controller: "eventCtrl"
};
};
The code for controller
module.exports = ($scope)=>{
console.log($scope.index);
$scope.loadDetails = ()=>{
console.log("hello there");
}
};
and for template
.event
h3(ng-bind="index.title")
p(ng-bind="index.description")
.price(ng-show="index.is_paid") {{cost}} $
a.button-primary(ng-click="loadDetails()") Details
The problem is the variables are not being rendered in the template. I tested if it is being passed correctly using console.log and i am getting proper response. Also the function loadDetails() is working properly leading me to believe that there is not problem with setting up the controller. Where exactly am i going wrong ?

You have to change your scope: {index: '#'}, cause # mean it is for string ..so try with :
module.exports = ()=>{
return {
restrict: 'E',
templateUrl: "/components/event/event.html",
scope: {index: '='},
controller: "eventCtrl"
};
};

Related

Attribute undefined in custom directive in angularjs

I am creating a custom directive in angularjs, but for some attributes i am receiving undefined value.
function processinfo(ProcessInfoService, $timeout) {
console.log("processInfo directive");
return {
restrict: 'E',
scope: {
start: '=',
end: '=',
uuid: '='
},
templateUrl: 'k2-modules/js/directives/templates/processInfoTemplate.html',
controller: function($scope) {
var self = this;
console.log($scope.uuid); // undefined
console.log($scope.end); // 164982555555
console.log($scope.start); // 0
self.processData = ProcessInfoService.getInfo($scope.start, $scope.end);
}
}
}
<processinfo start="0" end="164982555555" uuid="a57cf6f8"></processinfo>
For uuid I am getting undefined but for end and start values everything is working fine. I don't know why this is happening since syntax is same for all three. Any help will be appreciated
Your mixing directive syntax with component/controller syntax, in directives $scope is called scope (no dollar). Here's the correct syntax to build a angularjs directive:
angular.module('app').directive('myDirective', MyDirective);
MyDirective.$inject = ['$timeout'];
function MyDirective($timeout) {
return {
scope: {
'propBinding1': '<',
'propBinding2': '&'
},
replace: true,
restrict: 'EA',
templateUrl: 'path to html',
link: function link(scope, element, attrs) {
//... do stuff here ...
}
};
}

Using getTrustedHtml method to get html from a url

I am trying to retrieve html code from a URL to use as my templateUrl and using getTrustedHtml to do it, however, I'm receiving a $sce:unsafe error.
app.directive('showResult', ['$sce', function($sce){
return {
restrict: 'E',
scope: {
info: '='
},
templateUrl: $sce.getTrustedHtml('https://raw.githubusercontent.com/aidanhall21/aidanhall21.github.io/master/showResult.html')
};
}]);
Here is a working solution for you: http://jsfiddle.net/yvbenitah/U3pVM/57716/
2 things:
you need to use trustAsResourceUrl, because you want to access a remote URL: angularjs doc.
directive will be like this:
.directive('showResult', ['$sce', function($sce){
return {
restrict: 'E',
scope: {
info: '='
},
templateUrl: $sce.trustAsResourceUrl('https://raw.githubusercontent.com/aidanhall21/aidanhall21.github.io/master/showResult.html')
};
You have to do the binding correctly if you want the string to be displayed.Where the directive will be used, you have to do
.controller('testCtrl', function($scope){
$scope.coucou = {name:"A NAME HERE"};
})
and in your html:
<show-result info="coucou"></show-result>
enjoy!

Angular component won't display

I have piece of html I want to show as a component, as I'm not manipulating the DOM.
As a directive it works fine, but as a component it doesn't. I have made components before with no problem, just can't see what the issue is here.
If I comment in the component code, and the directive out, it doesn't work.
Any idea what I've done wrong?
(function() {
"use strict";
angular
.module('x.y.z')
// .component('triangularStatus', {
// bindings: {
// value: '=',
// dimension: '=?'
// },
// templateUrl: '/path/to/triangular-status.html',
// controller: TriangularStatusController,
// controllerAs: 'vm'
// });
.directive('triangularStatus', triangularStatus);
function triangularStatus() {
var directive = {
scope: {
value: '=',
dimension: '=?'
},
replace: true,
templateUrl: '/path/to/triangular-status.html',
controller: TriangularStatusController,
controllerAs: 'vm',
};
return directive;
}
TriangularStatusController.$inject = [];
function TriangularStatusController() {
var vm = this;
}
})();
Here is the working code, most probably you are not using vm.values to access data.
Just be sure you are using right version of angular js ~1.5
(function(angular) {
angular.module('x.y.z', [])
.component('triangularStatus', {
bindings: {
value: '=',
dimensions:'=?'
},
template: '{{vm.value}} <br/> {{vm.dimensions}}' ,
controller: TriangularStatusController,
controllerAs: 'vm'
});
TriangularStatusController.$inject = [];
function TriangularStatusController() {
}
})(window.angular);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.js"></script>
<div ng-app = "x.y.z">
<triangular-status value="24" dimensions="348"></triangular-status>
</div>
The definition of your component, using bindings, is not directly equivalent to the definition of your directive, using scope, even though both are defined to use controllerAs. This is because your component will be binding directly to the controller, and your directive will be binding to $scope (by default).
I've used your code in the snippet below, slightly modified to allow the component and directive(s) to be used together. I've also added an additional directive that makes use of bindToController:true to demonstrate a directive that behaves a little more like a component in binding its attribute values directly to the controller, rather than to $scope.
I've also used a very basic shared template that attempts to show the bound attribute values by looking for them on $scope, followed by looking for them on vm (the ControllerAs).
(function() {
"use strict";
var templateBody = '<h2>$scope</h2>' +
'<p>value: {{value}}</p><p>dimension: {{dimension}}</p>' +
'<h2>vm</h2>' +
'<p>vm.value: {{vm.value}}</p><p>vm.dimension: {{vm.dimension}}</p>';
angular
.module('x.y.z', [])
.component('triangularStatusComponent', {
bindings: {
value: '=',
dimension: '=?'
},
template: '<div><h1>Triangular Status Component</h1>' + templateBody + '</div>',
controller: TriangularStatusController,
controllerAs: 'vm'
})
.directive('triangularStatusDirective', triangularStatusDirective)
.directive('triangularStatusDirectiveBound', triangularStatusDirectiveBound);
function triangularStatusDirective() {
var directive = {
scope: {
value: '=',
dimension: '=?'
},
replace: true,
template: '<div><h1>Triangular Status Directive</h1>' + templateBody + '</div>',
controller: TriangularStatusController,
controllerAs: 'vm',
};
return directive;
}
function triangularStatusDirectiveBound() {
//https://docs.angularjs.org/api/ng/service/$compile#-bindtocontroller-
var directive = {
scope: {
value: '=',
dimension: '=?'
},
bindToController: true,
replace: true,
template: '<div><h1>Triangular Status Directive Bound</h1>' + templateBody + '</div>',
controller: TriangularStatusController,
controllerAs: 'vm',
};
return directive;
}
TriangularStatusController.$inject = [];
function TriangularStatusController() {
var vm = this;
}
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app="x.y.z">
<triangular-status-component value="'componentValue'" dimension="'componentDimension'">
</triangular-status-component>
<hr>
<triangular-status-directive value="'directiveValue'" dimension="'directiveDimension'">
</triangular-status-directive>
<hr>
<triangular-status-directive-bound value="'directiveValueBound'" dimension="'directiveDimensionBound'">
</triangular-status-directive-bound>
</div>
If you're finding that your code works as a directive, where your values are bound to $scope, but not as a component, where your values are bound to the controller, I would assume either your template html (most likely?) or your controller function are relying on trying to access your values as though they were on $scope. To confirm this, you may notice there are errors being logged to your javascript console that will help you zero in.
I think the only problem is, that your missing the brackets:
angular.module('x.y.z')
change to
angular.module('x.y.z', [])
https://docs.angularjs.org/api/ng/function/angular.module
As was mentioned in the comment, I need to clarify, the problem can be how are your JS files ordered or bundled, some other JS file executed later can overwrite this module and therefor you will not see any tag rendered.

Error after Minification of angular js. Error: [$injector:unpr] Unknown provider: eProvider <- e <- makeErrorsDirective

I used Gulp to minify my entire js files. Once minified I got an error like the following:
[$injector:unpr] Unknown provider: eProvider <- e <- makeErrorsDirective.
I had a Custom directive in my controller file.
var myhubdashboardControllers = angular.module('vpdashboardmodule', []);
.directive('mhDashboard', function ($http, authService, apiService) {
return {
restrict: 'EA',
scope: {
name: '#',
dash: '#',
report: '#',
disname: '#',
disdesc: '#',
distot: '#'
},
templateUrl: 'views/dashboard/dashboard-direc.html',
link: function (scope, element, attr) {
scope.linkChk = scope.name;
switch (scope.linkChk) {
case 'Shipped This Week':
scope.url = 'erp/JobShipmentList/PostCpsVwShipmentCount';
scope.shipstatus = "Departure";
scope.period = "ThisWeek";
scope.basicfilter = "Open";
scope.linkName = "Shipments";
scope.linkDesc = "Shipped This Week";
break;
})
};
This is the code used in my application.
There is a reason why you have to inject services and controller in string array.
if you want to inject scope to controller, you have to use
angular.module('yourApp')
.controller('yourController',['$scope',function($scope){
}]);
Minification will change the variable names and if you don't use that array of strings while injecting services or controllers, it will be like
angular.module('yourApp')
.controller('yourController',function(e){
});
So, angular will not be able to understand what 'e' stands for, hence the error.
Always remember that the order is also important.
.directive('mhDashboard', ['$http','authService','apiService', function ($http, authService, apiService) {
return {
restrict: 'EA',
scope: {
name: '#',
dash: '#',
report: '#',
disname: '#',
disdesc: '#',
distot: '#'
},
templateUrl: 'views/dashboard/dashboard-direc.html',
link: function (scope, element, attr) {
scope.linkChk = scope.name;
switch (scope.linkChk) {
case 'Shipped This Week':
scope.url = 'erp/JobShipmentList/PostCpsVwShipmentCount';
scope.shipstatus = "Departure";
scope.period = "ThisWeek";
scope.basicfilter = "Open";
scope.linkName = "Shipments";
scope.linkDesc = "Shipped This Week";
break;
}
}])
Angular doesn't always work well with minification.
If you as an example write this:
angular.controller("MyCtrl", function ($scope) {...});
Then the $scope would be changed to something meaningless during minification.
If one instead changes that to:
angular.controller("MyCtrl", ["$scope", function (s) {...}]);
Then it doesn't matter what the first argument in the function is called (here s), as long as the string is "$scope".
See this: https://docs.angularjs.org/tutorial/step_05#a-note-on-minification in the documentation for more details.
If you want more help, you have to post the code in question, not just the error.
I had this same issue, even when I use gulp-ng-annotate, but it only happens occurs for $stateProvider and ngDialog resolves:
$stateProvider
.state('orders', {
url: '/orders',
templateUrl: 'templates/orders.html',
controller: 'OrdersController as vm',
resolve: {
authenticate: function (Auth) {
return Auth.getAuthResolve();
}
}
});
Resolve needs to be written like this:
resolve: {
authenticate: ['Auth', function (Auth) {
return Auth.getAuthResolve();
}]
}
So it feels that ng-annotate does not inject the array into resolves, but only to controller/service/factory constructors.
I had an issue using angular-ui-router-title. After changing
$titleProvider.documentTitle(function($rootScope) {
return $rootScope.$title + ' my title';
});
to
$titleProvider.documentTitle(['$rootScope', function($rootScope) {
return $rootScope.$title + ' my title';
}]);
the error doesn't appear anymore.

Setting template or templateUrl in Angular Directive based on user input

I have simple directive like this :
app.directive('sample',function(){
return{
restrict:'E',
template:'Hello sample',
templateUrl:''
}
});
i want when user declare templateUrl in tag like this :
<sample template="some url"></sample>
use templateUrl but if nothing set use default template in directive
template and templateUrl can be specified as functions taking two arguments - tElement and tAttrs.
An easy way is to move your default template and perform your logic in the templateUrl function:
app.directive("sample", [
function() {
var defaultTemplate = 'default.html';
return {
restrict: 'E',
templateUrl: function (tElement, tAttrs) {
return tAttrs.template || defaultTemplate;
}
}
}
]);
Demo: http://plnkr.co/edit/rrPicuzzb6YF4Z6yh3Rn?p=preview
I suggest using transclude:
app.directive('sample',function(){
return {
restrict:'E',
transclude: true,
template:'Hello sample <div ng-transclude></div>
};
});
HTML
<sample>
<div ng-include="some url"></div>
</sample>

Categories

Resources