AngularJS code not minifying proper despite using array syntax in controllers - javascript

It's a well known issue in angular to need to use the special array syntax when bringing in dependencies into controllers to avoid minification problems, so I have been using that notation. But it seems that the injector is still having issues with this code that appear only after sending it through gulp-uglify.
Do other angular elements like directives also need to have this syntax be used? Also, I'm using object notation to define one of the controllers, so might that be the problem?
Some main config stuff.
var app = angular.module('musicApp', ['ngSanitize']);
//Whitelist Soundcloud
app.config(function($sceDelegateProvider) {
$sceDelegateProvider.resourceUrlWhitelist([
'self',
'https://w.soundcloud.com/**'
]);
});
Directives, one with a controller in it.
app.directive('soundcloudHtml', ['$sce', function($sce){
return {
restrict: 'A',
link: function(scope, element, attrs) {
scope.musicPiece.soundcloud = $sce.trustAsHtml(scope.musicPiece.soundcloud);
}
}
}]);
app.directive('music', function(){
return {
restrict: 'E',
scope:{
type: '='
},
templateUrl: '/resources/data/music/music.html?po=343we',
link: function(scope, element, attrs) {
},
controller: ['$http', '$scope', function($http, $scope){
this.musicList = [];
$scope.Utils = Utils;
var ctrl = this;
$http.get('/resources/data/music/music.json').success(function(data){
ctrl.musicList = data;
Utils.updateTableOfContents();
});
}],
controllerAs: 'musicCtrl'
};
});

Looks like I missed that config also needs that pattern as well in order to be minified.
The config should be
//Whitelist Soundcloud
app.config(['$sceDelegateProvider', function($sceDelegateProvider) {
$sceDelegateProvider.resourceUrlWhitelist([
'self',
'https://w.soundcloud.com/**'
]);
}]);
And not
//Whitelist Soundcloud
app.config(function($sceDelegateProvider) {
$sceDelegateProvider.resourceUrlWhitelist([
'self',
'https://w.soundcloud.com/**'
]);
});

Related

How do inject services to Link function contained directive?

I am trying to inject services to the below directive which is used link function instead of controller.
(function() {
angular
.module("myApp")
.directive('myDirective',['$scope','myService','myData',function($scope,myService,myData) {
return {
restrict'AE',
replace:'true',
templateUrl :'/myApp/directive/my-directive',
scope: {
userId: "#"
}
},
link:function(scope,elem,attr)
{
//Code for link function goes here ...
scope.myUsersArray [];
scope.getUserDetails = function()
{
//code for getUserdetails goes here...
}
}
}]);
})();
When i run this code, i am getting exception like [$injector:unpr] Unkown Provider <_ $scope error. If i remove the injected services, i am not getting any error. Error throws at angular.js file so i don't have any clue to fix it :(
You have several syntax issues. Your code should look like this:
.directive('myDirective', ['$scope', 'myService', 'myData', function($scope, myService, myData) {
return {
restrict: 'AE',
replace: 'true',
templateUrl: '/myApp/directive/my-directive',
scope: {
userId: "#"
},
link: function(scope, elem, attr) {
//Code for link function goes here ...
scope.myUsersArray = [];
scope.getUserDetails = function() {
//code for getUserdetails goes here...
};
}
};
}]);
You may have more problems as its not evident as to why you are injecting $scope, myService, and myData

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.

nodeJs + angularJs = not working .directive

help please.
I have simple project https://github.com/A1x1On/nodeJs-AngularJs
I don't understand why angularJs directive doesn't work while angularJs controller works.
These constructions include same and them paths are same, but .directive is broken
Help please.
it's just file with directive, but you better take look at project on git:
(function (angular) {
'use strict';
function contaction() {
var directive = {
restrict: 'E',
templateUrl: '/js/app/contact/templates/contact.template.html',
scope: true,
replace: true,
controller: [
'$scope',
function ($scope) {
$scope.eww = "ddsf";
}
]
};
return directive;
}
contaction.$inject = ['contact.factory'];
angular.module('contact').directive('contdirective', contaction);
})(angular);

Data is not being transferred from one custom directive to another if we use $http to fetch data

I have two different custom directive and wanted to pass data from one directive to another. The data is coming from server call. Problem is http being a asyn call doesn't return data upfront and controller of another widget doesnt receive it and it renders it's html without having it. here is the complete code (I have removed some code that might not make sense in the problem)-
The service which hits server is -
angular.module('myModule')
.service('MyService', [
'$http',
function($http) {
this.getData = (someId) => {
var url = someUrl + '/' + someId;
return $http.get(url);
};
}
]);
and the first directive that calls service and set "anotherData" in the scope to be transferred to another directive is -
angular.module('myModule')
.directive('myDirective', ['MyService',
function(MyService) {
return {
restrict: 'E',
scope: {
data: '='
},
templateUrl: 'my-template.html',
controller: ['$scope', function($scope) {
MyService.getData ($scope.data.id).then((response) => {
$scope.anotherData = response.data;
});
}]
}
}]);
and my-template.html from which i am calling another directive is (notice anotherData is passed here -
<other-directive mode="display" data="data" anotherData="anotherData" ></other-directive>
The other directive that should receive "anotherData" but giving me no result is -
angular.module('otherModule')
.directive('otherDirective', [function() {
return {
restrict: 'E',
scope: {
id: '#',
data: '=',
mode: '#',
anotherData: '#'
},
templateUrl: 'other-template.html',
controller: ['$scope', '$element', function ($scope, $element) {
console.log("other data in widget after server call:");
///THIS IS UNDEFINED.
console.log($scope.anotherData);
}],
link: function ($scope, $element) {
}
}
}]);
and other-template.html has iframe to display youtube widget -
<iframe width="{{anotherData.videoWidth}}"
height="{{anotherData.videoHeight}}"
src="{{anotherData.videoURL}}" frameborder="0" allowfullscreen></iframe>
You should use dashes instead of camel case, like this:
<other-directive mode="display" data="data" another-data="anotherData" ></other-directive>
Also, you are binding for text instead of two-way binding an object, so change the definition in your directive to this:
anotherData: '='
This should do the trick
<other-directive another-data=anotherData></other-directive>
You need to be caarefull with the camel case in html!

Injecting services into AngularJS directive controller directly

I understand how Angular dependency injection works with directives but wanted clarification on something. I have a dummy test directive as follows:
app.directive("test", [
function() {
return {
restrict: "E",
scope: {},
controller: ["$scope", "$filter",
function($scope, $filter) {
var food = ["Apple pie", "Apple cobler", "Banana Split", "Cherry Pie", "Applesauce"];
$scope.favorites = $filter('filter')(food, "Apple");
}
],
template: "<div>{{favorites}}</div>"
}
}
]);
This works fine and will filter the food array as expected. However I noticed if I inject the $filter service in the directive as follows, it still works:
app.directive("test", ["$filter",
function($filter) {
return {
restrict: "E",
scope: {},
controller: ["$scope",function($scope) {...
My question: Is it better practice to inject services into a directive in the declaration line like so:
app.directive("test", ["$filter", function($filter) {
or in the controller line like this:
controller: ["$scope", "$filter", function($scope, $filter) {?
Is there no difference? Here is a Plunker of the directive code.
In this case, you're receiving the same service, so it likely doesn't matter too much. I personally prefer to keep them as localized as possible; if you don't need $filter in the link function or something like that, I'd just inject it into the controller.
In certain cases, this may also make it easier to mock dependencies during testing.
You can do this also. Much better way by splitting directive and its controller in a single file. Or you can write in separate files. But, better understand
app.directive('throbberDirective',
[
function(){
return {
restrict: "EA",
templateUrl: "common/utils/throbbers/throbber.html",
controller: throbberController
}
}
]);
app.controller('throbberController', throbberController);
throbberController.$inject = ['$scope', '_$ajax'];
function throbberController($scope){
$scope.throbber = _$ajax.getThrobberConfigs();
$scope.throbber.templateName = $scope.throbber.templateName;
}

Categories

Resources