I want to add a ocLazyLoad in my mean-stack website. Here is the code:
.state('kpi', {
url:'/kpi',
templateUrl: '/htmls/kpi.html',
resolve: {
loadMyCtrl: ['$ocLazyLoad', function ($ocLazyLoad) {
return $ocLazyLoad.load('/javascripts/kpi-controller.js').then(function () {
console.log("done");
}, function (e) {
console.log("error")
})
}]
}}
Loading the kpi page returns
bootstrapped
kpi-controller inside
done
Error: [ng:areq] http://errors.angularjs.org/1.5.8/ng/areq?p0=KpiCtrl&p1=not%20aNaNunction%2C%20got%20undefined
where the error is about Error: ng:areq Bad Argument Argument 'KpiCtrl' is not a.
KpiCtrl is defined in kpi-controller.js, and printing kpi-controller inside in the console shows the file has been indeed loaded. But why KpiCtrl is still not recognized?
One thing special about my code is, in the beginning of the program, I have
jQuery(document).ready(function () {
angular.bootstrap(document, ['myweb'])
console.log("bootstrapped");
})
app = angular.module('myweb', ['ui.router', 'oc.lazyLoad']);
I did not understand angular.bootstrap well, but it seems that the new loaded KpiCtrl should be bootstrapped to be recognized. I tried to add angular.bootstrap(document, ['myweb']) inside ocLazyLoad, but it showed App already bootstrapped with this element 'document'.
Does anyone know how to solve this?
Related
Implementing localization in angular app.
In app.js, written below code to support fallback language , if required .json files not present in the specific {{de-DE}}\ folder. (Taken german for example)
function configure($routeProvider, $locationProvider, $translateProvider, $httpProvider, $compileProvider) {
$routeProvider
.when('/instructions', {
templateUrl: "app/instructions/Instructions.html",
resolve: {
translatePartialLoader: ['$translate', '$translatePartialLoader', function ($translate, $translatePartialLoader) {
$translatePartialLoader.addPart('instructions');
$translatePartialLoader.addPart('common');
//$translatePartialLoader.addPart('instructions').then(function (data) {
//console.log(data);
//});
//$translatePartialLoader.addPart('common').then(function (data) {
// console.log(data);
//});
$translateProvider.fallbackLanguage("en-US");
return $translate.refresh();
}]
}
})
.otherwise(
{
redirectTo: redirectTo
});
$httpProvider.useApplyAsync(true);
//$locationProvider.html5Mode(true);
$translateProvider.preferredLanguage($("#CultureCode").val());
$translateProvider.fallbackLanguage('en-US');
}
After changing my browser setting to german (google chrome). Files were not found, so it had to fallback. With the above code, my fallback language was english. So app downloaded .json files from {{en-US}}\folder.
But the actual problem is.
Once all the code excecutes , in one place i have written.
$rootScope.$broadcast("SHIFT_CHANGED");
And subscribing for the event like below.
$scope.$on("SHIFT_CHANGED", function() {
loadInstructions();
});
Here load instructions in my main method. Which is not getting executed because. Shift_changed events is not getting fired.
For testing purpose as soon as i paste those .json files in german folder. App starts working. But am trying to implement fallback.
I tried few code which is commented for refrence above. addpart trying to resolve for promise.
But none of them worked.
Am i missing some thing. And no error in console.
clueless to figure out.Any ideas to troubleshoot further / Is really some code is missing.
Please help.
Thanks in Advance
I want to test my app with protracor but test fails with this errors :
Failed: Error while waiting for Protractor to sync with the page: "root element (html) has no injector. this may mean it is not inside ng-app."
it seems that angular doesn't load completely, and browser.waitForAngular(); not working.
how can I setup protractor to continue test after RequireJs load dependencies ?
also adding this :
onPrepare:function(){
browser.manage().timeouts().pageLoadTimeout(40000);
browser.manage().timeouts().implicitlyWait(25000);
}
to ocnfig file(As mentioned here) cause this error:
Failed: Error while waiting for Protractor to sync with the page: "angular could not be found on the window"
You will need a manual way to know that Angular has bootstrapped from within your specs. Here's the basic run-down of how I have this set up with Angular, RequireJS and Protractor. This works for me with jasmine2 and old jasmine.
We want to add a class of ng-app to the element that Angular bootstraps. For example:
index.html
<html lang="en" class="ng-app">
But rather than putting this in the HTML file, we want to add the class using the same RequireJS module that is manually bootstrapping your Angular App. Eg:
ng-bootstrap.js
require(['angular'], function (angular, otherdeps) {
// Start the Angular App
angular.bootstrap(document, ['MyApp']);
// Set the ng-app class for Angular Protractor tests
var root = document.documentElement;
angular.element(root).addClass('ng-app');
});
Check that your page adds this class after bootstrapping. then set up your protractor.conf exports to run the onprepare test. This spec is executed each time Protractor is launched and we will use it to check for the class you added in the ng-bootstrap.js module.
protractor-conf.js
exports.config = {
// Every time protractor is launched:
onPrepare: 'onprepare.e2e.js',
};
In your onprepare.e2e.js spec file, you can trigger the load of the home page. Then ask Protractor to wait until the class .ng-app is found on the root element, Ie: Angular has bootstrapped and is ready to run Protractor tests.
onprepare.e2e.js
describe("On prepare", function () {
// Replace with your own URL
var baseUrl = 'http://127.0.0.1:8001/#/';
// Begin fetching the page
browser.driver.get(baseUrl);
// Wait until `.ng-app` is found on the root elem
browser.driver.wait(function () {
return browser.driver.getCurrentUrl().then(function (url) {
return browser.driver.isElementPresent(by.className('ng-app')).then(function () {
return true;
});
});
});
});
Keep in mind that if you a running lots of spec files together, your page could is being re-loaded when a new test starts. Your page also may be being reloaded if your Angular router is using a reload: true param.
This means that the app has to bootstrap again; And you will need to wait for the bootstrap class again before you can use Protractor.
Add a helper for this and include it in your protractor-conf.js.
helpers.js
module.exports = {
get: function (url) {
browser.driver.get(url);
browser.driver.wait(function () {
return browser.driver.getCurrentUrl().then(function (url) {
return browser.driver.isElementPresent(by.className('ng-app')).then(function () {
return true;
});
});
});
},
};
protractor-conf.js
helpers = require('helpers.js');
exports.config = {
onPrepare: 'onprepare.e2e.js',
specs: [
'my-spec.js'
]
};
Now your helper is globally visible to your specs and you can use your new helper.get(url) method instead of browser.driver.get(url). Example:
my-spec.js
describe("Users", function() {
it('should login', function () {
// Wait for Angular and RequireJS to finish
helpers.get('http://127.0.0.1:8001/#/login');
// ...tests here...
});
});
I had some similar problem, maybe it is because the way our app is loaded, but you can try having some custom wait:
browser.driver.wait(function() {
return browser.driver.isElementPresent(by.css('.ng-scope'));
}, 50000);// ^^or some other locator for your angular
});
inside your beforeEach() for example.
Edit:
Also for someone it helps to change browser windows size:
browser.manage().window().setSize(1280, 1024);
in onPrepare()
I can run test by adding browser.driver.sleep(3000) to beforeEach.
but this isn't the right solution.
I am trying to create notifications something like this:
http://plnkr.co/edit/GbFioFDNb2OC4ZjARQTp?p=preview
But I am unsuccesful to integrade it in my script, because when I click outside notification box nothing happend.
Here is my script:
'use strict';
var app = angular.module('notifications',['ngRoute'], function($interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
})
.controller('NotificationController', function($scope, $http) {
$http.get("/api/notification")
.success(function (response) {
$scope.notys = response;
});
$scope.notifications = {
visible: false
};
$scope.showNotifications = function(flag) {
$scope.notifications.visible = flag;
};
})
.directive('customBlur', function(){
return {
restrict: 'A',
scope: {
'customBlur': '='
},
link: function(scope, element, attr) {
element.on('click', function(event){
var targetAttr = angular.element(event.target).attr('custom-blur');
console.log(targetAttr);
if (typeof targetAttr !== 'undefined') {
scope.$apply(function(){
scope.customBlur = false;
});
}
});
}
};
});
Problem is when I click outside notifcation box it not return anything but shuld return notification.visible if I click into notification box it return undefined as expected.
that is result for: console.log(targetAttr);
I ran your code in plunkr and tried to fix the error.
All I found is that your module name and controller name were not same.
Uncaught Error: [$injector:modulerr] Failed to instantiate module demo due to:
Error: [$injector:nomod] Module 'demo' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
http://errors.angularjs.org/1.4.2/$injector/nomod?p0=demo
This error says that angular is not able to find the module 'demo'. So I made changes to HTML here. This line:
<html ng-app="notifications">
After that I got this error:
Uncaught Error: [$injector:modulerr] Failed to instantiate module notifications due to:
Error: [$injector:modulerr] Failed to instantiate module ngRoute due to:
Error: [$injector:nomod] Module 'ngRoute' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
This says that ngRoute which you are using here angular.module('notifications',['ngRoute'], function($interpolateProvider) { is not available. So I just removed it. (just to fix the error.).So I did changes to js. This line:
angular.module('notifications',[], function($interpolateProvider) {
ok After that I got this error:
Error: [ng:areq] Argument 'Ctrl' is not a function, got undefined
http://errors.angularjs.org/1.4.2/ng/areq?p0=Ctrl&p1=not%20a%20function%2C%20got%20undefined
Which says that Ctrl is not defined properly.So I made changes to HTML again.This line
<body ng-controller="NotificationController">
ok. After fixing all this I found no more error. and your plunker started working again.
you can see the plunker here : plunker
Hope this helps you. Thank you.
When running grunt karma, a test on one of the directive fails when it tries to fetch the template. I am using ng-html2js as a preprocessor. Here is some of my karma.conf.js
plugins: ['karma-chrome-launcher',
'karma-jasmine',
'ng-html2js',
'karma-ng-html2js-preprocessor'],
preprocessors: {
'app/scripts/directives/**/*.html': 'ng-html2js'
},
ngHtml2JsPreprocessor: {
moduleName: 'templates'
}
In my test, I have the following:
'use strict';
describe('Directive: myDirective', function () {
// load the directive's module
beforeEach(module('myApp'));
beforeEach(module('templates'));
var element,
scope;
beforeEach(inject(function ($rootScope) {
scope = $rootScope.$new();
}));
it('should not show search area initially', inject(function ($compile) {
element = angular.element('<navbar></navbar>');
element = $compile(element)(scope);
scope.$digest();
expect(element.find('.myClass').hasClass('myClass')).toBe(true);
}));
});
When I run the test, I get
Error: Unexpected request: GET /scripts/directives/myDirective/myDirective.html
It seems like the preprocessor is not properly injecting the javascript version of the template.
I have also tried using the path of the template in the beforeEach(module('')); but that causes an error that reads:
Error: [$injector:modulerr] Failed to instantiate module...
How can I fix this?
I had kind of the same problem. Be sure you have the exact file match. Open the Google chrome console and check the file path is exactly the same.
In the upper exemple, I had to add a "/" string in ngHtml2JsPreprocessor.stripPrefix and it worked.
So I guess with Yeoman, you should use
ngHtml2JsPreprocessor: {
moduleName: 'templates',
stripPrefix: 'app/' //add a slash
}
Since I was using the Yeoman tool to scaffold my project, I needed to add a stripPrefix to the ngHtml2JsPreprocessor option in my karma.conf.js file:
ngHtml2JsPreprocessor: {
moduleName: 'templates',
stripPrefix: 'app'
}
I had started writing an app using angularJS. After a few weeks, I suddenly realized that I should have used require JS from the beginning to load my modules. Yes, I know, it was stupid. But it is what it is.
So I've tried to convert my code to suit requireJS now.
This is my main.js
requirejs.config({
baseUrl: "js",
paths: {
jquery:'jquery-1.7.min',
angular: 'angular',
angularRoute:'angular-route',
mainApp:'AngularApp/app'
},
priority:['angular'],
shim:{
angularRoute:{
deps:["angular"]
},
mainApp:{
deps:['angularRoute']
}
}});
require(['angular','angularRoute', 'mainApp'],
function(angular, angularRoute, app)
{
angular.bootstrap(document, ['ServiceContractModule']);
});
This is my app.js
define(['angular',
'angularRoute',
'AngularApp/services',
'AngularApp/directives',
'AngularApp/controllers'],
function(angular, angularRoute, services, directives, controllers)
{
console.log("sup");
var serviceContractModule = angular.module('ServiceContractModule',[ 'ngRoute', services, directives, controllers ]);
serviceContractModule.config(function($routeProvider,$locationProvider) {
$routeProvider.when('/contractNumber/:contractNumbers', {
controller : 'ContractController',
templateUrl : './contractSearchResult',
reloadOnSearch : true
}).when('/serialNumber/:serialNumbers', {
controller : 'SerialController',
templateUrl : './serialSearchResult'
}).when('/QuoteManager',{
controller : 'QuoteManagerController',
templateUrl: './quoteManagerView'
}).when('/QuoteManagerHome',{
controller : 'QuoteManagerController',
templateUrl: './quoteManagerHome'
});
});
return serviceContractModule;
});
This is my directives.js file
define(['angular',
'AngularApp/Directives/tableOperations',
'AngularApp/Directives/line',
'AngularApp/Directives/listOfValues'],
function(
angular,
tableOperations,
line,
listOfValues)
{
var directiveModule = angular.module('ServiceContractModule.directives');
directiveModule.directive('tableoperations', tableOperations);
directiveModule.directive('line', line);
directiveModule.directive('listOfValues', listOfValues);
return directiveModule;
}
)
And this is my services.js file
define(['angular',
'AngularApp/Services/quoteManagerSearch'],
function(angular, quoteManagerSearch)
{
var serviceModule = angular.module('ServiceContractModule.services');
serviceModule.factory('searchRequestHandler', quoteManagerSearch);
return serviceModule;
}
)
When I run my page, the current error I am getting is
Uncaught TypeError: Cannot read property 'module' of undefined directives.js:14
Uncaught TypeError: Cannot read property 'module' of undefined services.js:5
This seems to be happening on this particular line
var directiveModule = angular.module('ServiceContractModule.directives');
I think for some reason, the angular file is not getting loaded. Although when I run the page, I can see all the js files being loaded in the correct order in chrome.
Any ideas guys? Need quick help! Thanks!
Looking at the sources for Angular, I do not see anywhere that it calls RequireJS' define so you need a shim for it. Add this to your shim configuration:
angular: {
exports: "angular"
}
By the way, the priority field in your configuration is obsolete. Either you use RequireJS 2.x which ignores this field because priority is supported only by RequireJS 1.x. Or you use RequireJS 1.x which would honor priority but would ignore the shim field because shim was introduced in 2.x. My suggestion: use RequireJS 2.x and remove priority.
There are 2 possible problems with your setup:
1. You are bootstrapping angular in your main.js and then loading the dependencies.
2. You should be referencing the dependency using string
So, after removing the angular.bootstrap from your main.js, try the following:
app.js
define([
'AngularApp/services',
'AngularApp/directives',
'AngularApp/controllers'],
function()
{
console.log("sup");
var serviceContractModule = angular.module('ServiceContractModule',[ 'ngRoute', 'ServiceContractModule.services', 'ServiceContractModule.directives', '<<Your Controller Module Name>>' ]);
serviceContractModule.config(function($routeProvider,$locationProvider) {
$routeProvider.when('/contractNumber/:contractNumbers', {
controller : 'ContractController',
templateUrl : './contractSearchResult',
reloadOnSearch : true
}).when('/serialNumber/:serialNumbers', {
controller : 'SerialController',
templateUrl : './serialSearchResult'
}).when('/QuoteManager',{
controller : 'QuoteManagerController',
templateUrl: './quoteManagerView'
}).when('/QuoteManagerHome',{
controller : 'QuoteManagerController',
templateUrl: './quoteManagerHome'
});
});
angular.bootstrap(document, ['ServiceContractModule']);
});
Check out angularAMD that I created to help the use of RequireJS and AngularJS:
http://marcoslin.github.io/angularAMD/