I have two files
test1.js
angular.module("test1",[]).controller("test1Ctrl",function(){
// some code
})
and
test2.js
angular.module("test2",[]).controller("test2Ctrl",function(){
//some code
})
app.js
var app = angular.module("testApp",['test1','test2']);
My question is how I can inject my both controller in app.js from test1.js and test2.js using same module and not using module test1 and test2?
If you want to keep controllers in separate file then,
app.js
var app = angular.module("testApp",[]);
test1.js
app.controller("test1Ctrl",function(){
// some code
})
test2.js
app.controller("test2Ctrl",function(){
// some code
})
Finally include js files in html,
<script src="app.js"></script>
<script src="test1.js"></script>
<script src="test2.js"></script>
Related
Currently trying to check very simple angular variables and functions. I cannot get even the simplest to work. This is my first time using it, and I need to use the older version as my lecturer requires it.
In the app.js I have many controllers but im only starting with one controller, with one variable assigned to a string:
var app = angular.module('myApp', ['ngRoute']);
blah blah blah etc etc
app.controller('HomeController', function ($scope) {
$scope.name = 'Batman';
}
In the runner.html file I have the following:
<script src="lib/jasmine-2.2.0/jasmine.js"></script>
<script src="lib/jasmine-2.2.0/jasmine-html.js"></script>
<script src="lib/jasmine-2.2.0/boot.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src='https://code.angularjs.org/1.4.8/angular-mocks.js'></script>
<!-- include source files here... -->
<script src="../js/main.js"></script>
<!-- include spec files here... -->
<script src="spec/test.js"></script>
In the test.js i have the following:
describe('myApp', function () {
var scope, controller;
beforeEach(angular.mock.module('myApp'));
beforeEach(angular.mock.inject(function($controller,$rootScope){
scope = $rootScope.$new();
$controller('HomeController', {$scope: scope});
}));
it('sets the name', function () {
expect(scope.name).toBe('Batman');
});
});
I then get the following error when I run the test:
Error: [$injector:modulerr]
EDIT
It appears to be the angular routing causing the problem. When I removed the route module 'ngRoute' it appears to function correctly. Is there is method to using jasmine with routing?
The problem with this was you were not having angular-route library included despite having it as a module dependency (angular.module('myApp', ['ngRoute'])).
I added as the following along with other libraries:
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular-route.min.js"></script>
And it's working!
Here's working plunker
I understand that services are the preferred way to get data into an app. However, what it the data is already on the page as js variable. Essentially looking for how you’d do the following with Angular:
var foo = {key1:value2, key2:value2};
myInitFunction( foo );
// This function may be on the page or in an external doc
myInitFunction( foo ){
// Do stuff with foo…
}
Essentially, foo exists on page load as a server-side object already. It seems silly to me to make an Ajax call to get this information (again). Foo could exist elsewhere like:
<span data-foo="{key1:value2, key2:value2}}></span>
If that makes getting the data into my app easier…
An easy way to do it is to store it as a global variable in your index.html for example :
<html>
<head>
<title>Angular QuickStart</title>
<!-- BASIC ANGULAR 2 INDEX HTML -->
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<my-app>Loading...</my-app>
<script>
// Store your value in some global scope variable.
window.foo = {key1:'value2', key2:'value2'};
</script>
</body>
</html>
And then, you can wrap this value in some Angular2 service
#Injectable()
export class FooService {
getFoo() {
return window.foo;
}
}
I assume this span is on your initial html page when you bootstrap your app(main) module, if so then you can do some jquery and assign this value to a global variable. (such as
var meyVar = $('#mySpan').attr('data-foo')
)
and then in your angular component you declare myVar and you can access it.
declare _myVar;
alert(_myvar)
I think the solution would be a custom value provider, then you can use dependency injection with it within your application. Check out:
https://angular.io/docs/ts/latest/guide/dependency-injection.html
In your index.html:
<script>
window.config = {key1:value2, key2:value2};
</script>
And then in your app.module
import { OpaqueToken } from '#angular/core';
export let APP_CONFIG = new OpaqueToken('app.config');
/* ... */
#NgModule({
/* ... */
providers: [{ provide: APP_CONFIG, useValue: window.config }]
})
class AppModule {}
I got this service
angular.module('common.utils', [])
.service('Timer', function () {
function Timer() {
var start = new Date();
return function () {
return (new Date()).getTime() - start.getTime();
};
}
return Timer;
});
And i'm trying to write a simple test for it:
describe('common.utils', function() {
beforeEach(function () {
module('common.utils');
});
it('has a timer service', inject(function(Timer) {
expect(Timer).not.toBeNull();
}));
});
And I keep getting ReferenceError: inject is not defined.
I included angular.js, angular-mocks.js and all the app files (module is working... ). I don't understand what the problem is...
I had the same problem.
It turns out the issue was in the loading order of the files. You have to load jasmine before you load angular-mocks.
The following loading order will be throwing the error as mentioned in the question:
<script src="/bower_components/angular/angular.js"></script>
<script src="/bower_components/angular-mocks/angular-mocks.js"></script>
<script src="/bower_components/jasmine/lib/jasmine-core/jasmine.js"></script>
<script src="/bower_components/jasmine/lib/jasmine-core/jasmine-html.js"></script>
<script src="/bower_components/jasmine/lib/jasmine-core/boot.js"></script>
<!-- include spec files here... -->
<script src="/spec/test.js"></script>
ReferenceError: inject is not defined
In several jasmine examples there is an additional comment included in the code:
<!-- include source files here... -->
The comment helps us to remind to load things in the right order.
<script src="/bower_components/jasmine/lib/jasmine-core/jasmine.js"></script>
<script src="/bower_components/jasmine/lib/jasmine-core/jasmine-html.js"></script>
<script src="/bower_components/jasmine/lib/jasmine-core/boot.js"></script>
<!-- include source files here... -->
<script src="/bower_components/angular/angular.js"></script>
<script src="/bower_components/angular-mocks/angular-mocks.js"></script>
<!-- include spec files here... -->
<script src="/spec/test.js"></script>
My folder structure :
/app
/components
/module1
/module2
/core
/extensions
-array.js
-string.js
/services
-localdataservice.js
/directives
- .... .js
index.html
each file aside from it's essence is associated with an angular module 'app.core'
for example : array.js
(function() {
'use strict';
var core = angular.module(app.core, []);
core.config( function(){
if (!Array.prototype.last){
Array.prototype.last = function(){
return this[this.length - 1];
};
};
})
}());
Composing all of these files and there contents under a usable module as some fallbacks.
1) Only one file can create the module and the rest need to use the module and add on to it.
meaning that all other files then the arbitrarly chosen array.js would use the module as :
var core = angular.app('app.core');
and not
var core = angular.app('app.core',[]);
2) I would have to reference each file from index.html in order for it to take part in the module's initiation.
index.html
<html>
<body>
<script src="components/core/array.js"></script>
<script src="components/core/string.js"></script>
<script src="components/core/localdataserice.js"></script>
.... and many more
</body>
</html>
There must be a better way for building a module across multiple files.
at first i thought about copying all of the contents of the files under a seperate file
/app
/components
/core
/lib
-core.js
index.html
<html>
<body>
<script src="components/core/lib/core.js"></script>
</body>
</html>
I thought of doing this with a grunt copy task. but that would require me to somehow manipulate the process of the copy task the fit content under the IFFE wrapper and the angular's module initiation.
(function() {
'use strict';
var core = angular.module(app.core, []);
core.config( function(){
... ALL THE FILES CONTENTS GO HERE
})
}());
And again there's gotta be a better way.
any suggestions ?
EDIT :
I decided to try Browserify along with Grunt and grunt-browserify
Gruntfile.js
grunt.initConfig({
browserify :{
main: {
src: 'app/components/core/{,*/}*.js',
dest: 'app/components/core/lib/core'
}
}
});
For this example the build file only has the content of array.js
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
if (!Array.prototype.last){
Array.prototype.last = function(){
return this[this.length - 1];
};
};
},{}]},{},[1]);
1) What i don't understand is how can i incorporate an export function in it.
since i wan't to require it from other modules.
module.exports = function() {
// Your code
}
2) Iv'e seen no reference in any tutorials on that weird looking wrapper my code was placed in. not sure what it does maybe it as an export in there some where :/
Let's say, I have HTML like this
<html ng-app='CoreAngular_App'>
<script>
var CoreAngular_AppObj = angular.module('CoreAngular_App', ['importantModule1', 'importantModule2', 'customModule1', 'customModule2', 'customModule3']);
</script>
<!-- here goes html structure with lot of ng-controller -->
<script>
//controller example
CoreAngular_AppObj.controller('MyControllerX', function($scope, myCustomModule2) {
}
</script>
</html>
It works, but as I have a lot of controllers and I don't know which of them will used, I want to load this list ['customModule1', 'customModule2', 'customModule3'] dynamically
I will glad to get something like this.
<html ng-app='CoreAngular_App'>
<script>
var CoreAngular_AppObj = angular.module('CoreAngular_App', ['importantModule1', 'importantModule2']);
</script>
<!-- here goes html structure with lot of ng-controller -->
<script>
// ADD myCustomModule2 TO CoreAngular_AppObj HERE
//controller example
CoreAngular_AppObj.controller('MyControllerX', function($scope, myCustomModule2) {
}
</script>
</html>
Is it possible? And how?
Thanks
I'll try to make an example of what either may look like.
Inline - from backend logic -
// Create list from rendered array.
var modules = ['customModule1', 'customModule3']; // ex: print json_encode($arrayStr);
// Add a custom module
angular.module('myCustom', modules);
//Inject the custom module
angular.module('CoreApp', ['importantModule1', 'importantModule2', 'myCustom']);
angular.bootstrap docs
Remember to remove ng-app
var app = angular.module('CoreApp', []);
someReadyFunction(){
// figure out which moules here
angular.bootstrap(document, ['CoreApp', 'customModule1', 'customModule3']);
}