All,
We are developing our app with AngularJS and time and again we keep running into the issue of Angular running or loading controllers twice. This becomes a little more intrusive when testing our controllers and more specifically when working with Testacular with jasmine's SpyOn's (since they get triggered before our code runs). So, our question is, is there such a thing as a constructor or init method that Angular is guaranteed to call when instantiating the controllers w/o having to hack work-arounds in the test code? TIA.
If you are specifying the controller in your router, then your template doesn't need to specify the controller via an ng-controller tag. Doing so will double load your controller.
Your controllers shouldn't be loaded twice, unless you are doing something wrong. You shouldn't have to hack any work-arounds.
You might want to provide a concrete example of how you are loading the controllers (and/or the partials which are associated with the controllers). It sounds like you probably have a routing issue which is causing your view to be loaded twice for each request.
Assuming that is a routing-related issue, unless/until you can provide more information to help people to help you, you may want to read this document. Pay particular mention to sections that mention 'redirect' and 'HTML 5' mode:
http://docs.angularjs.org/guide/dev_guide.services.$location
With so little information to go on, I can't answer your question, but perhaps that link will help you to help yourself. :)
Related
So, a little background on this, I have an AngularJS/Ionic project that I'm attempting to do some improvement on, I'm placing all my HTML/JS/CSS into a database table, which in turn will be retrieved on a GET upon app start. HTML is then saved in a factory(also local storage). The goal, is to have an app that can be controlled from the HTML/JS/CSS that is within the Database table, so that we don't need to redeploy new versions for simple updates/fixes. Here's what I have tried:
The most successful method I used was using the below within the controller:
$scope.pageContent = $sce.trustAsHtml(htmlString)
and calling it within the HTML like below:
<div ng-bind-html="pagecontent"></div>
The only problem is, that it isn't compiling correct in a few ways - All my $scope values within the HTML aren't being linked to the parent controller scope.
My questions is: Is there a better way of handling this? I've seen a few people claiming using directives would be the way to go, but can't get a definitive answer on how to implement. Or, is how I'm moving forward working, and I'm just missing some key components... Any help on best way to implement would be greatly appreciated. Let me know if I left any information out, thanks!
Use case:
I'm writing system tests using Geb/Selenium (so outside of angular).
I want to decorate $http to log all requests/responses at run time.
and here's the catch: without touching the source code.
Before you rush to answer "use $provide#decorator", for example,
http://blog.xebia.com/2014/08/08/extending-angularjs-services-with-the-decorate-method/
That solution for this use case means adding a test hook into production code... that's normally a bad thing I want to avoid if possible.
Update: Geb allows you to run Javascript in the browser window. So just for the heck of it I ran the tutorial code to decorate $http. Unfortunately, it didn't work because apparently you can't re-config the app after it's been loaded. But even if it did work, this brings up another interesting point---I need to override $http before any modules have had a chance to use it.
Since decorating $http service would be the cleanest way of doing this, you can avoid polluting production code by using something like ng-constants and gulp/grunt to only add decoration code for a 'test' environment.
See related Q/A here: How do I configure different environments in Angular.js?
If you are inclined on changing this at runtime(where runtime takes place in a test environment), you may need to go 'closer to the metal' and deal with XMLHttpRequests: Add a "hook" to all AJAX requests on a page
I'm new to AngularJS. I'm currently looking at the services. Some of these services look like the replace functions already available in JavaScript. For instance, the $timeout service. Why does AngularJS have these services? Is there a technical reason? Are there any advantages to this approach? I just don't understand the need for using these services.
Thank you for any help.
A service is a function or an object, with a set of methods, that could be used by several components (controllers, directives, filters, other services) of your application.
The main advantage that "wrapping" services like $timeout or $window have over their global functions equivalent is that they're injected by Angular, and can thus be mocked in unit tests, i.e. replaced by fake implementations.
Read the chapter about dependency injection in the angular documentation. Regarding the $timeout service in particular, its documentation explains what it does in addition to the native setTimeout() function.
Angular uses dirty check -- it keeps track of all variables that should be updated automatically and in case of any changes iterates through them as many times as needed (as there can be interdependence between observing variables). (To be precise if there are too many iterations something wrong is probably with your code and exception is raised).
The main reason behind $timeout is to signal to Angular engine that you will be making some changes to the observing variables in the callback. In case you would call normal timeout there is a way to inform Angular about those changes by calling e.g. $scope.$apply(function() {...}).
The other big reason, as #JB Nizet stated is that mocking is much easier.
Service is a way to store persistent information over your application.
unlike the $scope, which is an new child of $rootScope per each route\controller.
The purpose of the Angular-specific implementation of already existent functions, is to make your life and work easier, by automatically telling angular to register your changes, and apply them to the current scope at the next $digest iteration.
I'll be happy to address any other questions.
Good luck with Angular! :)
I will now create an example plunk to emphasize the idea to you
UPDATE:
This is the plunker:
http://plnkr.co/edit/mVmhZpEdsZDQ0MUQpFJ7?p=preview
I used ng-change and the native change
keyup event to explain the point.
while using the angular built in ng-change directive requires no additional effort nor code, using the native events requires wrapping everything in the scope.$apply function/
calling scope.$digest manually.
(run the code and see for yourself)
Check out this older answer which covers Services, Providers and Factories.
AngularJS: Service vs provider vs factory
I saw a similar question on the Google groups and also here on Stackoverflow. Both times the question was not answered. The code in this file doesn't make it very clear about what exactly it does and how it is used. Also it's not clear from the Angular documentation.
Can someone explain how this is used. Also can this be used along with Require.js?
Angular loader allows your angular scripts to be loaded in any order.
As angular-seed project shows us, Angular loader does not have any specific api, you just put it at the top of your index file (so that it's executed first) and then proceed to load your application files anyway you prefer.
But, the most important thing for your use case is that you don't really need angular loader at all. RequireJS also allows your files to be loaded in any order, but it also provides you with many other features that angular loader just isn't made for.
So, yes, you may use it with RequireJS, but you don't need to, because it becomes redundant.
Angular modules solve the problem of removing global state from the application and provide a way of configuring the injector. As opposed to AMD or require.js modules, Angular modules don't try to solve the problem of script load ordering or lazy script fetching. These goals are orthogonal and both module systems can live side by side and fulfil their goals.
http://docs.angularjs.org/tutorial/step_07#anoteaboutdiinjectorandproviders
It allows for you asynchronously load files when bootstrapping your angular application. A good example is the angular-seed project that has an index-async.html file that does this.
index-async.html
This is useful for using other libraries that load in modules asynchronously.
See angular-async-loader:
https://github.com/subchen/angular-async-loader/
To async load following components:
List item
controller
services
filter
directive
value
constant
provider
decorator
So, I'm in the midst of my first major project with Angular. I have one controller that is doing a ton of the legwork, and it's reached the point where it's thousands of lines of JavaScript.
I'd like to break this up somehow, but I can't seem to find a solid example anywhere. The code is mostly made up of functions used to do calculations on objects, so directives and modules don't seem like the right answer, but I could be wrong there.
How are you guys organizing code in your large Angular projects? Should I just suck it up, or is there a sane way to split this into easy to scan files?
I suggest putting at least some of those objects and their related calculations into services, then inject the services into your controller(s). See the Sticky Notes Part 1 blog entry for an example of a service that encapsulates some data and provides methods to access/manipulate that data.
See if you can break up your controller into multiple controllers, one for each view. A view can be as large as a page, or just some chunk/block on a page.
To quote from a google group post I saw recently: "I prefer to think of angular controllers as dumb apis/configs for my views and leave all the heavy lifting to services." -- reference
There are a few things that you need to ask yourself when you are in a controller.
Are you doing any DOM manipulation in the controller? This is a definite NO. Dont ever do that. It always belongs in the directives department.
Are you writing any Business Logic in your controller? That too is a NO. Your Business logic should in most cases exist in a Service. That is the right place for it.
Now, have a look at your controller. Is it devoid of these 2 things and still larger than 1000 lines? It is highly unlikely, but even if it somehow is happening, then consider breaking down your controller into smaller controllers. This breaking of controllers have to be done based on the view.
To sum things up, your controller is just a place where you glue up the business logic and your views in the HTML. It should technically never contain anything other than these glues.
I usually create a Util factory (seems to be the way to go now in Angular rather than services) and have it return any shared logic as a set of methods.
https://gist.github.com/lamba/c275f5f010090632209e