By RAONI BOAVENTURA - Javascript Engineer
#AngularJS #JavaScript #MVC


<body ng-app="F1FeederApp" ng-controller="driversController">
<table>
<thead>
<tr><th colspan="4">Drivers Championship Standings</th></tr>
</thead>
<tbody>
<tr ng-repeat="driver in driversList">
<td>{{$index + 1}}</td>
<td>
<img src="img/flags/{{driver.Driver.nationality}}.png" />
{{driver.Driver.givenName}} {{driver.Driver.familyName}}
</td>
<td>{{driver.Constructors[0].name}}</td>
<td>{{driver.points}}</td>
</tr>
</tbody>
</table>
</body>
{{ 1 + 1 }}{{ 946757880 | date }}{{ user.name }}La directriz ng-app es responsable de hacer bootstrapping a tu aplicación, para definir
el ámbito de ésta. En AngularJS, puedes tener múltiples aplicaciones dentro de la misma página, por lo
que esta directriz define el lugar donde comienza y termina cada aplicación.
La directriz ng-controller define qué controlador estará a cargo de tu vista. En este
caso, la denotamos driversController, la cual proporcionará nuestra lista de conductores
(driversList).
La directriz ng-repeat es una de las más utilizadas, y sirve para definir tu alcance de
plantilla al pasar a través de colecciones. En el ejemplo anterior, repite una línea en la tabla por
cada conductor en driversList.
controllers.js:angular.module('F1FeederApp.controllers', []).
controller('driversController', function($scope) {
$scope.driversList = [
{
Driver: {
givenName: 'Sebastian',
familyName: 'Vettel'
},
points: 322,
nationality: "German",
Constructors: [
{name: "Red Bull"}
]
},
{
Driver: {
givenName: 'Fernando',
familyName: 'Alonso'
},
points: 207,
nationality: "Spanish",
Constructors: [
{name: "Ferrari"}
]
}
];
});
$scope se supone que debe enlazar tu controlador y vistas. En particular, lleva todos los
datos que se utilizarán dentro de la plantilla.
Todo lo que se agrega a ella (como la driversList del ejemplo anterior) será
directamente accesible en tus vistas. Por ahora, vamos a trabajar con una matriz de datos ficticios
(estática), que vamos a sustituir más tarde con nuestro servicio API.angular.module('F1FeederApp', [
'F1FeederApp.controllers'
]);
app.js) más adelante.
index.html:<!DOCTYPE html>
<html>
<head>
<title>F-1 Feeder</title>
</head>
<body ng-app="F1FeederApp" ng-controller="driversController">
<table>
<thead>
<tr><th colspan="4">Drivers Championship Standings</th></tr>
</thead>
<tbody>
<tr ng-repeat="driver in driversList">
<td>{{$index + 1}}</td>
<td>
<img src="img/flags/{{driver.Driver.nationality}}.png" />
{{driver.Driver.givenName}} {{driver.Driver.familyName}}
</td>
<td>{{driver.Constructors[0].name}}</td>
<td>{{driver.points}}</td>
</tr>
</tbody>
</table>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="js/app.js"></script>
<script src="js/services.js"></script>
<script src="js/controllers.js"></script>
</body>
</html>
$http y $resource.
El primero es una capa en la parte superior de XMLHttpRequest o
JSONP, mientras que el último
proporciona un mayor nivel de abstracción. Vamos a utilizar $http.
$http al añadirlo a nuestro services.js:angular.module('F1FeederApp.services', []).
factory('ergastAPIservice', function($http) {
var ergastAPI = {};
ergastAPI.getDrivers = function() {
return $http({
method: 'JSONP',
url: 'http://ergast.com/api/f1/2013/driverStandings.json?callback=JSON_CALLBACK'
});
}
return ergastAPI;
});
F1FeederApp.services)
y registramos un servicio dentro de ese módulo (F1FeederApp.services). Nótese
que pasamos $http como parámetro a ese servicio.
Esto le dice al motor de inyección de
dependenciade Angular, que nuestro nuevo servicio
requiere (o depende) del servicio $http.app.js,
reemplazando nuestro código existente con:angular.module('F1FeederApp', [
'F1FeederApp.controllers',
'F1FeederApp.services'
]);
controller.js un poco,
integrar ergastAPIservice
como una dependencia, y estaremos listos para continuar:angular.module('F1FeederApp.controllers', []).
controller('driversController', function($scope, ergastAPIservice) {
$scope.nameFilter = null;
$scope.driversList = [];
ergastAPIservice.getDrivers().success(function (response) {
//Dig into the responde to get the relevant data
$scope.driversList = response.MRData.StandingsTable.StandingsLists[0].DriverStandings;
});
});
nameFilter
a nuestro alcance. Vamos a poner esta variable en uso.index.html,
justo debajo de la etiqueta <body>:<input type="text" ng-model="nameFilter" placeholder="Search..."/>
ng-model. Esta directriz une nuestro campo de
texto a la variable $scope.nameFilter
y se asegura de que su valor esté siempre al día con el valor de entrada. Ahora, vamos a
visitar index.html
una vez más y hagamos un pequeño ajuste en la línea que contiene la directriz
ng-repeat:<tr ng-repeat="driver in driversList | filter: nameFilter">
ng-repeat que, antes de dar salida a los datos, la matriz
driversList
debe ser filtrada por el valor almacenado en nameFilter.$scope.nameFilter que asociamos a él se actualice con el nuevo valor. Dado que binding
funciona en ambos sentidos, el momento en el que el valor
nameFilter se actualiza, la segunda directriz asociada a la misma (es decir,
ng-repeat) también recibe el nuevo valor y la vista se
actualiza inmediatamente.

Driver.givenName y Driver.familyName: En primer lugar,
añadimos a driversController, justo por debajo de la línea
$scope.driversList =[];:
$scope.searchFilter = function (driver) {
var keyword = new RegExp($scope.nameFilter, 'i');
return !$scope.nameFilter || keyword.test(driver.Driver.givenName) || keyword.test(driver.Driver.familyName);
};
ng-repeat:<tr ng-repeat="driver in driversList | filter: searchFilter">
$routeProvider (en app.js) lo que
nos ayudará a lidiar con estas variadas rutas de aplicación. A continuación,
añadiremos dos de estas rutas: una para la tabla del campeonato y otro para los datos del
conductor. Aquí est´ nuestra nueva app.js:angular.module('F1FeederApp', [
'F1FeederApp.services',
'F1FeederApp.controllers',
'ngRoute'
]).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when("/drivers", {templateUrl: "partials/drivers.html", controller: "driversController"}).
when("/drivers/:id", {templateUrl: "partials/driver.html", controller: "driverController"}).
otherwise({redirectTo: '/drivers'});
}]);
http://domain/#/drivers cargará
el driversController y buscará la vista parcial que se va a renderizar en
partials/drivers.html.
¡Pero espera! No tenemos ninguna vista parcial todavía, ¿verdad? Vamos a tener
que crearlas también.ng-view, modificando nuestra index.html para reflejar lo
siguiente:<!DOCTYPE html>
<html>
<head>
<title>F-1 Feeder</title>
</head>
<body ng-app="F1FeederApp">
<ng-view></ng-view>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="js/app.js"></script>
<script src="js/services.js"></script>
<script src="js/controllers.js"></script>
</body>
</html>
<ng-view>.
Lo &ucute;nico que tenemos que hacer es crear un archivo con el nombre partials/drivers.html,
y poner nuestra tabla de campeonato HTML allí. También vamos a utilizar esta
oportunidad para vincular el nombre del conductor a nuestra ruta de los detalles del conductor:<input type="text" ng-model="nameFilter" placeholder="Search..."/>
<table>
<thead>
<tr><th colspan="4">Drivers Championship Standings</th></tr>
</thead>
<tbody>
<tr ng-repeat="driver in driversList | filter: searchFilter">
<td>{{$index + 1}}</td>
<td>
<img src="img/flags/{{driver.Driver.nationality}}.png" />
<a href="#/drivers/{{driver.Driver.driverId}}">
{{driver.Driver.givenName}} {{driver.Driver.familyName}}
</a>
</td>
<td>{{driver.Constructors[0].name}}</td>
<td>{{driver.points}}</td>
</tr>
</tbody>
</table>
services.js, lo siguiente:angular.module('F1FeederApp.services', [])
.factory('ergastAPIservice', function($http) {
var ergastAPI = {};
ergastAPI.getDrivers = function() {
return $http({
method: 'JSONP',
url: 'http://ergast.com/api/f1/2013/driverStandings.json?callback=JSON_CALLBACK'
});
}
ergastAPI.getDriverDetails = function(id) {
return $http({
method: 'JSONP',
url: 'http://ergast.com/api/f1/2013/drivers/'+ id +'/driverStandings.json?callback=JSON_CALLBACK'
});
}
ergastAPI.getDriverRaces = function(id) {
return $http({
method: 'JSONP',
url: 'http://ergast.com/api/f1/2013/drivers/'+ id +'/results.json?callback=JSON_CALLBACK'
});
}
return ergastAPI;
});
controllers.js:angular.module('F1FeederApp.controllers', []).
/* Drivers controller */
controller('driversController', function($scope, ergastAPIservice) {
$scope.nameFilter = null;
$scope.driversList = [];
$scope.searchFilter = function (driver) {
var re = new RegExp($scope.nameFilter, 'i');
return !$scope.nameFilter || re.test(driver.Driver.givenName) || re.test(driver.Driver.familyName);
};
ergastAPIservice.getDrivers().success(function (response) {
//Digging into the response to get the relevant data
$scope.driversList = response.MRData.StandingsTable.StandingsLists[0].DriverStandings;
});
}).
/* Driver controller */
controller('driverController', function($scope, $routeParams, ergastAPIservice) {
$scope.id = $routeParams.id;
$scope.races = [];
$scope.driver = null;
ergastAPIservice.getDriverDetails($scope.id).success(function (response) {
$scope.driver = response.MRData.StandingsTable.StandingsLists[0].DriverStandings[0];
});
ergastAPIservice.getDriverRaces($scope.id).success(function (response) {
$scope.races = response.MRData.RaceTable.Races;
});
});
$routeParams en el
controlador del conductor.
Este servicio nos permitirá acceder a nuestros parámetros de URL (para el :id, en este caso)
utilizando $routeParams.id.partials/driver.html y agregamos:<section id="main">
<a href="./#/drivers"><- Back to drivers list</a>
<nav id="secondary" class="main-nav">
<div class="driver-picture">
<div class="avatar">
<img ng-show="driver" src="img/drivers/{{driver.Driver.driverId}}.png" />
<img ng-show="driver" src="img/flags/{{driver.Driver.nationality}}.png" /><br/>
{{driver.Driver.givenName}} {{driver.Driver.familyName}}
</div>
</div>
<div class="driver-status">
Country: {{driver.Driver.nationality}} <br/>
Team: {{driver.Constructors[0].name}}<br/>
Birth: {{driver.Driver.dateOfBirth}}<br/>
<a href="{{driver.Driver.url}}" target="_blank">Biography</a>
</div>
</nav>
<div class="main-content">
<table class="result-table">
<thead>
<tr><th colspan="5">Formula 1 2013 Results</th></tr>
</thead>
<tbody>
<tr>
<td>Round</td> <td>Grand Prix</td> <td>Team</td> <td>Grid</td> <td>Race</td>
</tr>
<tr ng-repeat="race in races">
<td>{{race.round}}</td>
<td><img src="img/flags/{{race.Circuit.Location.country}}.png" />{{race.raceName}}</td>
<td>{{race.Results[0].Constructor.name}}</td>
<td>{{race.Results[0].grid}}</td>
<td>{{race.Results[0].position}}</td>
</tr>
</tbody>
</table>
</div>
</section>
ng-show. Esta directriz
sólo mostrará el elemento HTML si la expresión proporcionada es true (es
decir, ni false, ni null).
En este caso, el avatar sólo aparecerá una vez que el objeto conductor ha sido cargado en el
alcance, por el controlador.
index.html,
para mejorar las capacidades de navegación del usuario. Las posibilidades son infinitas.Encuentralo Aquí