When trying to implement the session part in the tutorial of John Papa Pluralsight Video.
I got the following error:
Uncaught TypeError: Object # has no method 'extendQ'
(function () {
'use strict';
var app = angular.module('app', [
// Angular modules
'ngAnimate', // animations
'ngRoute', // routing
'ngSanitize', // sanitizes html bindings (ex: sidebar.js)
// Custom modules
'common', // common functions, logger, spinner
'common.bootstrap', // bootstrap dialog wrapper functions
// 3rd Party Modules
'ui.bootstrap', // ui-bootstrap (ex: carousel, pagination, dialog)
//'breeze.angular.q'
]);
// Handle routing errors and success events
app.run(['$route', '$rootScope', '$q', function ($route, $rootScope, $q) {
// Include $route to kick start the router.
breeze.core.extendQ($rootScope, $q);
//use$q($rootScope,$q);
}]);
})();
It's important to know that the version of breeze that I'm working on is newer than the used on the original video.
I search for some answers on the breeze website and I've found this:
The to$q has been deprecated. It is superseded by the Breeze Angular Service.
But I didn't make it work on the tutorial example. How to change the deprecated implementation with the new one?
UPDATE:
this link helped solve the problem:
http://www.breezejs.com/documentation/breeze-angular-service
The breeze library was updated and the answer is on this link: http://www.breezejs.com/documentation/breeze-angular-service
Specifically this code from the bottom of the post:
Migration is pretty painless.
Remove the breeze.angular.q.js script from your project.
Uninstall-Package Breeze.Angular.Q if you used NuGet.
Install breeze.angular.js as explained above.
Update your index.html, changing breeze.angular.q.js to breeze.angular.js.
Update your app module to depend on "breeze.angular".
Find the one place in your code where you call "use$q" and replace it with the "breeze" dependency.
For example, you might go from this:
var app = angular.module('app', [
// ... other dependencies ...
'breeze.angular.q' // tells breeze to use $q instead of Q.js
]);
app.run(['$q','use$q', function ($q, use$q) {
use$q($q);
}]);
to this:
var app = angular.module('app', [
// ... other dependencies ...
'breeze.angular'
]);
app.run(['breeze', function () { }]);
You should also track down and eliminate code that configures Breeze to use the "backingStore" model library adapter and $http. For example, you could go from this:
function configBreeze($q, $http, use$q) {
// use $q for promises
use$q($q);
// use the current module's $http for ajax calls
var ajax = breeze.config.initializeAdapterInstance('ajax', 'angular');
ajax.setHttp($http);
// the native Breeze 'backingStore' works for Angular
breeze.config.initializeAdapterInstance('modelLibrary', 'backingStore', true);
breeze.NamingConvention.camelCase.setAsDefault();
}
to this:
function configBreeze() {
breeze.NamingConvention.camelCase.setAsDefault();
While taking the same course by John Papa I also hit breeze.core.extendQ not available on step 4.10.
This is what I did to solve the issue:
1 - In app.js pass breeze dependency directly:
// Handle routing errors and success events
// Trigger breeze configuration
app.run(['$route', 'breeze', function($route, breeze)
{
// Include $route to kick start the router.
}]);
2 - In datacontext.js do:
return EntityQuery.from('Sessions')
.select('id, title, code, speakerId, trackId, timeSlotId, roomId, level, tags')
.orderBy(orderBy)
.toType('Session')
.using(manager).execute()
.then(querySucceeded, _queryFailed);
You can also get rid of breeze.to$q.shim.js from index.html and delete the file from the \Scripts folder in the project since it's not needed anymore.
Here's the updated source code of the same project I'm doing now [ including the fixes ].
Related
I am trying to get angularjs to play nicely with local templates that override bootstrap ones.
I had initially use the same file path (uib/template/carousel/carousel.html for example) which is fine when published, but locally it doesn't work.
So, I found this soluton:
Angular ui bootstrap directive template missing
They have said you can override the template with a new url with the $provide service.
So I have done this:
'use strict';
angular.module('core').config(coreConfig);
function coreConfig($provide) {
$provide.decorator('uibCarousel', function ($delegate) {
console.log($delegate[0]);
$delegate[0].templateUrl = 'bootstrap/carousel/carousel.html';
return $delegate;
});
};
which should work.
my core module looks like this:
'use strict';
angular.module('core', [
'ngCookies',
'ngNotify',
'ngResource',
'ngSimpleCache',
'ui.bootstrap',
'ui.bootstrap.tpls',
'ui.router',
'ui.select',
// -- remove for brevity -- //
]);
As you can see, I have the ui.bootstrap.tpls module loaded, so in theory, my code should work.
Can anyone think of a reason that it won't?
Sorry for all the comment spam. I think I have found the answer to your issue.
You must append Directive to a directive when defining the decorator:
function coreConfig($provide) {
$provide.decorator('uibCarouselDirective', function ($delegate) {
console.log($delegate[0]);
$delegate[0].templateUrl = 'bootstrap/carousel/carousel.html';
return $delegate;
});
};
From the docs:
Decorators have different rules for different services. This is
because services are registered in different ways. Services are
selected by name, however filters and directives are selected by
appending "Filter" or "Directive" to the end of the name. The
$delegate provided is dictated by the type of service.
https://docs.angularjs.org/guide/decorators
This is an example from my own (working) code:
$provide.decorator("uibDatepickerPopupDirective", [
"$delegate",
function($delegate) {
var directive = $delegate[0];
// removed for brevity
return $delegate;
}
]);
The short story is that I'm trying to lever some data model code that's not written for angular in particular into an angular application. This code is written using ES6 import / export syntax for modules, and I'd like to keep using that. So I have something like:
export class DataModel {
//some stuff with promises
}
What I did was create a utility module that exposes the relevant Angular (1.5) services to the ES6 module system thusly:
import angular from 'angular';
export const services = {};
angular.injector(['ng', 'toastr']).invoke([
'$q',
'$http',
'$rootScope',
(
$q,
$http,
$rootScope
) => {
services.$q = $q;
services.$http = $http;
services.$rootScope = $rootScope;
},
]);
Then I can just import the $q library into my DataModel classes and hey presto, everything kind of works - I'm doing promises, and the appropriate scopes should update when the .then methods fire.
The problem is that this doesn't actually work. I'm 90% sure that the reason this doesn't work is that the $rootScope element I get from the angular.injector call isn't a singleton rootscope, it's a fresh new one that gets created just for this context. It does not share any scope linkage with the actual scope on the page (I can confirm this by selecting a DOM element and comparing services.$rootScope to angular.element($0).scope().$root). Therefore, when a promise resolves or a $http returns, I get the data but have the standard symptoms of not notifying a scope digest in the interface (nothing changes until I manually trigger a digest).
All I really want is a copy of the $q, $rootScope and $http services that angular uses live in the active page. Any suggestions are welcome. My next try will be to see if I can grab the relevant services from some .run block where I inject $q et al instead of doing it with the injector. That introduces some problematic timing issues, though, since I need to bootstrap angular, run the run block, and then expose the services to my data model. But the bootstrapping process requires the datamodel. It's a bit circular.
I'm answering this myself for now, but would love to see any other ideas.
I changed the angularServices code to look like:
import angular from 'angular';
import { Rx } from 'rx-lite';
export const servicesLoaded = new Rx.Subject();
export const services = {};
angular.module('app.services', []).run([
'$q',
'$http',
'$rootScope',
(
$q,
$http,
$rootScope
) => {
services.$q = $q;
services.$http = $http;
services.$rootScope = $rootScope;
servicesLoaded.onCompleted();
},
]);
Since I was already using rx-lite anyway. This allows me to do
import { services } from 'angularServices';
services.$http(options) // etc;
whenever I'm working in code that is run after the application bootstrap cycle. For the code that was running prematurely (it was just config stuff that was in a few places, I wrapped it inside the RxJS event thusly:
import { services, servicesLoaded } from '../../common/angularServices';
servicesLoaded.subscribeOnCompleted(() => {
services.$rootScope.$on('$stateChangeSuccess', () => {
//etc
That way I don't try to get in touch with $rootScope or $window before it actually exists, but the $q, $rootScope, and $http I've stashed a reference to in my services object is actually a real thing, and digests all fire properly.
And now hey presto, while my model layer references $http and $q, they'll be pretty easy to exchange with some other provider of promises and XHRs, making all the work I put into that not bound to angular 1.x. Whee.
I am trying to include ngCookies in a project. The angular cookies library is included in my index.html after the ionic.bundle.
I can see on the network tab of the developer tools that it is actually loading. Angular doesn't show any error when loading the page, as it usually does when a module is missing. The problem is that, when in my code I try to access the functions of the $cookies service, the $cookies variable is actually pointing to an empty object.
Here are some relevant code snippets:
On the definition of my app.js
angular.module('myApp', [
'ionic',
'ngCookies',
'ngMessages',
'rt.eventemitter',
'myApp.views']);
On my factory:
angular.module('myApp.views')
.factory('UserStore', ['$rootScope', '$q', '$cookies', '$timeout',
function($rootScope, $q, $cookies, $timeout){
var user = {};
function setSessionId(sessionId){
console.log(">> setting sessionId to:",sessionId);
user.sessionId = sessionId;
$cookies.put('sessionId', user.sessionId);
}
return{ setSessionId:setSessionId}
}
]);
In this case, when I try to call the setSessionId method I get an error that $cookies.put is not a function since, as I mentioned above, $cookies is just an empty object.
Any Ideas?
it depends on which angular version you use!
they changed a lot in angular 1.4.. in angular 1.3 when you set a cookie you can just assign it:
$cookies.sessionId = user.sessionId;
I want to automatically dependency inject an Angular built-in service into all services within an Angular module / app.
The service I want to inject is ... $exceptionHandler
I do not want $exceptionHandler to be global ... e.g. I do not want to do ...
window.$exceptionHandler = $exceptionHandler
But I also do not want to dependency inject $exceptionHandler into every service manually using ...
angular.module('myApp').factory('myService', ['$exceptionHandler', function ($exceptionHandler) {
Is it possible to automatically inject an Angular built-in service into all services within an Angular module / app ?
Many thanks
It can be made more convenient through nested modules. In the root (or global) module inject $exceptionHandler and all the other modules you create or want to use. All sub modules of the root module will have $exceptionHandler injected without further ado. You still have to name the $exceptionHandler in your controller and factory function definitions, though, so it is not possible to completely get rid of injection artefacts.
Example:
app.js
angular.module('app', ['ionic', '$exceptionHandler', 'ngCordova','app.home',
'app.impressum'])
.run(function ($ionicPlatform, $state) {
..
})
.config(function ($stateProvider, $urlRouterProvider, $provide, $exceptionHandler, $ionicConfigProvider, $compileProvider) {
$stateProvider
.state('app', {
...
})
}
);
Now the app.home-Module:
home.js
angular.module('app.home', ['app.home.controller', 'app.home.factory']);
home/controller.js
angular.module('app.home.controller', [])
.controller('homeController', function ($scope, $exceptionHandler) {
...
});
app.home.factory and the three modules for app.impressum are quite similar, so I leave that to you.
As you can see you still have to put $exceptionHandler into the function parameters of your controller, but no injection is required on the module itself, because it inherits all injections from it's parent modules app.home and app.
By using a hierarchy of modules in an AngularJS app injections can be made where due... more globally for the whole app, for module groups or only on single modules. Plus we get a very clean structure for the App's sections.
I'm learning Angular and I'm trying to include Restangular this way:
var app = angular.module('myapp',['restangular']);
app.controller('UsersController', ['$scope', function ($scope, Restangular) {
...
Then I'm using Restangular like this:
var data = Restangular.all('someurl');
Here I get an error: Restangular is undefined. According to the documentation, this should have been simple:
// Add Restangular as a dependency to your app
angular.module('your-app', ['restangular']);
// Inject Restangular into your controller
angular.module('your-app').controller('MainCtrl', function($scope, Restangular) {
// ...
});
However I am unable to get it to work. What gives?
You're using the bracket notation for your controller, but you forgot to add Restangular to the list of dependencies:
['$scope', 'Restangular', function ($scope, Restangular) {...}]
This article has more information on Angular and minification. Search for "A note on minification”.
That looks correct, just make sure you've added the import of Restangular to your html file
<script type="text/javascript" src="http://cdn.jsdelivr.net/restangular/1.1.3/restangular.js"></script>
They also mention it requires lodash or underscore.js so maybe make sure you're loading those as well