What is the best way to debug angular code? - angularjs

I'm a newbie in the Angular space. I've been having trouble debugging my code. Any methods proven more effective in debugging Angular?

open the developer console in the chrome browser, this allows you to:
set breakpoints and see whats going on in your code
use the console in the developer tools while you are waiting in breakpoints to execute some code or check the contents of variables
use the "select element" tool to select any HTML element, then in the console type "$scope" to see what's on the $scope of this element.
general tipps:
use some console.log statment like "running ControllerXYZ now" so you see, when your controllers are executed or when you are transitioning between states.
When using ui-router I find it extremly important to add a console.log statement into $stateChangeStart, $stateChangeSuccess and $stateChangeError event handlers, that shows you when you transition between states or when errors happen on state transitions, without that I am blind...
adding some {{anImportantVariable | json}} into html often is enough to debug stuff.
and the most important: if everything looks ok, and it still does not work, the problem is in 99%:
either a scoping issue (see here: Why do I need $parent to enable the function in ng-click when using ion-scroll?)
or a spelling mistake and a directive is not found (often because of the CamelCase in JS to dash-case in HTML: e.g. ngShow directive in JS is ng-show in HTML, and isOpenattribute in JS is is-open in HTML)

When it comes to inspecting the state: even though I always (irony) write unit tests for each and every conditional in my code (so I normally don't need to debug stuff) this is so far my favourite technique:
<pre ng-show='mymodel.debugPlz'>{{ mymodel.something | json }}</pre>
Simple example : fiddle

Chrome DevTools usually get the job done pretty well. You can insert a debugger; statement anywhere in the code and if Chrome DevTools are open, the code will stop there and you can further add breakpoint and traverse lines one by one. Other than that, there are a few extensions you can use by just searching for Angular in the Chrome Webstore. These usually help with inspecting $scope

what about using AngularJS Batarang chrome extention
it gives you a nice overview of the current scope within the selected element
as you see in the screenshot there is a new scope tab

Related

binding an expression into ng-src directive

i am trying to load google map api link inside ng-src directive using this method..
<script ng-src="{{trustSrc(vCustom.googleMapApi.src)}}"></script>
in my controller i have..
v.googleMapApi = { src: "https://maps.googleapis.com/maps/api/js?key=" + config.googleApiKey + "&libraries=places" };
$scope.trustSrc = function (src) {
return $sce.trustAsResourceUrl(src);
}
sometimes it works and some times it doesn't..
The Error
ReferenceError: google is not defined...
i have tried different ways to bind it inside ng-src directive but no success..
it works when i add this script <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"></script> but it doesn't work dynamically.. any help ??
there is no syntax error and my controller is ng-controller="Custom as vCustom"
any suggestions to bind it in ng-src directive ?
I think you are trying to lazy load the script. Pls have a look at below post it may help. How to asyncronously load a google map in AngularJS?
Let me try to explain the scenario as best as I can :)
The <script> tags are evaluated only once in a web application. Unlike img tags which can have src attribute assigned to different values throughout the app and so are re-evaluated. So what's happening is that sometimes when the compiler gets to your script tag, the model (vCustom.googleMapApi.src) is resolved so it works fine but sometimes it doesn't because the $digest loop (events loop) in angular hasn't finished resolving the model and so the API key isn't passed correctly to script tag which results in not loading the google maps API and then where you're using the map, it throws the error. In that case, to verify, check the script tag on chrome debugger, it won't have the correct API key resolved and the api script won't have been loaded.
Now the question is that what's the solution. You can either implement a directive that initially resolves the APIKey model and then appends the script tag into your HTML, or use the hard coded value as you use it right now (i have usually seen it hardcoded in most of the code and examples i've seen).
NOTE: even if you implement such directive, you have to make sure that you are using the google maps api AFTER your directive has executed and you've got the maps api loaded.
Hope this helps.

Making a directive load before ngController

I am trying to get experience with angular by making an app (for my own use) and I ran into an issue.
I decided to try to implement lazy loading (like in the "Complex" part of the answer to this question ) and had that working with my own additions to it.
I wanted to make components more self-contained though and decided to try to make a directive to load any javascript dependencies for me.
This left me with the following template html
<div dependencies="app/components/home/controller.js" ng-controller="HomeCtrl as home">
This is the home page.<br />
{{home.test}}
</div>
When I try to load this page I see the following error
Argument 'HomeCtrl' is not a function, got undefined
If I remove the ng-controller directive then my directive works fine and controller.js is loaded.
Based on the source for ngController I thought that setting the priority for my directive higher than 500 would work but it didnt seem to help.
I also tried moving my directives contents from link to compile.pre. It didnt help either, my directives compile runs before the error but compile.pre does not.
Is there any way to make my directive load/run first, before ngController?

mmenu is not initializated under angularjs

I am developing a mobile application with left and right drawer, using mmenu (http://mmenu.frebsite.nl/) it is working fine till I've decided to populate items of the right menu on the fly. My app is based on angularjs and all directives of angularjs in body are working fine except all directives inside <nav id="menu-right">somehow, angularjs directives inside the menu definitions are not executed. I am not sure if it is something related with the order of executing javascript. Any help will be really appreciated. Thank you !!
UPDATED (07-April)
An example in jsfiddle http://jsfiddle.net/jmhostalet/wcK8L/
"My controller says" is working in the body but not in the mmenu, in body prints "Hello" but in mmenu prints nothing
The problems you were running into were:
First off the was not included in the declaration
You are changing the DOM without angular knowing about it therefor it does not have a chance to compile the braces {{myCtrlVar}}
It seems like extra work to create a directive but in the long run will allow you to reuse your code more. Also if you are like me and have bad javascript habits; it is nicer to use a framework to keep things straight.
My solution the in the plunker below shows "one way" to do what you are asking. It would be interesting to port the entire MMenu code over to an angular module in order to have more parameters and control.
(Never heard of MMenu, but seems like a cool project -- I will look more into it).
Plunker
(sorry I am inept at using fiddler)
Your fiddle doesn't have controller initialization on #menu-right but on his sibling element and therefore {{myCtrlVar}} expression can't access controllers scope objects.

browser.executeScript doesn't see $scope

i am making a test with protractor for my angularjs app
and i came accross the following problem
what i want to do is :
browser.executeScript('$scope.$apply')
i want to do this so that my screen updates/renders so i can get the values on screen
only when i do this it says : $scope is not defined
if have also tried multiple javascript render ways who also failed ,but i am not sure if i have used the right methods for that...
does anybody has the same problem or know how to fix this?
Perhaps you should be using an ng-view directive in your container markup to render html snippets or partials within your index page. Take a look at what ng-view can do (http://docs.angularjs.org/api/ngRoute.directive:ngView) :-)

AngularJS Directive is not linking when using an input in the template to replace an input in the html with the type attribute specified

I'm having a really specific, strange issue.
We have to code our app to support IE8. We are wrapping the Angular-Bootstrap's Typeahead directive in a template to encapsulate a lookup widget with some extra functionality.
The issue we're having is that our directive template looks like this:
'<input ng-model="typeaheadValue" typeahead="xxx.code as formatXxx(xxx) for xxx in searchXxxs($viewValue)">'
Inside the link function in the directive we are simply calling replace: true and passing in some values to the scope.
This works beautifully in both IE8 and Chrome.
Now, the REALLY strange part is that, for IE8 only, if we say in the HTML in which we're using the directive:
<input type="text" search-directive>
It will not ever get into the link function. If i take the type="text" off everything works perfectly.
I created a simple JSFiddle to mimic what we're doing with a really basic test. Unfortunately for me the JSFiddle doesn't work in IE8 - but this is basically what we're doing. This can be found here: http://jsfiddle.net/lungsponge121/8xGuF/ (this is my first fiddle, not sure if it's editable or not)
After fighting with it for hours I've found the following: if i keep the html as (input type="text") and i replace the directive template input element with label or textarea it works fine, but when i use input it does not work at all. I also removed all of the typeahead code from the template and found that in IE8 it still doesn't work. The IE8 console did nothing for me and just gave me the standard illegal operation.undefined error.
I had somebody I work with help me debug my code and right now we're wondering if this is a bug. Has anybody else run into this - I'm thinking of submitting this to the Angular people as I can't find out how to get around this.
One thing jumped out at me: your directive is doing replace. The markup of the template you are replacing it with does not have the type="text", whereas the original markup does. I have noticed that replace does a sort of merge, and it may be getting confused when trying to merge or replace some HTML that has an attribute with a template that does not.
Interestingly, you don't really need to replace the original markup with a template at all. That is one use of directives, but not the most powerful in my opinion. Take "replace" off and remove the template entirely, if you're just trying to extend the typeahead anyway. In my own projects, for example, I might put several different directives attributes on a single element and they all add their own flavor of extra functionality to the existing element. All of them have a reference to the same $element, you just have to be careful that they don't conflict.
I wrote the rest of this before I looked at the fiddle first, sorry.
I'm on a chromebook so I can't test the IE8 thing, but if I recall IE is very picky about HTML attributes. Have you tried any of the following:
Alternate directive specification, as in data-search-directive
Make sure the directive has a property, as in search-directive="", even if you don't use it
Is the template cache really necessary? Have you tried this just by putting the template in a template property of the directive?
Is IE8 happy without "use strict"?
Have you seen the angular ui bootstrap alternative typeahead? At the very least, looking at what they did may give you ideas of how to do what you are trying to do.

Resources