Marek Matczak, Jarosław Fuczko, Tomasz Szewców
You can think of a module as a container for the different parts of your app – controllers, services, filters, directives, etc.
// define a module without dependencies
angular.module('moduleName', []);
// define a module with dependencies
angular.module('moduleName', ['dependency1', 'dependency2']);
// retrieve a module
angular.module('moduleName');
Dependency Injection (DI) is a software design pattern that deals with how components get hold of their dependencies.
The Angular injector subsystem is in charge of creating components, resolving their dependencies, and providing them to other components as requested.
angular.module('moduleName').controller('SomeController', function($scope, someService){
'use strict';
// add something to injected $scope
$scope.data = {};
// call injected service method
someService.someMethod();
};
angular.module('someModule').controller('MyFirstController', function($scope){
'use strict';
$scope.helloWorld = 'hello world!';
alert($scope.helloWorld);
});
<!DOCTYPE html>
<html>
<body>
<section data-ng-controller="MyFirstController">
<h2>Hello from Dialog A!</h2>
</section>
</body>
</html>
angular.module('someModule').controller('MyFirstController', function($scope){
'use strict';
var cntl = this;
this.helloWorld = 'hello world!';
alert(this.helloWorld);
});
<!DOCTYPE html>
<html>
<body>
<section data-ng-controller="MyFirstController as cntl">
<h2>Hello from Dialog A!</h2>
<span>{{cntl.helloWorld}}</span>
</section>
</body>
</html>
angular.module('someModule').service('myService', function(){
'use strict';
this.print = function(){
alert('hello world from a service');
};
});
angular.module('someModule').factory('myService2', function(){
'use strict';
var helloWorld = 'hello world from a service2';
return {
print: function(){
alert(helloWorld);
}
};
});
myForm: { //form name
fistName:{}, //input name
lastName:{}, //input name
email:{} //input name
}
myForm: { //form name
$dirty: false, $pristine: true, //dirty or pristine
$valid: false, $invalid: true, //valid or invalid
fistName: { //input name
$dirty: false, $pristine: true, //dirty or pristine
$valid: false, $invalid: true, //valid or invalid
$error: { //validation for field
required: true, //required validation
minlength: false //minlength validation
}
},
email: {} //input name
}
Branch with fallback solution when exercise 1 not done: step-2-first-controller
Branch with fallback solution when exercise 2 not done: step-3-forms
// Simple GET request example:
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
// shortcut methods
$http.get('/someUrl', config).then(successCallback, errorCallback);
$http.post('/someUrl', data, config).then(successCallback, errorCallback);
Branch with fallback solution when exercise 3 not done: step-4-edit-modal
Branch with fallback solution after exercise 4:
step-5-backend-communication
describe('A suite', function() {
it('contains spec with an expectation', function() {
expect(true).toBe(true);
});
});
// install Karma
npm install karma
// install plugins
npm install karma-jasmine
npm install karma-phantomjs-launcher
npm install karma-chrome-launcher
// run Karma
./node_modules/karma/bin/karma start / init / run
// alternative
npm install -g karma-cli
karma start / init / run
// can be created with karma init command
module.exports = function (config) {
config.set({
basePath: '',
frameworks: [],
files: [],
hostname: 'localhost',
port: 9876,
autoWatch: false,
browsers: [],
singleRun: false,
})
};
// for debugging in a browser:
// - set single run to true
// - select other browser
http://karma-runner.github.io/0.8/config/configuration-file.html
describe('SampleCntl tests', function() {
'use strict';
var $scope;
beforeEach(module('someModule'));
beforeEach(inject(function($controller, $rootScope){
$scope = $rootScope.$new();
$controller('SampleCntl', {$scope: $scope});
}));
describe('some suite', function() {
it('some spec', function() {
// given
// when
$scope.someMethod();
// then
});
});
});
describe('SampleCntl tests', function() {
'use strict';
var cntl;
beforeEach(module('someModule'));
beforeEach(inject(function($controller){
cntl = $controller('SampleCntl', {});
}));
describe('some suite', function() {
it('some spec', function() {
// given
// when
cntl.someMethod();
// then
});
});
});
// sample controller code
angular.module('someModule').controller('SomeCntl', function($scope, $location){
'use strict';
$scope.goToDialog = function(path){
$location.path(path);
}
});
// test code
var $scope, locationMock = {
path: angular.noop
};
beforeEach(inject(function($controller, $rootScope){
$scope = $rootScope.$new();
// injection of mocked $location service
$controller('SomeCntl', {$scope: $scope, $location: locationMock});
}));
describe('data service tests', function () {
'use strict';
var someDataService;
beforeEach(module('app'));
beforeEach(inject(function (_someDataService_) {
someDataService = _someDataService_;
}));
describe('get data method', function () {
it('should return data', function () {
// given
var data = [];
// when
data = someDataService.getData();
// then
expect(data.length).toEqual(10);
});
});
});
// sample service code
angular.module('someModule').factory('serviceUnderTests', function('otherService'){
'use strict';
var data = [];
return {
getData: function(){
angular.copy(otherService.getData(), data);
},
getCurrent: function(){
return data;
}
};
});
// test code
var otherServiceMock = {getData: function(){return [1,2,3]}};
var serviceUnderTests;
beforeEach(function(){
module('someModule');
module(function($provide){
// injecting other service with $provide service
$provide.value('otherService', otherServiceMock);
);
});
beforeEach(function(_serviceUnderTests_){
serviceUnderTests = _serviceUnderTests_;
});
var booksData, $httpBackend;
beforeEach(inject(function (_booksData_, _$httpBackend_) {
booksData = _booksData_;
$httpBackend = _$httpBackend_;
}));
afterEach(function () {
// then
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it('should load books', function () {
// given
var searchParams = {title: 'title', author: 'author'}, books = [], response = [
{id: 0, title: 'title1'},
{id: 1, title: 'title2'}
];
$httpBackend.expectGET('/books-management/books-list/books.json?author=author&title=title').respond(response);
// when
booksData.getBooks(searchParams).then(function (response) {
books = response.data;
});
$httpBackend.flush();
// then
expect(books).toEqual(response);
});
Fallback branches for exercies 5 and 6:
step-6-testing-controller
step-7-testing-service