Angular JS és un framework javascript per al desenvolupament d'aplicacions web (web apps) de tipus client-side. Descripció alternativa:
A client-side Javascript framework for adding interactivity to HTML.
AngularJS, commonly referred to as Angular, is an open-source web application framework maintained by Google and a community of individual developers and corporations to address many of the challenges encountered in developing single-page applications (SPA). Its goal is to simplify both development and testing of such applications by providing a framework for client-side model–view–controller (MVC) architecture, along with components commonly used in rich Internet applications.
The library works by first reading the HTML page, which has embedded into it additional custom tag attributes. Those attributes are interpreted as directives telling Angular to bind input or output parts of the page to a model that is represented by standard JavaScript variables. The values of those JavaScript variables can be manually set within the code, or retrieved from static or dynamic JSON resources.
Vegeu SPA
Comparació entre el Data Binding clàssic i el two-way databinding de Angular:
https://docs.angularjs.org/guide/databinding
Basic example:
https://egghead.io/lessons/angularjs-binding
In Angular, a Controller is a JavaScript constructor function that is used to augment the Angular Scope.
When an Angular Controller is attached to the DOM via the ng-controller directive, Angular will instantiate a new Controller object, using the specified Controller's constructor function. A new child scope will be available as an injectable parameter to the Controller's constructor function as $scope.
Use controllers to:
Do not use controllers to:
Controllers are the 'glue' of an AngularJS application. They connect your markup with your data and act as a sort of switchboard. This video is going to take a look at Controllers and introduce the $scope, building on the Binding video.
https://egghead.io/lessons/angularjs-controllers
Resources:
Scope as Data-model:
Scope is the glue between application controller and the view. During the template linking phase the directives set up $watch expressions on the scope. The $watch allows the directives to be notified of property changes, which allows the directive to render the updated value to the DOM.
Both controllers and directives have reference to the scope, but not to each other. This arrangement isolates the controller from the directive as well as from the DOM. This is an important point since it makes the controllers view agnostic, which greatly improves the testing story of the applications.
Resources:
Vegeu SOLID and Depency Injection. Els serveis són similars i tenen el mateix objectiu que a Laravel vegeu Laravel Service Container.
Exemple:
https://egghead.io/lessons/angularjs-sharing-data-between-controllers
Instal·lació bàsica utilitzant CDN:
<!doctype html> <html ng-app> <head> <title>My Angular App</title> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script> </head> <body> </body> </html>
Resources:
<!DOCTYPE html> <html lang="en" ng-app> <head> <meta charset="UTF-8"> <title>Ej Hola Mundo desarrollado en AngularJS</title> </head> <body> <h1>Hola {{nombre}}</h1> <form> ¿Cómo te llamas? <input type="text" ng-model="nombre"> </form> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> </body> </html>
Vegeu el JSFiddle:
http://jsfiddle.net/acacha/yh5m0wL7/
I vegeu com ho faríem amb Jquery:
http://jsfiddle.net/acacha/1ruyo5gy/3/
Resources:
https://www.airpair.com/angularjs/posts/jquery-angularjs-comparison-migration-walkthrough
El sistema de plantilles Blade de [[Laravel] i el sistema de plantilles d'AngularJS xoquen al utilitzar tots dos:
{{}}
La opció més senzilla per barrejar els dos sistemes és canviar AngularJS com s'explica a:
http://www.codetutorial.io/laravel-5-angularjs-tutorial/
Bàsicament al controlador Angular:
var app = angular.module('todoApp', [], function($interpolateProvider) { $interpolateProvider.startSymbol('<%'); $interpolateProvider.endSymbol('%>'); });
Aleshores Angular utilitzarà:
<% %>
Data-binding:
https://egghead.io/lessons/angularjs-binding
Gamification amb badges:
http://campus.codeschool.com/courses/shaping-up-with-angular-js/intro
http://stackoverflow.com/questions/14994391/thinking-in-angularjs-if-i-have-a-jquery-background
See Ionic
Basat en:
https://github.com/kriskowal/q
Resources:
S'utilitza el servei http per tal de fer peticions Ajax amb Angular. Aquest és servei és un servei core d'Angular i facilita la obtenció de recursos remots utilitzant el protocol HTTP i l'objecte XMLHttpRequest dels navegadors. També suporta JSONP.
NOTA: Vegeu l'apartat següent per a veure el servei $resource un servei de més alt nivell relacionat amb recursos remots via crides REST a APIs remotes.
El servei $http es basa en l'API deferred/promise exposada pel servei $q (Jquery, vegeu Jquery Ajax també es basa en deferred/promise ).
Vegeu un exemple:
// Simple GET request example : $http.get('/someUrl'). success(function(data, status, headers, config) { // this callback will be called asynchronously // when the response is available }). error(function(data, status, headers, config) { // called asynchronously if an error occurs // or server returns response with an error status. }); // Simple POST request example (passing data) : $http.post('/someUrl', {msg:'hello word!'}). success(function(data, status, headers, config) { // this callback will be called asynchronously // when the response is available }). error(function(data, status, headers, config) { // called asynchronously if an error occurs // or server returns response with an error status. });
Quasevol codi de resposta HTTP entre 200 i 299 es considera un success la resta són error. Cal tenir en compe que si la resposta és una redirecció HTTP l'objecte XMLHttpRequest seguirà la redirecció i per tant no és normal que ens torni codis de resposta de redirecció (300).
Shortcut methods
$http.get('/someUrl').success(successCallback); $http.post('/someUrl', data).success(successCallback);
Complete list:
$http.get $http.head $http.post $http.put $http.delete $http.jsonp $http.patch
El valor que retorn la crida a $http és una promise i per tant i podem registrar callbacks als quals se'ls hi passa un objecte que representa la resposta HTTP:
TODO
Testing
Per a les proves Unit Testing s'utilitza $httpBackend mock. Un exemple utilitzant ngMock i $httpBackend.flush():
$httpBackend.expectGET(...); $http.get(...); $httpBackend.flush();
Vegeu també l'article AJAX
Resources:
Vegeu $resource
Resources
REST API Laravel + (Laravel + Angular) web client. S'utilitza $http service:
http://www.codetutorial.io/laravel-5-angularjs-tutorial/
REST API Laravel + Angular Standalone web client
http://www.codetutorial.io/laravel-5-and-angularjs-tutorial-reloaded-part-1/ http://www.codetutorial.io/laravel-5-and-angularjs-tutorial-reloaded-part-2/ https://github.com/andbet39/poolAppTutorial
Vegeu també Bootstrap i:
https://github.com/angular-ui/bootstrap
Podeu veure un exemple d'ús a la plantilla sidemenu de Ionic
S'utilitza ng-view per a definit un template i treballar amb una SPA que anirà canviant la part central de la nostra aplicació:
<!DOCTYPE html> <html> <head> <!--Angulare --> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular-route.js"></script> <!--Applicazione --> <script src="js/app.js"></script> <script src="js/controller/PoolController.js"></script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"> </head> <body ng-app="poolApp"><div class="container-fluid"> <ng-view></ng-view></div> </body> </html>
El fitxer principal de l'aplicació Angular (app.js) només mapeja les routes a controladors i vistes:
var app = angular.module('poolApp',['ngRoute']); app.config(['$routeProvider', function($routeProvider) { $routeProvider. when('/admin', { templateUrl: 'js/view/admin.html', controller: 'adminController' }). when('/view', { templateUrl: 'js/view/list.html', controller: 'poolController' }). otherwise({ redirectTo: '/view' }); }]);
Com podeu veure hi ha dos controladors cadascú amb el seu template. A la carpeta view els controllers:
admin.html:
<div class="row"> <div class="col-md-3"> <div class="panel panel-default"> <div class="panel-heading"><h3>Pool Admin</h3></div> <div class="panel-body"> <input type="text" ng-model="newpool.title"> <button class="btn btn-primary" type="button" ng-click="addPool()">Add Pool</button> <div class="row"> <a href="#/view" class="thumb"><button class="btn btn-primary" type="button">List</button></a> </div> </div> </div> </div> <div class="col-md-3" ng-repeat="pool in pools"> <div class="panel panel-default"> <div class="panel-heading"><h3>{{pool.title}}</h3> <button class="btn btn-danger" type="button" ng-click="removePool(pool)">Remove </button></div> <div class="panel-body"><table class="table table-striped"> <tr ng-repeat='option in pool.pooloptions'> <td>{{ option.title }}</td> <td><button class="btn btn-danger" type="button" ng-click="removeOption(option,pool)">Remove </button></td> </tr></table> <tr><td> <input type="text" ng-model="newoption.title" name="title"> </td> <td> <button class="btn btn-primary" type="button" ng-click="addOption(pool,newoption)">Add Opt</button> </td> </tr> </table> </div> </div> </div> </div>
list.html:
<div class="row"> <a href="#/admin" class="thumb"><button class="btn btn-primary" type="button">Admin</button></a> </div> <div class="row"> <div class="col-md-3" ng-repeat="pool in pools"> <div class="panel panel-default"> <div class="panel-heading"><h3>{{pool.title}}</h3></div> <div class="panel-body"><table class="table table-striped"> <tr ng-repeat='option in pool.pooloptions'> <td>{{ option.title }}</td> <td><button class="btn btn-primary" type="button" ng-click="addVote(option)"> Vote <span class="badge">{{ option.vote }}</span> </button></td> </tr> </table> </div> </div> </div> </div>
I els controladors a la carpeta controllers (al mateix fitxer PoolController.js):
app.controller('poolController', function($scope, $http) { $scope.pools = []; $http.get('/api/pool'). success(function(data, status, headers, config) { $scope.pools = data; }); $scope.addVote = function(pooloptions) { $http.get('/api/pooloption/addvote/' + pooloptions.id). success(function(data, status, headers, config) { pooloptions.vote++; }); } }); app.controller('adminController', function($scope, $http) { $scope.pools = []; $scope.newpool = { }; $http.get('/api/pool'). success(function(data, status, headers, config) { $scope.pools = data; }); $scope.addPool = function() { $http.post('/api/pool', $scope.newpool). success(function(data, status, headers, config) { data.pooloptions=[]; $scope.pools.push(data); $scope.newpool.title=""; }); } $scope.removePool = function(pool) { $http.delete('/api/pool/' + pool.id). success(function(data, status, headers, config) { for (index = 0; index < $scope.pools.length; ++index) { if ($scope.pools[index].id == pool.id) { $scope.pools.splice(index, 1); } } }); } $scope.addOption = function(pool,newoption) { newoption.pool_id=pool.id; $http.post('/api/pooloption', newoption). success(function(data, status, headers, config) { pool.pooloptions.push(data); newoption.title=''; }); } $scope.removeOption = function(pooloptions, pool) { $http.delete('/api/pooloption/' + pooloptions.id). success(function(data, status, headers, config) { for (index = 0; index < pool.pooloptions.length; ++index) { if (pool.pooloptions[index].id == pooloptions.id) { pool.pooloptions.splice(index, 1); } } }); } });
Resources:
Veeu Angular REST
http://www.codetutorial.io/laravel-5-angularjs-tutorial/ https://github.com/acacha-org/todoApp
http://www.codetutorial.io/laravel-5-angularjs-tutorial/ https://github.com/acacha-org/todoApp