Puissance du JavaScript

Résumé d'AngularJS

W3.JS est une library moins complète,
mais 13 fois plus légère.

Angular (sept 2016) est le successeur (incompatible) d'AngularJS (créé en 2009 dont la version min 1.6.9 pèse 166 Ko).
Angular utilise TypeScript (au lieu de JavaScript)

Pré-requis :

Introduction

AngularJS est un framework (une bibliothèque) qui permet de créer plus facilement des applications web. Il suffit d'ajouter une seule ligne à son code HTML pour bénéficier de cette facilité. Ici, la version 1.6.9 :

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
  </head>
  ...

Donc, l'application web ne fonctionnera que si l'utilisateur est connecté.
Il est recommandé de placer ce Javacript dans le <head>.
Télécharger (=> enregistrer le lien sous) : angular.min.js (version 1.6.9)

While it is common in HTML applications to place scripts at the end of the <body> element, it is recommended that you load the AngularJS library either in the <head> or at the start of the <body>. This is because calls to angular.module can only be compiled after the library has been loaded.

Le HTML 5 permet d'ajouter aux balises HTML n'importe quels attributs à condition que leurs noms débutent par data-.

Les directives

Les directives sont de nouveaux attributs de balises HTML. Pour que le code HTML 5 soit valide, ces noms doivent donc être préfixé par data-.

Les expressions

Les expressions AngularJS peuvent contenir des littéraux (nombre et chaîne de caractères), des opérateurs (arithmétiques ( + * - / % ), logiques (&& || ! ) et relationnels( < <= == != > >= ), des parenthèses, des variables, true et false, des noms de propriétés d'objet, ... (comme en JavaScript).

Une variable peut aussi être un nom de tableau ou un objet.

Quelques exemples d'expression :

3.1415926535
2+2
"Thibaut"
'PIGNÉ'
"Thibaut"+'PIGNÉ'
nom
(2.5 + 0.5 ) * 4
points[2]
personne.nom
!true
17<18
(17<18)&&(17>18)
('PIGNÉ').length
'PIGNÉ'+5

Ci-dessus, nom est un nom de variable. Le résultat de cette expression vaut le contenu de cette variable.

Utilisation d'une expression

Pour afficher une expression, on peut utiliser la directive ng-bind, car elle lie le résultat de l'expression AngularJS à la méthode JavaScript innerHTML de l'élément HTML (ci-dessous, <span>) qui la contient.

<p>Valeur de l'expression : <span data-ng-bind="expression"></span></p>

Toutefois, en pratique, on préfère utiliser {{ expression }}, car, placé dans le contenu d'une balise - c'est-à-dire entre la balise ouvrante et fermante - il affiche le résultat de l'expression; et, placé dans la balise, le résultat de l'expression est utilisé comme valeur dans un attribut (comme nous le voyons dans notre première application web pour changer la couleur de fond d'un champ).

<p>{{ expression }}</p>

<input ... style="background-color:{{couleur}}" />

Les espaces dans {{ }} sont facultatifs. Ils permettent une meilleure lisibilité du code. {{expression}} = {{      expression }}

Ma première application web

Code HTML de l'application web :

  ...
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
  </head>
  <body>
  ...
    <!-- début de l'application AngularJS -->
    <div data-ng-app="" data-ng-init="nom='LEDRU';points=[1,15,19,2,40];
    personne={nom:'EINSTEIN',prenom:'Albert'}">
      ...
      <p>
        Affichage de résultats d'expressions avec la directive <code>ng-bind</code> :
      </p>
      <aside>
        <p>
          3.1415926535 = <span data-ng-bind="3.1415926535"></span><br />
          2+2 = <span data-ng-bind="2+2"></span><br />
          "Thibaut" = <span data-ng-bind='"Thibaut"'></span><br />
          'PIGNÉ' = <span data-ng-bind="'PIGNÉ'"></span><br />
          'Thibaut'+' '+'PIGNÉ' = <span data-ng-bind="'Thibaut'+' '+'PIGNÉ'"></span><br />
          nom = <span data-ng-bind="nom"></span><br />
          (2.5 + 0.5 ) * 4 = <span data-ng-bind="(2.5 + 0.5 ) * 4"></span><br />
          points[2] = <span data-ng-bind="points[2]"></span><br />
          personne.nom = <span data-ng-bind="personne.nom"></span><br />
          !true = <span data-ng-bind="!true"></span><br />
          17 < 18 = <span data-ng-bind="17 < 18"></span><br />
          (17<18)&&(17>18) = <span data-ng-bind="(17<18)&&(17>18)"></span><br />
          ('PIGNÉ').length = <span data-ng-bind="('PIGNÉ').length"></span><br />
          'PIGNÉ'+5 = <span data-ng-bind="'PIGNÉ'+5"></span><br />
        </p>
      </aside>
      ...
      <p>Résultats d'expressions :</p>
      <aside>
        <p>
          {{3.1415926535}}<br />
          {{2+2}}<br />
          {{"Thibaut"}}<br />
          {{'PIGNÉ'}}<br />
          {{"Thibaut"+'PIGNÉ'}}<br />
          {{nom}}<br />
          {{(2.5 + 0.5 ) * 4}}<br />
          {{points[2]}}<br />
          {{personne.nom}}<br />
          {{!true}}<br />
          {{17 < 18}}
          {{(17<18)&&(17>18)}}<br />
          {{('PIGNÉ').length}}<br />
          {{'PIGNÉ'+5}}<br />
        </p>
      </aside>
      ...
      <aside>
        <p>
          Mon nom : <input type="text" data-ng-model="mon_nom" />
        </p>
        <p>
          Le nom que j'ai tapé est : {{ mon_nom }}<br>
          Le nom que j'ai tapé est : <span data-ng-bind="mon_nom"></span>
        </p>
      </aside>
      ...
      <aside>
        <p>
          Tapez le nom d'une couleur de fond (blue, red, ...) pour ce champ :
          <input type="text" data-ng-model="couleur"
           style="background-color:{{couleur}}" placeholder="blue" />
        </p>
      </aside>
    </div>
    <!-- fin de l'application AngularJS -->

nom est un nom de variable (simple) dont la valeur a été initialisée à 'LEDRU', via la directive ng-init
<div data-ng-app="" data-ng-init="nom='LEDRU';...">

personne = le nom d'une variable (objet)

Dans le code source de la zone de l'application AngularJS, on ne peut pas taper des doubles accolades - {{ }} ou &#123;&#123; &#125;&#125; - sans qu'ils soient automatiquement interprétés.

Les doubles accolades ne peuvent pas contenir des doubles accolades.

Pour mieux délimiter la zone d'application, une couleur de fond est appliquée.

Application AngularJS

Affichage de résultats d'expressions avec la directive ng-bind :


Affichage de résultats d'expressions avec les doubles accolades :



Les doubles accolades peuvent être tapées dans le contenu d'une balise, mais aussi dans la balise !

Créer une mini-application web est très facile.

Résumé

Vous savez déjà l'essentiel. Il faut :

  1. lier sa page web à un framework (= ajouter une ligne dans le <head>)
  2. définir la zone de l'application web (= ajouter l'attribut data-ng-app)
  3. récolter les données de l'utilisateur (= ajouter l'attribut data-ng-model)
  4. {{ expression }} peut être placé dans :
    1. le contenu d'une balise, pour afficher le résultat de l'expression sur la page web.
    2. la balise, pour utiliser le résultat de l'expression comme valeur dans un attribut de cette balise.

L'initialisation se fait normalement dans le controller.

ng-controller

Le controller "contrôle" l'application. Concrètement, contient tout le code JavaScript nécessaire.

La directive ng-controller permet de donner un nom au controller. Elle est souvent placée dans la même balise que celle qui nomme l'application (car une application simple ne dispose que d'un seul controller).

<div data-ng-app="myApp" data-ng-controller="myCtrl">

Le code JavaScript pourrait être le contenu de la balise script, mais il est préférable de placer le code JavaScript dans un fichier Javascript.

myCtrl.js

angular.module('myApp',[]).controller('myCtrl', function($scope) {

});

Vous pouvez recopier ce code tel quel dans vos scripts. Veillez à ce que le nom du controller dans le code HTML soit le même dans le code JS.

A controller is a JavaScript Object, created by a standard JavaScript object constructor.

Pour initialiser la variable nom, il suffit alors de taper : $scope.nom="PIGNÉ";

angular.module('myApp',[]).controller('myCtrl', function($scope) {

   $scope.nom="PIGNÉ"; /* initialisation de la variable nom sans passer par ng-init */

});

$scope

$scope est un objet pouvant avoir des propriétés et/ou des méthodes qui fait la liaison entre la vue (view HTML) et le controller. $cope est un mot-clé.

When adding properties to the $scope object in the controller, the view (HTML) gets access to these properties. In the view, you do not use the prefix $scope

If we consider an AngularJS application to consist of :
- View, which is the HTML.
- Model, which is the data available for the current view.
- Controller, which is the JavaScript function that makes/changes/removes/controls the data.
Then the scope is the Model.

$rootScope

All applications have a $rootScope.
The rootScope is available in the entire application.
If a variable has the same name in both the current scope and in the rootScope, the application uses the one in the current scope.

ng-repeat

La directive ng-repeat répète une balise HTML, autant de fois qu'il existe d'éléments dans une tableau ou une collection (tableau d'objets).

The ng-repeat directive is perfect for looping through an array.

<div ng-app="" ng-init="names=['Jani','Hege','Kai']">
  <ul>
    <li ng-repeat="x in names">
      {{ x }}
    </li>
  </ul>
</div>
<div ng-app="" ng-init="names=[
{name:'Jani',country:'Norway'},
{name:'Hege',country:'Sweden'},
{name:'Kai',country:'Denmark'}]">

<ul>
  <li ng-repeat="x in names">
    {{ x.name + ', ' + x.country }}
  </li>
</ul>

</div>

ng-model

With the ng-model directive you can bind the value of an input field to a variable created in AngularJS.

The data model is a collection of data available for the application

ng-show / ng-hide / ng-disabled

Be displayed only if the expression in the ng-show attribute returns true. You can use any expression that evaluates to true or false.

<p>
  17 > 18 <span ng-show="17 > 18">vaut <em>false</em> !</span><br>
  17 < 18 <span ng-show="17 < 18">vaut <em>true</em>.</span>
</p>

<p>17 > 18<span ng-hide="17 > 18"</span> => caché !</span><br>
    17 < 18<span ng-hide="17 < 18"</span> => pas caché !</span></p>
<div ng-app="" ng-init="mySwitch=true">

<p><button ng-disabled="mySwitch">Click Me!</button></p>
<p><input type="checkbox" ng-model="mySwitch">Button</p>
<p>{{ mySwitch }}</p>

</div>

ng-click

The event directives allows us to run AngularJS functions at certain user events.

<div ng-app="myApp" ng-controller="myCtrl">
    <h1 ng-click="changeName()">{{firstname}}</h1>
</div>
angular.module('myApp',[]).controller('myCtrl', function($scope) {

  $scope.firstname = "John";

  $scope.changeName = function() {
    $scope.firstname = "Nelly";
  }

});

ng-blur
ng-change
ng-click
ng-copy
ng-cut
ng-dblclick
ng-focus
ng-keydown
ng-keypress
ng-keyup
ng-mousedown
ng-mouseenter
ng-mouseleave
ng-mousemove
ng-mouseover
ng-mouseup
ng-paste

Mouse events occur when the cursor moves over an element, in this order :

ng-mouseover
ng-mouseenter
ng-mousemove
ng-mouseleave

Or when a mouse button is clicked on an element, in this order :

ng-mousedown
ng-mouseup
ng-click

If you want to show a section of HTML code when a button is clicked, and hide when the button is clicked again, like a dropdown menu, make the button behave like a toggle switch :

  <button ng-click="myFunc()">Click Me!</button>

  <div ng-show="showMe">
    <h1>Menu:</h1>
    <div>Pizza</div>
    <div>Pasta</div>
    <div>Pesce</div>
  </div>
  $scope.showMe = false;
  $scope.myFunc = function() {
    $scope.showMe = !$scope.showMe;
  }

$event

You can pass the $event object as an argument when calling the function. The $event object contains the browser's event object :

  <h1 ng-mousemove="myFunc($event)">Mouse Over Me!</h1>
  <p>Coordinates: {{x + ', ' + y}}</p>
  $scope.myFunc = function(myE) {
    $scope.x = myE.clientX;
    $scope.y = myE.clientY;
  }

Filters

AngularJS provides filters to transform data : currency Format a number to a currency format.
date Format a date to a specified format.
filter Select a subset of items from an array.
json Format an object to a JSON string.
limitTo Limits an array/string, into a specified number of elements/characters.
lowercase Format a string to lower case.
number Format a number to a string.
orderBy Orders an array by an expression.
uppercase Format a string to upper case.

Le format est celui utilisé aux États-Unis. Pour obtenir le format franco-belge (au niveau du currency, date et number, il faut ajouter le fichier angular-locale_fr-be.js après le fichier angular.min.js :

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script src="angular-locale_fr-be.js"></script>

Utilisez le menu contextuel du lien pour choisir "enregistrer le lien sous ..." et ainsi télécharger le fichier (au lieu de le visualiser).

Filters can be added to expressions by using the pipe character |, followed by a filter.

<p>The name is {{ lastName | uppercase }}</p>


<li ng-repeat="x in names | orderBy:'country'">
  {{ x.name + ', ' + x.country }}
</li>


<li ng-repeat="x in names | filter : 'i'">{{ x }}</li>

<tr data-ng-repeat="x in tableReduite=(table | filter:{'e':search})">


<td>{{x.b | date}}</td>
<td>{{x.c | currency}}</td>

table est le nom d'un tableau (d'objets)
e est le nom d'un champ (d'une propriété de l'objet)
search est le nom d'une variable (qui contient la valeur du champ "e" de certains objets). La valeur de cette variable est tapée par l'utilisateur via un champ (user input)

Pour plus d'info, consultez le code-source des fichiers : tab3.htm et tab4.htm.

Services

A service is a function or object. AngularJS has about 30 built-in services. The name service is passed in to the controller as an argument. Ce nom est toujours préfixé par le signe $.

Once you have created a service, and connected it to your application, you can use the service in any controller, directive, filter, or even inside other services.

$http

This service makes a request to the server, and lets your application handle the response. $http is an XMLHttpRequest object for requesting external data.

angular.module('myApp',[]).controller('myCtrl', function($scope, $http) {

  $http.get("welcome.htm").then(function (response) {
        $scope.myWelcome = response.data;
    });

});

Method of the $http service :

.delete()
.get()
.head()
.jsonp()
.patch()
.post()
.put()

angular.module('myApp',[]).controller('myCtrl', function($scope, $http) {

  $http({
        method : "GET",
        url : "welcome.htm"
    }).then(function mySuccess(response) {
        $scope.myWelcome = response.data;
    }, function myError(response) {
        $scope.myWelcome = response.statusText;
  });

});

The response from the server is an object with these properties :

.config the object used to generate the request.
.data a string, or an object, carrying the response from the server.
.headers a function to use to get header information.
.status a number defining the HTTP status.
.statusText a string defining the HTTP status.

The data you get from the response is expected to be in JSON format.
JSON is a great way of transporting data

$http.get("customers.php").then(function(response) {
        $scope.myData = response.data.records;
    });

myData est un tableau d'objets (au format JSON).
$http.get() reads JSON data

Tables

The ng-repeat directive is perfect for displaying tables.

  <tr ng-repeat="x in names"</tr>
    <td>{{ $index + 1 }}</td>
    <td>{{ x.Name }}</td>
    <td>{{ x.Country }}</td>
  </tr>

$index est un mot-clé qui affiche un index qui commence à 0 et qui s'auto-incrémente (à chaque nouvelle ligne affichée). Voir ng-repeat

  $http.get("customers.php")
    .then(function (response) {
      $scope.names = response.data.records;
    });

To make it nice, add some CSS to the page :

table, th , td {
  border: 1px solid grey;
  border-collapse: collapse;
  padding: 5px;
}

table tr:nth-child(odd) {
  background-color: #f1f1f1;
}

table tr:nth-child(even) {
  background-color: #ffffff;
}

Ou, utilisez le fichier w3.css et la classe w3-table-all

ng-options

To create a dropdown list, based on an array of strings :

  <select ng-model="selectedName" ng-options="x for x in names">
  </select>
  <select>
    <option ng-repeat="x in names">{{x}}</option>
  </select>

ng-options vs ng-repeat. Dropdowns made with ng-options allows the selected value to be an object, while dropdowns made from ng-repeat has to be a string.

The data source was can also use an object. Assume you have an object with key-value pairs. The expression in the ng-options attribute is a bit different for objects :

<select ng-model="selectedCar" ng-options="x for (x, y) in cars">
</select>

x for (x, y) => key s'affichera dans les options; value = ce qui sera sélectionné
y for (x, y) => value s'affichera dans les options; value = ce qui sera sélectionné

The selected value will always be the value in a key-value pair.

Avec la collection suivante :

$scope.cars = {
car01 : {brand : "Ford", model : "Mustang", color : "red"},
car02 : {brand : "Fiat", model : "500", color : "white"},
car03 : {brand : "Volvo", model : "XC90", color : "black"}
};
<select ng-model="selectedCar" ng-options="y.brand for (x, y) in cars">
</select>

SQL

AngularJS is perfect for displaying data from a Database. Just make sure the data is in JSON format.

Cross-Site HTTP Requests Requests for data from a different server (than the requesting page), are called cross-site HTTP requests. Cross-site requests are common on the web. Many pages load CSS, images, and scripts from different servers. In modern browsers, cross-site HTTP requests from scripts are restricted to same site for security reasons. The following line, in our PHP examples, has been added to allow cross-site access.

<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");

  $cnx = $typDB.":host=".$host.";dbname=".$dbname;
  $bdd = new PDO($cnx, $root, $password);

  $sql = "...";
  $rep = $bdd->query($sql);
  echo json_encode($rep->fetchAll(PDO::FETCH_ASSOC));

?>

Voir : PHP - MySQL - JSON - AngularJS

Forms

Radio buttons with the same ng-model can have different values, but only the selected one will be used.

<input type="radio" ng-model="myVar" value="dogs">Dogs
<input type="radio" ng-model="myVar" value="tuts">Tutorials
<input type="radio" ng-model="myVar" value="cars">Cars

The property defined in the ng-model attribute will have the value of the selected option in the selectbox.

<select ng-model="myVar">
    <option value="">
    <option value="dogs">Dogs
    <option value="tuts">Tutorials
    <option value="cars">Cars
</select>

The novalidate attribute disables any default browser validation.

Validation

L'apport d'AngularJS en matière de validation d'un formulaire est insuffisant. La validation HTML et validation JS sont suffisantes (et doivent être refaites côté serveur)

Apport d'AngularJS

Input fields have the following states :

$untouched The field has not been touched yet
$touched The field has been touched
$pristine The field has not been modified yet
$dirty The field has been modified
$invalid The field content is not valid
$valid The field content is valid

Forms have the following states :

$pristine No fields have been modified yet
$dirty One or more have been modified
$invalid The form content is not valid
$valid The form content is valid
$submitted The form is submitted

AngularJS adds CSS classes to forms and input fields depending on their states. The classes are removed if the value they represent is false.

angular Object

The Global API functions are accessed using the angular object. Below is a list of some common API functions :

angular.lowercase() : Converts a string to lowercase angular.uppercase() : Converts a string to uppercase angular.isString() : Returns true if the reference is a string angular.isNumber() : Returns true if the reference is a number

Toutes les fonctions de l'objet angular

ng-include

You can include HTML content using the ng-include directive. It can also contain AngularJS code. By default, the ng-include directive does not allow you to include files from other domains. To include files from another domain, you can add a whitelist of legal files and/or domains in the config function of your application:

<div ng-include="'https://tryit.w3schools.com/angular_include.php'"></div>

<script>
var app = angular.module('myApp', []);
app.config(function($sceDelegateProvider) {
    $sceDelegateProvider.resourceUrlWhitelist([
        'https://tryit.w3schools.com/**'
    ]);
});
</script>

Be sure that the server on the destination allows cross domain file access. To allow this file to be read from other domains, it must contain the header :

<?php
  header("Access-Control-Allow-Origin: *");
?>

Animations

Applications should not be filled with animations, but some animations can make the application easier to understand.

you must include the AngularJS Animate library :
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular-animate.js"><script>

Then you must refer to the ngAnimate module in your application :
<body ng-app="ngAnimate">

Or if your application has a name, add ngAnimate as a dependency in your application module

var app = angular.module('myApp', ['ngAnimate']);

Liens :