$routeParams generating Unknown Provider - javascript

This is my code inside a Mean.IO package. The controller takes in a number from the URL and then passes it to a factory.
This bit of code is giving me and Unkown Provider error for $routeParams.
angular.module('mean.rotor-tablet').controller('taskListController',
function($scope,$location,$routeParams,dataFactory){
console.log("SAD");
$scope.partid=$routeParams.id;
$scope.part=dataFactory.getPart($scope.partid)
$scope.tasklist=dataFactory.getTaskList($scope.partid)
$scope.goToTask=function (task_index){
$location.path('task/'+$scope.partid+'/'+task_index);
}
})
The exact same code was working fine on an AngularJS application I was running on the LAMP stack. When I added this to Mean IO however I got this error. (in case it's important I created a new package and this is in a file called controllers.js in the controllers folder)
PS I'm a n00b to Mean.IO. The reason I chose to mention Mean.IO specifically is because the problem seems endemic to it and not to AngularJS in general

Related

grunt an angular project then it errors as Cannot find Module

Hi I have a problem :) I developed an angular project and it works fine in my localhost apache. I'm using angular 1.4.3 for frontend things and node.js for backend things. Now I need to use Grunt to version it.
I did many config (such as that maple thing disabled.it changes all variables names such as a,b,c from indexCounter,PersonCounter,AgencyCounter and it causes some problems.) But I get an error everytime I try to run. It is like [module] cannot found. My project works on my local machine If I dont grunt it but after the grunt I take 3 files as vendor.js vendor2.js and app.js. In vendor.js I have native angular js files. In vendor2.js I have plugins. and lastly In app.js I have controllers. I'm added them in my index HTML in this order;
vendor.js
vendor2.js
app.js
Do you have any idea about that?
Problem: In angular you cannot minify your code without using either .$inject or array syntax.
Solution
For each controller, directive, service etc. that you add to your module, you will have to add en extra array of strings specifying the dependencies that should be injected into you service, controller etc.
Example
Using $inject property
function mainController(indexCounter,PersonCounter,AgencyCounter) {
//Controller implementation
}
mainController.$inject=['indexCounter','PersonCounter','AgencyCounter'];
angular
.module('mymodule')
.controller('mainController', mainController);
Using array
var mainController;
function controller(indexCounter,PersonCounter,AgencyCounter) {
//Controller implementation
}
mainController=['indexCounter','PersonCounter','AgencyCounter', controller];
angular
.module('mymodule')
.controller('mainController', mainController);
When you don't specify the dependecies in an array, angular will try to find an registered dependency based on its' parameter name. e.g. function mainController(indexCounter) {}, then angular will try to find a registered dependency called indexCounter. It works perfectly fine when the code is not minified. However, when minified the indexCounter parameter name will be changed to a shorter name, e.g. a. And when trying to find dependency a which is not registered in your app. It's gonna fail to instaciate your angular module.

Unit testing an AngularJS app that uses $translatePartialLoaderProvider

I am designing the unit tests for an AngularJS web app, using Karma-Jasmine.
The web app uses angular-translate and, specifically, employs the $translatePartialLoaderProvider module. The app itself works well; however, the unit tests fail with the following error:
Error: [$injector:modulerr] Failed to instantiate module myApp.view1 due to:
[$injector:unpr] Unknown provider: $translatePartialLoaderProvider
I have followed the unit-testing instructions for angular-translate available at http://angular-translate.github.io/docs/#/guide/22_unit-testing-with-angular-translate, as mentioned in Question #18876290, yet the unit tests still fail with the above-mentioned error.
A code sample illustrating the error is available here (Plunker):
http://embed.plnkr.co/8X7diP/. Note that the app works well: you can switch views and the view text is translated as expected. As soon as you remove $translatePartialLoaderProvider in view1mod.js, the app passes the test.
Your help would be greatly appreciated!
Its because, even though your app.js has the translate dependency, your view1 or view2 modules don't, i.e. this will fix the spec -
angular.module('myApp.view1', ['ngRoute', 'pascalprecht.translate'])
You'll have to fix this in both view1mod.js and view2mod.js.

AngularJS Backendless Development 'Unexpected request' of templates issue

I'm working on a project that needs the backend to be mocked while the frontend implementation is being made.
I have a gulp structure that loads /**/*.mock.js files only for tests and while serving the source for development. I use this .mock.js files to mock test data and services and to intercept http calls for backendless development. The file looks like this:
(function() {
'use strict';
var mockResponseData = {
'mock': 'data'
};
angular
.module('module.name')
.value('mockResponseData', mockResponseData)
.config(config)
.run(run);
/** #ngInject */
function config($provide) {
$provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
}
/** #ngInject */
function run($httpBackend) {
$httpBackend.whenPOST(/\/api\/path\/$/)
.respond(function() {
return [200, mockResponseData];
});
$httpBackend.whenGET(/^\w+.*/).passThrough();
$httpBackend.whenPOST(/^\w+.*/).passThrough();
$httpBackend.whenPUT(/^\w+.*/).passThrough();
$httpBackend.whenDELETE(/^\w+.*/).passThrough();
}
})();
As you can see, I already have the .passThrough() applied (which is the common solution for the Unexpected request issue) and it works just fine when just one .mock.js file like this exists. After creating the second file, the Unexpected request errors start to appear:
Error: Unexpected request: GET 'path/to/template.html'
After trying some things, I realized that the problem could be with the way I'm injecting $httpBackend. To avoid it from being injected in the dist files and to keep the project structure modular, I have to inject it via $provide instead of directly in the module's definition, in each module that needs it. Which is done in the config block of the code above.
If the $provide.decorator(...) line is removed from all but one .mock.js files, everything works fine again (except that the run block from the files with the line removed would start to complain about the non-existent $httpBackend, but this is not the issue here).
So, any idea of what this could be?
Thanks in advance!
P.S.: I can't miss the modularity structure and the .mock.js files cannot be included in the dist build.
So, I've solved this a while ago and now I'm answering here for future reference.
The basic problem is that I was injecting the $httpBackend service using the $provide.decorator() method, which according to the documentation, works like this:
Register a service decorator with the $injector. A service decorator intercepts the creation of a service, allowing it to override or modify the behavior of the service. The object returned by the decorator may be the original service, or a new service object which replaces or wraps and delegates to the original service.
Injecting the service like this was necessary to avoid injecting it when it wouldn't be used, but somehow, if you decorate this same service twice, AngularJS get confused and starts to throw the errors described in the question.
So, the solution is to create a .mock.js file for the main module. This way it will inject the service only once and avoid the problem:
(function() {
'use strict';
angular
.module('mainModuleName')
.config(config);
/** #ngInject */
function config($provide) {
$provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
}
})();
Please note that you can still add more decorators to the service as follows:
$provide.decorator('$httpBackend', function($delegate, $injector) {
// Your decorator...
});
As long as you don't inject angular.mock.e2e.$httpBackendDecorator more than once.

How to minify famous.angular without DI errors?

I'm running into some issues with famous-angular when minified.
A couple of the PRs I submitted yesterday were attempts to fix this, but these don't appear to have resolved the issue.
When built without minfication, everything works as expected.
When built with minification, but removing the dependency on 'famous.angular' from my app module,
the app degrades gracefully to angular only, so the layout is borked, but the underlying angular app works as expected, no errors.
When built with minification, and the app module depends on 'famous.angular',
the app does not load at all, with the following error:
Uncaught Error: [$injector:modulerr] Failed to instantiate module app due to:
Error: [$injector:modulerr] Failed to instantiate module famous.angular due to:
Error: [$injector:unpr] Unknown provider: t
http://errors.angularjs.org/1.2.23/$injector/u...<omitted>...2)
By employing this method,
I was able to determine which function was not getting minified correctly,
and tripping up Angular'S dependency injection:
function LocationHashbangInHtml5Url(appBase, hashPrefix) { /* ... */ }
This is in the core angular file - angular.js,
and it does indeed minify correctly in other instances.
So I am not sure why when I include 'famous.angular' in my app module,
this introduces the error.
Anyone know whaty is amiss here?
Demo of problem:
git clone git#github.com:bguiz/browserify-gulp-starter.git
cd browserify-gulp-starter
npm install famous
bower install --save angular angular-route famous-angular
# edit gulpoptions.js
# appName: 'app',
# appFolder: './src-famousangular/app/',
gulp serve-dist
I submitted these two PR's to famous-angular previously, thinking that I had caught all of the $inject scenarios:
https://github.com/Famous/famous-angular/pull/191
https://github.com/Famous/famous-angular/pull/190
Turns out that there was a third one that I had missed, and have now submitted a patch for:
https://github.com/Famous/famous-angular/pull/195
In my question above, I said function LocationHashbangInHtml5Url(appBase, hashPrefix) { /* ... */ } in angular/angular.js was the function that was not minifying correctly.
This was incorrect, and the culprit was in fact a provider in famous-angular/src/scripts/directives/fa-input.js.
For the curious, here is the process that I used to figure the above out.
As an added bonus, I happen to have discovered an additional technique to use when debugging dependency injection errors in minified AngularJs apps.
It turns out that the technique that I linked to above ( https://stackoverflow.com/a/25126490/194982 ) does not always work correctly.
What did work in the end, was to traverse up the execution stack, until we get to the invoke() function, as described in that technique. Then, instead of inspecting only fn, look in the Scope Variables tab in the the developer tools, and inspect every scope member which is a function.
This casts a wider net, and results in more things which need to be inspected;
but was necessary in this case, and I suspect might apply in others.

Imitate backend API with AngularJS

I am building a GUI for an app whose API is still being worked on. I have an idea of how it will look but it's not functional yet. I have to mimic its behaviour until it's ready.
I'm trying to do this with $httpBackend. I set up my installation with Yeoman.
Attempt to Install
I'm running Angular v1.2.6.
The documentation gives me three ways of installing it:
Google CDN at //ajax.googleapis.com/ajax/libs/angularjs/X.Y.Z/angular-mocke2e.js
Bower via bower install angular-mocke2e#X.Y.Z
code.angularjs.org: //code.angularjs.org/X.Y.Z/angular-mocke2e.js
Where X.Y.Z is my version number.
Thing is none of those work. Google gives 404, and won't let me travel up the directories. Bower says no package available, and a 404 for code.angularjs.org. So I browsed code.angularjs.org and found that for 1.2.6, there is no anguler-mock
Anyway I did find a file at https://code.angularjs.org/1.2.6/angular-mocks.js which seems to have $httpBackendProvider defined in it.
When I went back to my Yeoman install - it looks like I already had angular-mocks.js installed.
So, question 1: Is this what I'm looking for to use $httpBackend?
Attempt to Use
So I try to start using it in my project:
// Gotta manually run the app to check cookies
app.run(['$cookies', '$location', '$rootScope', '$httpBackend', function($cookies, $location, $rootScope, $httpBackend){
// Some stuff....
console.log($httpBackend);
}]);
And now my app won't start. I get the following error:
But the app does show me the contents of $httpBackend. I thought that maybe I should put it into a different module, but I don't know.
So question 2: Is it normal that my app won't load once I throw $httpBackend into the app.run() call?
And question 3: Should I be putting my $httpBackend stuff into a different module while I'm testing?
And I guess lastly is Is this even the best way for me to test the API?
You can use $httpBackend to mock your services like so:
$httpBackend.whenGET(/\/api\/foo\/bar/).respond({some:'thing'});
Your app isn't loading because it wasn't expecting a request for your partials. You can avoid that by doing something like this:
$httpBackend.whenGET(/^views\/.*/).passThrough();
It would be good to break these out into individual modules so you can exclude them before deployment.
As far as it being the best solution, it depends on your needs. I would propose integrating some build tools (Grunt, Express, Protractor, etc.) that include a local node server for testing locally. Then you could just use actual services for testing, as proposed by #Ronald91.
Going through a similar situation like this on a project I am working on. Never utilized httpbackend for this but we mocked out the backend services with a MongoDB instance and in our app.js file we set up the routing as followed:
app.get( '/ui/orders/:orderId/details', function( req, res ){
mongoclient.connect( mongoUrl, function(err, db){
if( err ) throw err;
var collection = db.collection('order-details');
console.log( req.query);
collection.findOne( { orderId : req.params.orderId}, function(err, docs){
if( err ) throw err;
console.log( "Docs...");
console.log( docs );
db.close();
res.send( docs );
} );
});
});
The service call we use to utilize this routing is
ourApp.factory('orderDetails', function($resource, $routeParams) {
return function(){
return $resource('/ui/orders/:orderId/:subSystem', {orderId: $routeParams.orderId});
};
});
This is a potential answer to the "Attempt To Install" query.
Yes, angular-mocks.js is what you want. The file contains multiple modules useful for mocking. You don't have to use all of them.
For the specific case you mentioned (and the issue I'm trying to solve too, which brought me here):
include the file you found
add the following dependency to your main app module, you should be able to mock back-end requests.
var yourApp = angular.module('app', ['ngMockE2E']);
You can use the mocks module in unit tests and in application development.

Categories