Upload
linkme-srl
View
891
Download
0
Embed Size (px)
Citation preview
AngularJs Intermediate
Who we are
Daniele Bertella@_denb
Gianfranco Garipoli@gianfra__
LinkMe SRL@LinkMeSRL
Target
People who have already some experience with angular and wanted to see more feature.
Topics
● Integration with RESTful API● Code modularization● Client side validations● Custom directive● Testing
Slack - Join us on MEAN milan
If you are not there already: http://meanmilan.herokuapp.com/
https://meanmilan.slack.com/
Ninja time!
https://github.com/linkmesrl/ngIntermediate
What we are going to do
What is it?
Back end: Node.js + Express + MongoDb
Front end: Angular Js
1° Lesson
$http, $resource
Angular $http
Angular $http - shortcut
Angular $http - in the service
Angular $http - in controller
Ok let’s go $resource
$resource - Usage
$resource(url, [paramDefaults], [actions], options);
https://docs.angularjs.org/api/ngResource/service/$resource
$resource - Let’s create the model
$resource
Each of the model instances will have methods, which could be used for the different CRUD operation. In one line of code.
It’s not free! ngResource should be installed in your app
$resource - Default method
'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'}
$resource - How to use it - Query
// Get allvar ninjas = Ninja.query();
$resource - How to use it - Get
// get singleNinja.get({ id: 1}, function (ninja) {...});
// get single using $promiseNinja.get({ id: 1}).$promise.then(...);
$resource - Handling returned data
// $save, $remove ($delete)ninja.$save();ninja.$remove();
Let’s code
● Create a service to incapsulate the $resource
● Create 2 controllers to handle the requests
● Connect the views with their controllers
$resource - wrap it into a service
.service('Ninja', function($resource){ var Ninja = $resource('http://192.168.105.130:3000/api/ninja/:_id', {_id: '@_id'}); return Ninja;});
$resource - Controller, load ninjas and go on
.controller('NinjaCtrl', function($scope, Ninja){$scope.ninjas = [];
// TODO GetAll, CreateNew, Update, Delete $scope.loadNinja = function(){ $scope.ninjas = Ninja.query(); };
...});
$resource - Custom methods
{
action1: {method:?, params:?, isArray:?, headers:?, ...},
action2: {method:?, params:?, isArray:?, headers:?, ...},
...
}
$resource - Custom method example
var Ninja = $resource('http://127.0.0.1:3000/api/ninja/:_id', {_id: '@_id'}, {
count: {method:'GET', url: 'http://127.0.0.1:3000/api/ninja/count'}});
// our custom method is mapped as well.
Ninja.count();
2° Lesson
form validation, directive
Let’s use the built in Angular form validation
ngForm - validation
http://codepen.io/sevilayha/full/xFcdI/
ngForm - validation - Property | classes
● $valid | .ng-valid● $invalid | .ng-invalid● $pristine | .ng-pristine● $dirty | .ng-dirty● $touched | .ng-touched
ngForm - validation - Other properties
● $submitted● $error
With $error property we can target every different errors in the form:
myForm.$error.requiredmyForm.$error.minlengthmyForm.$error.maxlength
ngForm - validation - access properties
● formName.propertyex: “createForm.$valid”
● formName.inputName.propertyex: “createForm.age.$pristine”
ngForm - input directive (with ng-model)
https://docs.angularjs.org/api/ng/directive/input
ngForm - custom errors
Directives
Directives makes HTML interactive by attaching event listeners to elements and/or transforming the DOM.
Angular directive
● ng-model● ng-repeat● ng-show
<input ng-model=”name” /><div ng-repeat=”item in items”></div>
Angular custom directive
<ng-intermediate />or
<div ng-intermediate></div>
simple object configuration
● no scope => parent’s scope.● scope: true => child scope● scope: {} => isolated scope
With isolate scope:● @ => Attribute string binding● = => Two-way model binding● & => Callback method binding
directive scope
directive scope example
<ng-intermediate cheering=”{{hello}}” name=”class” />
directive isolated scope explained
● @ binding is for passing strings. These strings support {{}} expressions for interpolated values.
For example: . The interpolated expression is evaluated against directive's parent scope.
● = binding is for two-way model binding. The model in parent scope is linked to the model in the
directive's isolated scope. Changes to one model affects the other, and vice versa.
● & binding is for passing a method into your directive's scope so that it can be called within your
directive. The method is pre-bound to the directive's parent scope, and supports arguments. For
example if the method is hello(name) in parent scope, then in order to execute the method from
inside your directive, you must call $scope.hello({name:'world'})
directive link function
The link function is mainly used for attaching event listeners to DOM elements, watching model properties for changes, and updating the DOM.
directive link function attributes
● scope – The scope passed to the directive. ● el – The jQLite (a subset of jQuery) wrapped
element on which the directive is applied. ● attr – An object representing normalized
attributes attached to the element on which the directive is applied.
directive link function example
directive require
Directive Definition Object
● https://docs.angularjs.org/api/ng/service/$compile
● https://docs.angularjs.org/guide/directive
Let’s build our custom validation
Register a custom directive
Configure our custom directive
Add the validation logic
3° Lesson
Modularization Path to Angular 2
What is a Module?
You can think of a module as a container for the different parts of your app
Let’s modularize the app
App structure - Angular 1.x
App structure - Angular > 1.3
Ideas?
Let’s modularize the app
ninja-list
ninja-tile
ninja-handle
Let’s start by creating component as a directive.
We will use directive definition object where we declare controller, controllerAs, templateUrl, and bindToController properties.
Directive Definition Object
https://docs.angularjs.org/guide/directive
ControllerAs
ControllerAs syntax enables controller to live and do their job without being bound (only) on $scope.
bindToController (new in Angular 1.3.X)
When used, properties from isolated scope will be automatically bound to controller’s this.
Example
Let’s do it together
Exercise App structure
Exercise ninja.module.js
Exercise <ninja-list>
● Create a new module with a new routing● Create one component for every part of the app● Every component should have one controller
and one view
Exercise
4° Lesson
test test test
Testing Theory
What tests are?
Automated software testing
is a process in which software tools
execute pre-scripted tests
on a software application
before it is released into production.
Tests Typologies
Unit Tests
A unit test is an automated piece of code that invokes a unit of work in the system and then checks a single assumption about the behavior of that unit of work.
➔ Has full control over all the pieces running (Use mocks)
➔ Can be run in any order if part of many other tests
➔ Runs in memory (no DB or File access, for example)
➔ Consistently returns the same result
➔ Tests a single logical concept in the system
➔ Readable and Maintainable
End to End Tests
End-to-end testing is a methodology used to test whether the flow of an application is performing as designed from start to finish.
➔ Use the real code (no mocks)
➔ Test Integration between components
➔ Test a workflow (eg: Registration, Profile Update, …)
➔ Run in a real Environment
What to be tested?
Unit Tests
➔ Complex Algorithm
➔ Shared Functions
➔ Core Functions
E2E Tests
➔ Complex Workflows
➔ Business Value
➔ Smoke Test
Angular Testing Toolset
Unit Tests
➔ Karma
➔ Jasmine
➔ ngMock, $inject, $template
E2E Tests
➔ Protractor
➔ Jasmine
How test are structured
A suite that describe what is going to be tested
Some specs that verify a behaviour
Some expectations that assert a result
Setup and Cleanup before and after each test
How test are structured
Suites - Describe
Describe blocks:
➔ Used to wrap spec from the same component➔ Can be nested➔ Should be verbose➔ Can be skipped (xdescribe)
Spec - It
It blocks:
➔ Used to wrap expectations for the same unit➔ Can NOT be nested➔ Should be verbose➔ Can be skipped (xit)➔ Should test only one behaviour
Setup and Cleanup
before, beforeEach, after, afterEach blocks:
➔ Used to setup/cleanup the test environment➔ Mock the data➔ Mock external Unit➔ Mock the backend➔ Can NOT be nested
Let’s test our components
Our modularized app
ninja-list
ninja-tile
ninja-handle
Getting StartedUnit Tests - Environment Setup
Setting up Karma Environment
In order to execute Unit Tests we need:
➔ A test runner (Karma)➔ An assertion library (Jasmine)➔ A browser in which run the tests (PhantomJs)➔ A configuration File➔ One spec (at least)➔ A script to run the test (npm test)
Setting up Karma Environment
npm install
jasmine-core
karma
karma-jasmine
karma-mocha-reporter karma-ng-html2js-preprocessor karma-phantomjs-launcher
phantomjs
--save-dev
Karma CLI
Optionally Install:
npm install -g karma-cli
Then, you can run Karma simply by karma from anywhere
and it will always run the local version.
Karma Configuration File
By default the configuration file is called:
karma.conf.jshttp://karma-runner.github.io/0.8/config/configuration-file.html
karma init is an helper to generate this file
Karma Configuration File
What’s inside:➔ Base path: path that will be used to resolve all patterns
➔ Assertion framework: (Jasmine) complete list here
➔ Files to be loaded: Spec and application files
➔ Browser: Test environment
➔ Preprocessors*: Babel, Html2js, ...
➔ Reporters: Formatter for the test output (Mocha)
Npm Test
It’s a common practice to define a script called:
npm test
"scripts": {"test": "karma start"}
Exercise
ninja-list -> What to test?
● Variable in scope
● Function in scope
● Html render
ninja-list -> show me the code
$httpBackend
Fake HTTP backend implementation suitable for unit testing applications that use the $http service.
https://docs.angularjs.org/api/ngMock/service/$httpBackend
$httpBackend -> How we use it
var serverMock = [{'age': 55, 'name': 'Daniele', '_id': '0'}, {'age': 35, 'name': 'Marco', '_id': '1'}];
Flushing HTTP requests
flush() method, allows the test to explicitly flush pending requests. This preserves the async api of the backend, while allowing the test to execute synchronously.
ninja-list (beforeEach) final
The end
questions?
Thanks
Daniele Bertella@_denb
Gianfranco Garipoli@gianfra__
LinkMe SRL@LinkMeSRL
Links
*** If you are not there already: http://meanmilan.herokuapp.com/
● http://linkme.it/
● https://github.com/linkmesrl/ngIntermediate
● https://meanmilan.slack.com/ ***