I cannot get the Breeze Angular service (http://www.getbreezenow.com/documentation/breeze-angular) to configure Breeze to use Angular promises, i.e., I can never get the useNgPromises() function within breeze.bridge.angular.js to log a message to the console and thus I assume Breeze is never configured to use Angular promises.
My JS files are loaded as follows:
angular.js (v 1.3.14)
angular-route.js (v.1.3.14)
q.js (v 1.1.2) - This is here because I kept getting errors that Q was undefined if I left this out. I don't know if it is necessary to load Q.js if I use Angular promises instead.
breeze.js (v 1.5.3)
breeze.bridge.angular.js (v 1.1.0)
app.js and other app-specific JS files
So far, that satisfies steps #1 and #2 from the "Install It" section of that Breeze page.
Per steps #3 and #4 on that Breeze page and comments in breeze.bridge.angular.js, this is what my app.js looks like:
window.myApp = angular.module("myApp", [
"breeze.angular"
])
.value("breeze", window.breeze)
.config(["$routeProvider", function ($routeProvider) {
// Routing code
}])
.run(['breeze', function (breeze) {}]);
As far as I can tell, that code matches the Example #1 code on that Breeze page and satisfies steps #3 and #4 on that Breeze page.
Then I have some basic views that use controllers and datacontext JS files, the latter of which inject the breeze object as a dependency. To test whether Breeze is actually executing the configuration to work with Angular promises, I edited the breeze.bridge.angular.js file such that the following statement is included as the first line in the useNgPromises() function:
console.log("Using Angular promises!");
When I run my app, I never see that in the console, so I assume the configuration is not happening.
Am I doing something wrong in the setup? If so, what?
You absolutely do NOT need Q.js; the fact that you see errors relating to that library is an indication of a configuration mistake.
I think you found the problem when you added .value("breeze", window.breeze).
That one line wipes out the definition of the breeze service established by the 'breeze.angular' module (defined in breeze.bridge.angular.js), thus preventing the configuration of breeze for $http and $q. Without that configuration, breeze looks for a promises implementation elsewhere ... hence the complaint about missing Q.js. So ... yes ... that line was a disaster.
I wondered where you got the idea for that line. Thanks for referencing the Microsoft ASP Breeze/Angular template documentation. Wow that is old (2013). I'd kill it ... and the other defunct Visual Studio Breeze templates ... if I could (maybe I can). I thought we had made them hard to find. Looks like you found them. How?
That certainly isn't how we teach Breeze + Angular these days.
The "Todo Angular" sample is a far better guide (even if it is a year old).
I resolved the issue by commenting out the line:
.value("breeze", window.breeze)
I had included that line per the "Dependency Injection" section here: http://www.getbreezenow.com/ng-spa-template#module as well as the "Value Recipe" section here: https://docs.angularjs.org/guide/providers, but apparently it does not play well with the Breeze Angular service.
I am not sure exactly why this is the case but my best guess is that the issue was caused by Angular values not being configurable, per this explanation: https://gist.github.com/demisx/9605099, and I assume the Breeze Angular service requires the Breeze object to be configurable and therefore it should not be injected as a dependency for the app via the value recipe.
I should also note that after removing that troublesome line of code, I no longer receive an error indicating that Q.js is required since the Breeze Angular service successfully configures Breeze to use Angular's $q instead.
Related
I've migrated my angular application from Angular 1.3.15 to Angular 1.5.5. I'm struggling with this for about a day and tried various possible solutions mentioned in the AngularJS Error Reference, checked my code to not contain,
Multiple module definitions for the same moudule
Not contain a controller inside another controller.
Attempting to inject a scope object into anything that's not a controller or a directive.
Also tried checking the dependency issue
Couldn't find any fruitful solution to this, the whole screen seems like broken, like, angular itself hasn't been loaded, things, like interpolations are not resolved to their values.
Help is much appreciated.
Thanks!
The i18nFilter which you are referencing in your application is likely being provided via the angular-localization library.
There are a number of issues raised in the project relating to version compatibility when upgrading the AngularJS version.
I suggest you track down the version you are referencing and upgrade to a supported version for AngularJS 1.5.5
I'm trying to clean up my Angular app a little bit and when I came to my app.js.coffee file I ran into some things I have little knowledge of because I copy/pasted it from another source and it seemed to work.
To my knowledge every controller, service, filter etc. needs a ,
angular.module('nameOfModule')
But 2 (or more) controllers can't have the same module name because then Angular outputs an error,
Error: [ng:areq] Argument 'nameOfModule' is not a function, got undefined
But it seems the module name that you give a controller such as nameOfModule can be used on multiple services,
addMovieService.js
angular.module('addMovieseat')
.factory('movieAdd',
movieSearchService.js
angular.module('addMovieseat')
.factory('MovieSearch',
So I'm starting to wonder what the module names are for.
Add dependency for your angular module and if not then put it blank like this
angular.module('nameOfModule',[])
Error is occured because you don't add dependency for your module.
But 2 (or more) controllers can't have the same module name
This assumption is incorrect! Modules almost always have more than one controllers. In fact it is the highest level in an angular app and the module, along with all other entities (controllers, services, factories) comprise of a self sustaining AngularJS app.
For using another app inside another app, you just include the module as a dependancy like this:
angular.module('secondApp', ['firstApp'])
I'm working on a Cordova application using AngularJS and OnsenUI. I'm having trouble with the documentation that's out there with respects to the call to ons.bootstrap().
Specifically, I am used to manually bootstrapping AngularJS applications in Cordova when needed -- i.e., either when the DOM loads, if I'm in a browser, or when the deviceready event fires, if I'm on a device, with a call to angular.bootstrap(document, [ 'myApp' ]).
I noticed that in Onsen, there's a necessary call to ons.bootstrap, with or without other parameters, such as ons.bootstrap('myApp', [...dependencies...]). I have fiddled around with this, and it seems like the only way I can get Onsen injected is if I use its bootstrapping call. However, elsewhere in my application's file, I'm still using the angular definitions (e.g., angular.module('myApp', [...dependencies...]).config(...).run(...)) and so forth.
I've found several things of questionable implementation, and haven't been able to find a definitive answer online as to this:
1) If I call angular.bootstrap within my initialization, Onsen never loads
2) If I use the ons.bootstrap call, things seem to work, but I end up repeating my dependencies within the bootstrapping call as well as my application definition using angular. This redundancy seems bad to me.
3) If I use both calls (not unexpectedly), I get a isWebView() already defined error, and the application goes nowhere.
Unfortunately, all of the examples on the Onsen website assumes all code (HTML, JS, etc.) like to reside in one spot, and doesn't seem to take Cordova into account. I've used Onsen in the past, but several versions ago, and the old methods of injection no longer seem to work.
So my question is, what is the way you're supposed to bootstrap and use Onsen, Angular, and Cordova together? Alternatively, is there a good example somewhere that doesn't involve Monaca?
Thanks in advance.
Of course there are good examples somewhere. Have you tried with the basic Onsen UI templates? They are provided in the 'Getting started' guide of Onsen UI and answer all your questions: http://onsen.io/download.html#download-templates
In short, Onsen UI is independent from Monaca and the only difference will be including Monaca's loader.js in your index.html (what includes OnsenUI, AngularJS, Cordova, etc.), or including all the libraries separately.
Also, ons.bootstrap() is optional, you can use angular.module('app', ['onsen']) if you want.
It is possible to use Cordova as well, you just need to include Cordova files as you would do in any other Cordova application. You can see it in the templates.
There are many examples out there with all of this, like the basic templates. More examples:
Onsen UI's Github: https://github.com/OnsenUI/OnsenUI/tree/master/demo
Onsen UI's blog: http://onsen.io/blog/developing-hybrid-mobile-apps-with-onsen-ui/
Hope it helps.
Well, for some reason, the only way I can get this thing to initialize appropriately is by using the Onsen bootstrap method and having it load all dependencies. Since ons.bootstrap() returns the Angular module, I'll use that for now.
So essentially, on the Cordova deviceready event, I call:
angular.module('myApp.controllers', []);
angular.module('myApp.services', []);
ons.bootstrap('myApp', [ ...dependencies... ]);
And yes, there are plenty of examples out there, but the ones that incorporate Cordova and exercise a reasonable organizational facsimile of how actual code would be used, being that different objects are defined within different files, in multiple folders, are quite lacking. Although admittedly by Google-Fu isn't necessarily great.
Thank you for your response.
Thanks to the great article from Dan Wahlin, I managed to implement lazy loading of Angular's controllers and services. However, there does not seem to be a clean way to lazy load independent modules.
To better explain my question, assume that I have an app would be structure as below without RequireJS:
// Create independent module 'dataServices' module with 'Pictures' object
angular.module("dataServices", []).factory("Pictures", function (...) {...});
// Create 'webapp' ng-app, with dependency to 'dataServices', defining controllers
angular.module("webapp", ['dataServices'])
.controller("View1Controller", function (...) {...})
.controller("View2Controller", function (...) {...});
Here is the sample app with RequireJS in Plunker:
http://plnkr.co/aiarzVpMJchYPjFRrkwn
The core of the problem is that Angular does not allow adding dependency to ng-app post instantiation. As result, my solution is to use angular.injector to retrieve the instance of Picture object to be used in my View2Controller. See js/scripts/controllers/ctrl2.js file.
This creates 2 problems for me:
The injected services runs outside of angular and therefore all async call must end with $scope.$apply()
Messy code where some object can be injected using standard angular syntax while others require the explicit use of injector.
Have any of you figured out how to lazy load independent module using RequireJS and somehow hook this module in angular so normal angular dependency injection syntax can be used?
Note:
The question is on lazy loading of independent module. One simple solution to this specific example is to create "Pictures" object using cached $providers during ng-app.config but that is not what I am looking for. I am looking for solution that works with 3rd party module such as angular-resource.
I finalized my own implementation called angularAMD and here is the sample site that uses it:
http://marcoslin.github.io/angularAMD/
It handles config functions and out of order module definitions.
Hopefully this can help other looking for something to help them with RequireJS and AngularJS integration.
Take a look at my project in GitHub: angular-require-lazy
This project is intended to demonstrate an idea and motivate discussions. But is does what you want (check expenses-view.js, it loads ng-grid lazily).
I am very interested in comments, ideas etc.
(EDIT) The ng-grid Angular module is lazy loaded as follows:
expenses-view.js is loaded lazily, when the /expenses route is activated
expenses-view.js specifies ng-grid as a dependency, so RequireJs loads ng-grid first
ng-grid is the one that calls angular.module(...)
In order to accomplish this, I replaced (proxied actually) the real angular.module method with my own, that supports laziness. See bootstrap.js and route-config.js (the functions initLazyModules() and callRunBlocks()).
This implementation has its drawbacks that you should be aware of:
Config functions are not implemented (yet). I do not know if it is possible to lazily provide config-time dependencies.
Order matters in definitions. If service A depends on B but A is defined after B in your module, DI wil fail. This is because the lazyAngular proxy executes definitions immediately, unlike real Angular that makes sure dependencies are resolved before executing the definitions.
It looks like the Node.js module ocLazyLoad defines a way of doing this lazy-loading, though I'm not sure how it fares, performance-wise, compared to the methods in the other answers or hard-coding the dependencies. Any info on this would be appreciated. One interesting thing is that the other answers need RequireJS to operate, while ocLazyLoad doesn't.
It looks like ocLazyLoad defines another provider that injects the dependency after the containing module has already been instantiated. It seems to do this by essentially replicating some low-level Angular behavior, like module loading and providing, hence why it looks so complicated. It looks like it adds just about every core Angular module as a dependency: $compileProvider, $q, $injector, ng, and so many more.
I am new to Jasmine, but would like to do more TDD in Javascript. I've been using the Angular library from Google, and I know that Testacular was specifically created for testing Angular apps.
I have read through both the Jasmine documentation and watched the Testacular setup video, but I can't get the most basic testing to work. Assume I have three files:
modules.js
controller.js
appSpec.js
modules.js has my module definition with a few .factory(...) services and a few .directive(...) custom directives. controller.js houses my controllers for wiring up the modules to the html view.
So far, so good. Next I have added appSpec.js. Let's say I want to use it to test a service in my module called, "Data" that has a method, "getData()" which returns a resource.
In testactular init I have told it to watch all three files. I run Testacular and it tells me it is watching the correct files. Super.
What I don't understand is how I get the Jasmine spec know how to look at the module and controller so that they can be tested. If I simply say:
describe('Data Service', function(){
it ('should retrieve two items from the database', function(){
data = Data.getData() //my angular service
expect(data.length).toBe(2);
});
});
Not surprisingly, it has no idea what Data.getData() is.
It seems obvious that somehow I am supposed to bring my module definition and controllers into the spec before I begin writing suites. It must be so obvious that I don't see in the documentation how people are doing it. Tutorials just seem to start writing specs in the spec.js file and assume all is well.
I have seen other posts here where similar questions are being asked, but admittedly they all have a foundation I seem to be lacking. For example, one post talks about not manually creating an instance of the controller, but rather inject dependencies. Why is he creating a new $rootScope object, how is his module being referenced, etc...
I understand that my question is probably just a lack of basic understanding of the Jasmine framework, but I can't seem to squeeze any more understanding from the Jasmine readme file. Can someone point me to a basic explanation of how this is supposed to work?
Thanks.
Try doing module('myModule') in the jasmine test.
Here are some open source angular projects that have great tests to look at:
angular-app
angular-ui
bootstrap
The way that you include your definitions for your tests is through the karma.config.js file
files = [
JASMINE,
JASMINE_ADAPTER,
'../app/lib/icg/object.js',
'../app/lib/icg/geometry.js',
'../app/lib/icg/ubiquity.js',
'../test/unit/icgUbiquitySpec.js',
'../test/unit/icgObjectSpec.js'
];
Here you define which files get loaded into your browser, the first files that don't include the word 'Spec' are the definitions and the ones that do include are my test files. You need to include your definitions BEFORE your tests so that they are defined before you run the tests, which is why I include all my spec files last.