I have the following code which is working fine
var angular = require("angular");
module.exports = angular
.module('controllers', [])
.controller('Topbar', require('../controllers/Topbar'));
But when I change it to the following code such that the require is done by a separate 'utility' function called r which automatically appends the folder name, I am getting errors.
var angular = require("angular");
var r = function (a) {
return require('../controllers/'+ a)
}
module.exports = angular
.module('controllers', [])
.controller('Topbar', r('Topbar'));
Related
I'm new to Jasmine. I've written a simple code to execute in JS Fiddle which is working perfectly fine. But, when I include jasmine code, its not working. Am I missing anything here?
var app = angular.module('sortModule', [])
app.factory('sortFactory', function(){
var sortedColors = []
var shouldPush = true;
return {
sortColors: function(colorsArray){
var colorsOrder = [{color:'green'},{color:'yellow'},{color:'blue'},{color:'red'}]
for(color in colorsOrder) {
for(objColor in colorsArray) {
shouldPush = colorsOrder[color].color === colorsArray[objColor].color ? true : false
if(shouldPush) {sortedColors.push(colorsArray[objColor]);}
}
}
return sortedColors;
}
}
});
app.controller('sortController', function($scope,sortFactory){
$scope.colorsArray = [{id: '1',color: 'red',code : '#ff0000'},{id: '2',color: 'blue',code : '#0000ff'},{id: '3',color: 'red',code : '#ff0000'},{id: '4',color: 'yellow',code : '#ffff00'},{id: '5',color: 'green',code : '#00ff00'}];
$scope.sortedColors = sortFactory.sortColors($scope.colorsArray)
});
describe('colors', function () {
beforeEach(module('sortModule'));
it('can get the actual sorted ordered colors list', inject(function(sortFactory) {
expect(sortFactory).toBeDefined();
}));
});
var NOT_IMPLEMENTED = undefined;
// load jasmine htmlReporter
(function() {
var env = jasmine.getEnv();
env.addReporter(new jasmine.HtmlReporter());
env.execute();
}());
Actual working fiddle without Jasmine
http://jsfiddle.net/SyedNizamChennai/kjuemhua/15/
New fiddle when Jasmine is included
https://jsfiddle.net/SyedNizamChennai/5d4f0hdL/3/
Test code contains module function
beforeEach(module('sortModule'));
This is function from ngMock module, you need include it as external resource.
https://jsfiddle.net/SyedNizamChennai/5d4f0hdL/3/
EDIT:
working example is here:
http://jsbin.com/lenogujesi/1/edit?html,output
(i used jsbin to better show dependencies and their order)
some notes:
if is jasmine loaded, angular mock expose function mock and others as global (see https://docs.angularjs.org/api/ngMock#function), otherwise function is undefined
angular and angular mock should have same version
I am following a tutorial about how to use AngularJS with RequireJs. I don't seem to understand how this works.
The author creates a file app.js and inside the file adds;
define(function (require) {
'use strict';
var angular = require('angular');
var services = require('./services/services');
var controllers = require('./controllers/controllers');
var directives = require('./directives/directives');
var app = angular.module('App', ['services', 'controllers', 'directives']);
app.init = function () {
angular.bootstrap(document, ['App']);
};
...
})
But does not show how the files services.js, controllers.js, and directives.js are structured.
For example in the services file I assume I would have multiple definitions of services. This is a nice structure because it means I can create multiple services or controllers in a single script. The problem I have is to get the services from; var = services into the App.
Nesting or grouping files with require is quite common - so the services/services.js file (which is being required in your app above) could look like:
define(function (require) {
var services = {};
services.service1 = require('services/service1');
services.service2 = require('services/service2');
services.service3 = require('services/service3');
services.service4 = require('services/service4');
services.service5 = require('services/service5');
return services;
});
and then services.service1 would become available within the app.
I have an angular application with some global environment variables defined in an env.js file:
(function(sp) {
'use strict';
pk.env = pk.env || {};
// localhost
pk.env.baseUrl = 'http://localhost:8080/';
})(typeof exports === 'undefined' ? (this.pk = this.pk || {}) : exports);
These variables are used in multiple factories to make REST API calls:
'use strict';
angular.module('pkApp').factory('pkFactory', PKFactory);
function PKFactory($http) {
var urlBase = pk.env.baseUrl;
var apiUrl = 'v1/data';
var _pkFactory = {};
_pkFactory.getData = function() {
return $http.get(urlBase + apiUrl);
};
return _pkFactory;
}
I am writing unit tests for this factory using Jasmine and I keep getting the error:
ReferenceError: Can't find variable: pk
If I remove this variable reference from the factory, the tests run fine.
'use strict';
console.log('=== In pk.factory.spec');
describe('Unit: pkFactory', function() {
beforeEach(module("pkApp"));
var $httpBackend, $rootScope, pkFactory;
beforeEach(inject(function($injector) {
// Set up the mock http service responses
$httpBackend = $injector.get('$httpBackend');
$httpBackend.when('GET', 'v1/data').respond('Not found');
pkFactory = $injector.get('pkFactory');
}));
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it('expects getData method to be defined', function(){
expect(pkFactory.getData()).toBeDefined();
$httpBackend.flush();
});
})
How do I inject value of 'pk.env.baseUrl' into the factory? I have tried using $window, but it didn't work.
As pretty much already answered here, you can also declare a global variable within your test file
var globalVar = "something";
describe('Your test suit', function() {
...
});
and if you are using Karma you can edit the karma.conf.js file to define it
// list of files / patterns to load in the browser
files: [
...,
'file-containing-the-global-variable.js'
],
You should avoid using the globals in Angular completely.
Convert the file to an angular value or constant:
angular.module('pkApp').value('pk', pk);
now you can change pkFactory to get the pk object injected
function PKFactory($http, pk) {
// pk is no longer from global scope, but injected from angular as an argument
var urlBase = pk.env.baseUrl;
var apiUrl = 'v1/data';
var _pkFactory = {};
_pkFactory.getData = function() {
return $http.get(urlBase + apiUrl);
};
return _pkFactory;
}
and in tests, you can now mock the pk to a different value (or not do anything and use the one from code)
I am building a MVC application and using angular and require.js in it.
I have defined my JS files as below.
First JS File:
define(function (require) {
'use strict';
var angular = require('angular');
var app = angular.module('App');
app.service('Service1', function () {
});
});
Second JS File:
define(function (require) {
'use strict';
var angular = require('angular');
var app = angular.module('App');
app.service('Service2', function () {
});
});
In the require js configuration , I gave the path of the script bundle and could see JS files are bundled and minified and is loaded. But we are getting an error "Service2 is not defined".
When i merge the two files or remove "define(function (require)" from the individual files then everything is working fine.
Merged File:
define(function (require) {
'use strict';
var angular = require('angular');
var app = angular.module('App');
app.service('Service1', function () {
});
app.service('Service2', function () {
});
});
First JS File:
'use strict';
var angular = require('angular');
var app = angular.module('App');
app.service('Service1', function () {
});
Second JS File:
'use strict';
var angular = require('angular');
var app = angular.module('App');
app.service('Service2', function () {
});
I cannot merge the files as above since i have huge list of JS files.
I am not 100% sure what would be the impact if i remove "define(function (require)".
What would be best approach to use MVC's bundling and minification feature in my scenario?
Thanks.
The function passed to define does not run until it is required by something else. So your service 2 is not defined error is probably because you haven't explicitly required it.
require(['First', 'Second'], function () {
//Use Service1 and Service2
});
We built a widget app with backbone and require.js. It works cool with one app instance on page. Now we have a new requirement. We need to run multiple widget instances on same page. Each of app will have its own configurations.
The following test code is not working as we expected:
for(var i=0;i<3;i++){
require([ "app" ], function(app) {
var bootstrap = {};
jQueryPB(function() {
app.testData = i;
app.startup();
});
});
}
I wonder how could I instantiate multiple apps and set different configs to them?
Project structure is similar to:
/main.js
require.config({
....
});
/*code to create multiple instances*/
require(["app"], function(app){
var instance = new app(color:"yellow");
var instance2 = new app(color:"red");
instance.render();
instance2.render();
/*want to create multiple instances here to same page*/
})
/*above code is not working, TypeError: app is not a constructor*/
/app.js
define([ "jQueryPB", "backbone", "underscore", "models/app", "views/app" ], function($jpb,
Backbone, _, appModel, appView) {
var appInfo = new appModel();
var app = new appView({
model : appInfo
});
return app;
});
/models/app.js
/views/app.js
/view/bags.js
/view/bag (it references app by var app = require("app") , so that it can access app.color)
/collection/bags
/model/bag
I use r.js to compile all js into one
node r.js -o build.js optimize=none
After main.js is fully downloaded, it would start to initialize different app instances.
=================================================updated code
cool. I tried it with similar way:
main.js
require(["app"], function(app){
var instance = new app({
testData : 1
});
instance.testData = "1";
instance.startup();
})
app.js
define([ "jQueryPB", "backbone", "underscore", "models/app", "views/app" ], function($jpb,
Backbone, _, appModel, appView) {
return function app(color) {
var appInfo = new appModel();
var app = new appView({
model : appInfo
});
console.log(">>"+color.testData);
app.testData = color.testData;
return app;
};
});
a problem is in bag.js, it needs to access the custom variable in app. I use var app = require("app"); console.log(app.testData); But the output is undefined. Is there a different way to access app instance?
In addition, if require("app"), will it cause a problem if there are multiple app instances?
The problem is, require being an asynchronous function, does not execute immediately, and when it finally does execute, the value of i will have changed. Ultimately, you will end up with all your instances sharing the same value of i, as the loop will have completed before the first require callback gets executed. See here.
You can solve this by creating a closure around each iteration of your loop. This way the original value of i is retained within the scope of the require callback.
for (var i = 0; i < 3; i++) {
(function (i) {
require(["app"], function (app) {
// etc
});
})(i);
}