en el CIPFP Mislata (Valencia)
¿Por qué no aparece JQuery?
JQuery no es un framework es una librería para manejar el DOM
y vamos a seguir usándola pero desde AngularJS
En AngujarJs lo importante es el modelo
var app = angular.module('app', []);
function MainCtrl($scope) {
$scope.nombre="Lorenzo";
}
app.controller('MainCtrl', MainCtrl);
app.js
index.html
<html ng-app="app">
<head>
<script src="angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div>
Mi nombre es:{{nombre}}
</div>
</body>
</html>
$scope.miModelo={
prop1:'valor1',
prop2:'valor2'
}
Siempre debería haber un "." en el HTML al acceder al $scope
index.html
<html ng-app="app">
<head>
<script src="angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div>
<input ng-model="nombre" >
Mi nombre es:{{nombre}}
</div>
</body>
</html>
"Two-way data binding"
var modelo={
nombre:"Lorenzo",
apellidos:"Diaz Ortega",
direccion: {
localidad:"Valencia",
calle:"Las barcas"
numero:4
}
}
function MainCtrl($scope) {
$scope.nombre="Lorenzo";
$scope.$watch("nombre",function(newNombre,oldNombre) {
alert("El nuevo nombre es:" + newNombre);
});
$scope.cambiarNombre=function() {
$scope.nombre="Juan";
}
}
El método $watch avisa de cambios en el modelo
La función "cambiarNombre" no tiene que avisar de lo que cambia.
$("#menu").on('click', function() {
$scope.nombre="Juan"
});
Este código no funciona a menos que avises a AngularJS
Es un problema con páginas con muchísimos datos a mostrar: Scrolls Infinitos
<html ng-app="app">
<head>
<script src="angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div>
<input ng-model="nombre" >
Mi nombre es {{::nombre}}
</div>
</body>
</html>
Solución con Angular 1.3: One-way data binding
El campo "nombre" ya no se actualiza si hay nuevos cambios
function MainCtrl($scope) {
$scope.nombre="Lorenzo";
$scope.cambiarNombre=function() {
$scope.nombre="Juan";
}
}
<body ng-controller="MainCtrl">
<div>
<input ng-model="nombre" >
Mi nombre es {{nombre}}
<button ng-click="cambiarNombre()">Cambiar Nombre</button>
</div>
</body>
function MainCtrl($scope) {
$scope.nombre="Lorenzo";
$scope.cambiarNombre=function() {
$scope.nombre="Juan";
}
}
<body ng-controller="MainCtrl">
<div>
<input ng-model="nombre" >
<div ng-show="nombre=='Juan'">Mi nombre es {{nombre}}</div>
<button ng-click="cambiarNombre()">Cambiar Nombre</button>
</div>
</body>
function MainCtrl($scope) {
$scope.nombre="Lorenzo";
$scope.cambiarNombre=function() {
$scope.nombre="Juan";
}
}
<body ng-controller="MainCtrl">
<div>
<input ng-model="nombre" >
<div ng-hide="nombre=='Juan'">Mi nombre es {{nombre}}</div>
<button ng-click="cambiarNombre()">Cambiar Nombre</button>
</div>
</body>
function MainCtrl($scope) {
$scope.nombre="Lorenzo";
$scope.cambiarNombre=function() {
$scope.nombre="Juan";
}
}
<body ng-controller="MainCtrl">
<div>
<input ng-model="nombre" ng-disabled="nombre=='Juan'" >
Mi nombre es {{nombre}}
<button ng-click="cambiarNombre()">Cambiar Nombre</button>
</div>
</body>
function MainCtrl($scope) {
$scope.usuarios = [
{
idUsuario:34,
nombre:"Juan",
ape1:"Gonzalez"
},
{
idUsuario:46,
nombre:"Ana",
ape1:"Morales"
},
{
idUsuario:62,
nombre:"Sara",
ape1:"Diaz"
},
{
idUsuario:18,
nombre:"Marcos",
ape1:"Ortega"
}
]
}
<body ng-controller="MainCtrl">
<table>
<tr>
<th>Nombre</th>
<th>Apellido</th>
</tr>
<tr ng-repeat="usuario in usuarios">
<td>{{usuario.nombre}}</td>
<td>{{usuario.ape1}}</td>
</tr>
</table>
</body>
function MainCtrl($scope) {
$scope.usuarios = [
{
idUsuario:34,
nombre:"Juan",
ape1:"Gonzalez"
},
{
idUsuario:46,
nombre:"Ana",
ape1:"Morales"
},
{
idUsuario:62,
nombre:"Sara",
ape1:"Diaz"
},
{
idUsuario:18,
nombre:"Marcos",
ape1:"Ortega"
}
]
$scope.usuarioSeleccionado=null;
}
<body ng-controller="MainCtrl">
<p>
Selecciona un usuario:
<select
ng-model="usuarioSeleccionado"
ng-options="usuario as usuario.nombre for usuario in usuarios"
>
<option value="">-- Selecciona un usuario --</option>
</select>
</p>
<p>
El usuario seleccionado es:
{{usuarioSeleccionado.nombre}} {{usuarioSeleccionado.ape1}}
</p>
</body>
JQuery lo puedes seguir usando dentro de tus directivas
*: A veces pueden modificar el DOM para ventanas modales, notificaciones, etc.
constant
value
factory
service
provider
function Login() {
var logged=false;
this.login=function(user,password) {
if ((user==="foo") && (password==="bar")) {
logged=true;
}
return logged;
}
this.isLogged=function() {
return logged;
}
}
app.service("login",Login);
app.service("login",Login); //Es la clase del Singleton
app.value("login",new Login()); //Es el objeto Singleton
app.factory("login",function() { //Es una función que crea el Singleton
return new Login()
});
function Login() {
var logged=false;
this.login=function(user,password) {
if ((user==="foo") && (password==="bar")) {
logged=true;
}
return logged;
}
this.isLogged=function() {
return logged;
}
}
app.service("login",Login);
app.value("defaultUserPassword",{
user:"foo",
password:"bar"
});
function Login(defaultUserPassword) {
var logged=false;
this.login=function(user,password) {
if ((defaultUserPassword.user===user) &&
(defaultUserPassword.password===password)) {
logged=true;
}
return logged;
}
this.isLogged=function() {
return logged;
}
}
Las dependencias son parámetros del constructor
Login.$inject=['defaultUserPassword'];
function Login(defaultUserPassword) {
}
app.service("login",Login);
$inject es un array con los nombres de los servicios a inyectar
Un provider es una factoría de un servicio
Se ejecuta antes de "iniciarse" la aplicación por lo que NO existe aun ningún servicio creado, solo otros Providers
Permite configurase y consecuentemente configurar al servicio que creará
Permite configurarse mediante otros Providers o Constantes
Obligatoriamente tiene un método "$get" que es el que crea el servicio
AngularJS tiene unos bloques llamados "config" que permiten ejecutar código que define los Providers
app.config(function() {
//Este código se ejecuta para inicializar los providers
});
function Login(defaultUserPassword) {
var logged=false;
this.login=function(user,password) {
if ((defaultUserPassword.user===user) &&
(defaultUserPassword.password===password)) {
logged=true;
}
return logged;
}
this.isLogged=function() {
return logged;
}
}
function LoginProvider() {
var defaultUserPassword={
user:undefined,
password:undefined
}
this.setUser=function(user) {
defaultUserPassword.user=user;
}
this.setPassword=function(password) {
defaultUserPassword.password=password;
}
this.$get=function() {
return new Login(defaultUserPassword);
}
}
app.provider("login",LoginProvider);
app.config(function(loginProvider) {
loginProvider.setUser("foo");
loginProvider.setPassword("bar");
});
Configuramos el provider "programaticamente", lo que nos da mucha versatilidad
IMPORTANTE: No injectamos el servicio sino el provider. Por éso se llama "loginProvider"
No podemos usar un "value" ya que es un servicio y por lo tanto no está inicializado.
AngularJS se inventa un nuevo servicio llamado "constant" que puede inyectarse en un Provider y en un bloque "config"
app.constant("initialUserPassword",{
user:"foo",
password:"bar"
});
app.constant("initialUserPassword",{
user:"foo",
password:"bar"
});
$inject=['initialUserPassword']
function LoginProvider(initialUserPassword) {
var defaultUserPassword={
}
angular.extend(defaultUserPassword,initialUserPassword);
this.setUser=function(user) {
defaultUserPassword.user=user;
}
this.setPassword=function(password) {
defaultUserPassword.password=password;
}
this.$get=function() {
return new Login(defaultUserPassword);
}
}
app.provider("login",LoginProvider);
app.config(function(loginProvider) {
//loginProvider.setUser("foo2");
//loginProvider.setPassword("bar2");
});
Usando "constant" en el Provider
Se usa el servicio "$inject" con el método "instantiate".
var locals = {
defaultUserPassword: defaultUserPassword
};
var login = $injector.instantiate(Login,locals);
Login.$inject=['defaultUserPassword'];
function Login(defaultUserPassword) {
//Aqui vael código pero no lo hemos puesto para ahorrar espacio
}
$inject=['initialUserPassword']
function LoginProvider(initialUserPassword) {
var defaultUserPassword={
}
angular.extend(defaultUserPassword,initialUserPassword);
this.setUser=function(user) {
defaultUserPassword.user=user;
}
this.setPassword=function(password) {
defaultUserPassword.password=password;
}
this.$get=function() {
var locals = {
defaultUserPassword: defaultUserPassword
};
var login = $injector.instantiate(Login,locals);
return login;
}
}
app.provider("login",LoginProvider);
var app = angular.module('app', []);
MainCtrl.$inject=['$scope','$http'];
function MainCtrl($scope,$http) {
var config={
method:"GET",
url:"https://api.github.com/repos/angular/angular.js/issues?state=open"
}
var promise=$http(config);
promise.then(function(response){
$scope.issues=response.data;
},function(response) {
alert("Fallo la petición:" + response.status);
})
}
app.controller('MainCtrl',MainCtrl);
<table>
<tr>
<th>Numero</th>
<th>Titulo</th>
<th>Usuario</th>
</tr>
<tr ng-repeat="issue in issues">
<td>{{issue.number}}</td>
<td>{{issue.title}}</td>
<td>{{issue.user.login}}</td>
</tr>
</table>
Escalares
lowercase / uppercase
number
date
currency
Arrays
orderBy
limitTo
filter
MainCtrl.$inject=['$scope'];
function MainCtrl($scope) {
$scope.texto = "HOLA mundo";
$scope.numero = 1.14159;
$scope.precio = 99.9;
$scope.fecha = new Date();
});
<body ng-controller="MainCtrl">
<p>Texto: {{texto | uppercase }}</p>
<p>Texto: {{texto | lowercase }}</p>
<p>Numero:{{numero | number:4 }}</p>
<p>Precio:{{precio | currency }}</p>
<br />
<p>Fecha: {{fecha | date:'dd/MM/yyyy' }}</p>
<p>Fecha (short): {{fecha | date:'short' }}</p>
<p>Fecha (shortDate):{{fecha | date:'shortDate' }}</p>
</body>
NOTA: Cuidado al usar formatos de fecha predefinidos. Pueden cambiar entre versiones
MainCtrl.$inject=['$scope'];
function MainCtrl($scope) {
$scope.usuarios = [
{
idUsuario:34,
nombre:"Juan",
ape1:"Gonzalez"
},
{
idUsuario:46,
nombre:"Ana",
ape1:"Morales"
},
{
idUsuario:62,
nombre:"Sara",
ape1:"Diaz"
},
{
idUsuario:18,
nombre:"Marcos",
ape1:"Ortega"
}
]
}
<body ng-controller="MainCtrl">
<table>
<tr>
<th>Nombre</th>
<th>Apellido</th>
</tr>
<tr ng-repeat="usuario in usuarios | orderBy:['nombre','ape1']">
<td>{{usuario.nombre}}</td>
<td>{{usuario.ape1}}</td>
</tr>
</table>
</body>
Definen nuevos:
Controladores
Directivas
Filtros
Servicios
Ejecutan código al cargar el módulo:
config: Código de configuración
run: Código "Main"
Indica el nombre del módulo inicial a cargar
El resto de módulos se cargan como dependencias de este primer módulo
<html ng-app="app">
<head>
<script src="angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
</body>
</html>
angular.module("nombre",['ui.router']);
var modulo=angular.module("nombre");
modulo.controller("MainCrtl",MainCrtl);
Creando un módulo con dependencia de 'ui.router':
Obteniendo un módulo:
Usando el módulo para definir un controlador:
Broccoli
Protractor
Bower
Gulp
Grunt
Controladores
Quita todo lo que puedas de los controladores, usa servicios reutilizables.
No uses $scope, hay una nueva forma de declarar un controlador que usa "this".
No uses controladores, crea directivas que hacen la función del controlador.
Módulos
Los módulos son útiles en librerías de terceros, en tu aplicación usa un único módulo llamado "app"
Usa promesas para casi todo, nunca sabes cuando algo será asíncrono.
No abuses del $watch, no suele ser necesario.
Arquitectura
Un fichero cada clase
Ordena los ficheros por funcionalidades y no por tipos
Arquitectura en 3 capas
Vuelve a simplificar tus controladores otra vez
Nos hemos dejado más cosas.......
especialmente las rutas, pero hoy no era un buen día para contarlas ;-)
var app=angular.module('app',['ngNewRouter']);
Mas en: http://cursoangular.es
Ejemplo en: https://github.com/logongas/decharlas2015