angular.injector - can't find custom (app-related) services - javascript

I've got a angular application. I start it and I open the chrome dev tools console and start typing.
I want to do some $injector.get(...), to play with my services and factories in console. But I'm not in a DI context, so... $injector is the same as angular.injector(), right? So I type angular.injector().get('MyModel') and I get
Uncaught Error: [$injector:unpr] Unknown provider: MyModelProvider <- MyModel
Well... why does angular injector can't find the model that I have declared with:
MyModule.service('MyModel', MyModel);
and I'm sure it works, because when I click out some things in the app, the model gets used and calls the API correctly.
Moreover, if I execute angular.injector().get('$attrs') or angular.injector().get('$scope') or whatever, I get the same errors. So I can see that I can't use injector this way.
What am I doing wrong? Or is there something wrong with my app configuration?
More or less, what I want to do is to retrieve a service or a factory or whatever from angular in the console (when the app is already loaded) to play with those DI-components.

Try :
angular.element(document.body).injector().get('MyModel')
For any DOM element you can do this:
angular.element(domElement).scope() to get the current scope for the element
angular.element(domElement).injector() to get the current app injector
angular.element(domElement).controller() to get a hold of the ng-controller instance.

Related

AngularJS Scope is not accessible through console

I just started learning angular js. I have understanding that we can access and debug scope available to any dom element by selecting/inspecting anywhere on the page and running
angular.element($0).scope()
code on console. But if you try this, I find its value undefined. How they are hiding it and how can I reach to data through console?
Its likley that debugInfoEnabled in $compileProvider is set to false, which means angular.element($0).scope() will always return undefined
You can however run angular.reloadWithDebugInfo in the console which will override this.
Reference:
AngularJS $compileProvider Documentation
AngularJS reloadWithDebugInfo Documentation
Load angular.js instead of angular.min.js. You will get better stack traces and data debugging will be enabled.
From the Docs:
angular.element — jQuery/jqLite Extras
AngularJS also provides the following additional methods and events to both jQuery and jqLite:
scope() - retrieves the scope of the current element or its parent. Requires Debug Data to be enabled.
— AngularJS angular.element API Reference - jQuery/jqLite Extras
For more information, see
AngularJS $compileProvider API Reference
AngularJS angular.reloadWithDebugInfo API Reference

Get access to Angular service instance from JavaScript code

What I'm trying to do is have some testing assertions based on the data in the Angular service, i.e. we're trying to create E2E tests and the tool we're using allows us to execute arbitrary JavaScript code for assertions, so for that I need to know if it's possible to get access to the Angular service instance.
How can I get access to an Angular service instance from plain JS code?
That is, if my Angular app is deployed, and I open the app in the browser, then open Chrome DevTools, can I get access to the service instance of the my Angular service that was provided to all components?
I know it's possible to get access to your component by through ng.probe($0) etc. but not sure about services.
From what I have searched so far, it seems like we have to do use the Injector class and then use it's .get() method to get access to one of the Angular service instances but I'm not sure how would I get access to the Injector class/instance itself?
Here's what I tried: ng.probe($0) ($0 being the <app-root> of my app) and then I see that the return value has an .injector property, I tried to call ng.probe($0).injector.get('MyServiceName') and got an error for: Uncaught Error: No provider for MyServiceName!.
(Even though I'm trying ng.probe above, I would love to know how to get access to the injector without ng.probe because during execution of the automated testing i.e. prod mode, I don't think I'll be able to do ng.probe($0))
So I'm not sure if I'm trying to access it the right way? Any ideas?
I'm using Angular 4.
This works for me in Angular 7 using ng.probe():
window.ng.probe(window.getAllAngularRootElements()[0])
.injector.view.root.ngModule._providers
.find(p => p && p.constructor && p.constructor.name === 'MyServiceName');
And I guess it is not possible to do it another way without ng.probe()

Why doesn't angularJS directly give the specific error location, rather than giving a link to their website link which gives some generic explanation?

Why doesn't angularJS directly throw the specific error location(i.e., in which file there is an error or fault), rather than giving a link their website link which gives some generic explanation? It is making debugging a very difficult task!
Whenever there is an error, i can't debug the app easily because I have to go through the complete application and search every line, if it is valid line or not?
You can use console.log() in the module where you are debugging, might make it easier.
Because AngularJS is not being compiled so it can not know its exact location where actual error occurred.
For example Suppose you are defining a module Say 'XYZ' as follows
angular.module('XYZ', []);
Then you are using this as
var app = angular.module('XYZ');
But if you did mistake and do as follows
var app = angular.module('XYZ', []);
AngularJS will think you want to override your previous module. Then angular can not found dependency for the old component which were defined earlier on 'XYZ' module. So angular will tell those component are not defined.
One more point mostly those error happens on angular digest cycle which is not in our code.
Another Example
$scope.$watch('foo', function() {
$scope.foo = $scope.foo + 1;
});
The above code will be executed infinite time because foo is being watch if it is changed, and insde of watch it is again being changed.
But after 10 iteration angular will stop execution and show a link. Because angular does know it is a digest cycle repetition happening. But do not know which part of the code is responsible for that.
Note: Yes, I found angularJS debugging is really little hard, But If
we see the error carefully and try to find out what latest changes we
did last time, then we can found exact problem.

Angular js deployment on web server issue

I've developed my first spa application in Angular js but I've done it on localhost.
Now it's time to test it online. I'm sure that everything works localy but simply I can't make it work online.
It seems to me like controllers are not being loaded although they are linked well.
Routing works because html templates change but THERE ARE NO CONTROLLERS ???.
Here is sample output from console :
First,for every controller in my app I get this (total 5 times) :
Uncaught SyntaxError: Unexpected token <
And after that I get this for controller that is being used right now:
Error: [ng:areq] http://errors.angularjs.org/1.3.5/ng/areq?p0=homeCtrl&p1=not%20aNaNunction%2C%20got%20undefined
at Error (native)
at https://code.angularjs.org/1.3.5/angular.min.js:6:416
For every single controller I get the same error.
I followed rule to inject dependacys (found that on stackowerflow but it doesn't help at all) so my every controller looks like this:
myApp.controller('nearCtrl',
['$scope', 'geolocation', 'nearApartments', 'uiGmapGoogleMapApi',
function ($scope, geolocation, nearApartments, uiGmapGoogleMapApi) {...}])
Does anyone have an idea what could I do to fix this ?
Ok I found the solution,as usual it was trivial and now I feel like I shot myself in leg.
The thing was that I was very stupid and didn't follow good
practices as NAMING CONVENTION from the BEGINING of the
project !
In my index.html file there was an issue because few controllers were named by lowercase like myController.js and their real name on server was different like MyController.js so there's a problem.
I worked with git,merged branches and stuff and probabbly git messed up something with names(explains how it worked on localhost I guess) but that wouldn't happen if I had followed rules from the start.
To every wannabe Angular.js developer like me there are some great design guides and good practices described on link below.
Use them !
https://github.com/mgechev/angularjs-style-guide
Tnx everyone who tried to help me, Angular has really great community.
The trouble is with your server routing. You're serving your whole app instead of the individual JS files. First thing you should do is make sure 188.226.150.65/app/components/about/aboutController.js serves correctly the JS for aboutController.js.
Looking at each of your component folders, it seems all your controller.js files all have the same error:
Error in exception handler: The stream or file "/var/www/html/zimmer-
production/app/storage/logs/laravel.log" could not be opened: failed to open stream:
Permission denied in /var/www/html/zimmer-production/bootstrap/compiled.php:9016
The only controllers that seem to actually have any Javascript are the signup controllers and the apartmentControler. I'd check the permissions in your production environment, as that seems to be the problem.

Ember-cli creates/initializes app.js twice

I'm moving my project from Ember AppKit to Ember-Cli. I have an myapp/app/app.js, where the app is initialized and in myapp/app/index.html I have the following lines:
var config = require('myapp/config/environment')['default'];
window.App = require('myapp/app')["default"].create(config.APP);
*config is not that important in my question.
So when I run the ember server I see that app.js was called twice. For the first time, automatically, I guess, and the second call is made by create() function from above. So after running the server I get an error:
"Uncaught Error: Assertion Failed: You cannot use the same root element (body) multiple times in an Ember.Application "
I know that the error means that I'm creating two instances of my app in the same DOM-Object and it can be solved by creating two sub containers () with different ids.
But how do I avoid creating the first instance, which is done automatically, before I actually call create()? Without the lines shown above the app is not shown at all, but with them I get the mentioned error. I have checked the whole app implementation, there is nothing what would call the initial instance creation, before create() function from above.
I didn't have that mistake in EmberAppKit running Grunt
In Ember CLI config lives in /config/environment.js, and it will be handed to your app automatically. You shouldn't need to this manually.
Setting window.App=this in app.js has solved the problem.
If you look into my-app.js in assets, you will see that an instance is created at the end of the script. So it only has to be assigned to window.App

Categories