Cours de Rémi JarjatCours de Rémi Jarjat
  • Liste des cours
  • Culture numérique
  • Git
    • Terminologie
    • Avant de commencer
    • Créer un dépôt (local)
    • Enregistrer des changements
    • Des branches
    • Mise en commun du travail
    • Annuler des changements
    • Réécrire l'historique
    • Des outils pour se simplifier Git
    • Exercices
    • Exemples pratiques
  • Linux
    • Installation
    • Historique
    • Rangement des fichiers
    • Les processus
    • Commandes de base
    • Commandes avancées
    • /linux/6-other-technologies.html
    • Exercices
    • Correction des exercices
  • PHP
    • Environnement de travail
    • Bases du PHP
    • Tests et boucles
    • Procédures et fonctions
    • Interagir avec l'utilisateur
    • La temporisation de sortie
    • PHP Doc et PSR
    • PHP Orienté objet
    • Héritage et objets
    • Factorisation
    • Manipuler la BdD avec PDO (PHP Data Object)
    • Architecture MVC
    • Webservices REST
    • Exercices - Bases
    • Exercices - Séparer en plusieurs fichiers
    • Exercices - POST et SESSION
    • Exercices - Panier et validation
    • Exercices - Objets
    • Exercices - BdD avec PDO
    • Projet - montage d'ordinateurs
    • Projet - Personnages de Jeux de Rôle
  • Symfony
    • Installer Symfony et son environnement de travail
    • Structure et utilisation d'un projet
    • Le routing
    • Les controllers
    • Twig
    • Les services et l'injection de dépendances
    • Doctrine et la BdD
    • Formulaires
    • Les traductions
    • Event listeners/subscribers
    • Connexion et sécurisation
    • Bundles
    • Easy Admin Bundle
    • API Platform
    • Pense-bêtes
    • Symfony au quotidien
    • Travailler avec Docker
    • Projet : annonces de SPA / éleveurs
    • Exercices
  • Javascript
    • Les bases du langage
    • Manipulation logique
    • Le DOM
    • JQuery
    • Ajax
    • Programmation orientée objet
    • Webpack
    • Outils utiles
    • Révisions
  • Serveur Lamp
  • Déploiement
    • Des outils et manières de faire
    • Déploiement par FTP
    • Wordpress
    • Intégrer Git dans le processus
    • GitHub Pages pour déployer facilement
    • Symfony et Angular
  • Docker
  • Intégration continue
  • Sécurité informatique

Ajax

Définitions

AJAX (Asynchronous JavaScript and XML) est un ensemble de techniques pour permettre au front (JS principalement) de communiquer avec un serveur de manière asynchrone.

Bien que le format de données XML ait été largement mis de côté au profit du format JSON, AJAX désigne désormais tout moyen permettant au front de communiquer en HTTP(s) avec un serveur de manière asynchrone (sans rechargement de page).

JSON (JavaScript Object Notation) est un format de données, une manière formalisée d'écrire des données pour les stocker ou les échanger. Sa syntaxe est très proche de celle des objets javascript.

{
  "hp": 100,
  "strength": 10,
  "defense": 5
}

Convertir du JS en JSON

La méthode JSON.stringify() vous permet de convertir un objet JS en sa représentation en JSON :

let player = {
    name: 'Tango',
    hp: 100,
    strength: 10,
    defense: 5
}

let jsonPlayer = JSON.stringify(player);

JSON accepte les valeurs suivantes :

  • Objet
  • Array
  • Nombre
  • Chaîne de caractères
  • true
  • false
  • null

Convertir du JSON en JS

L'inverse est fait avec la méthode JSON.parse(). Attention à bien vérifier que le JSON n'est pas vide avant de la parser.

let jsonPlayer = {"name": "Tango", "hp": 100, "strength": 10, "defense": 5};

let player = JSON.parse(jsonPlayer);

Faire des appels AJAX

Nous pouvons facilement créer des appels AJAX, avec JQuery ou l'API Fetch de VanillaJS. L'idée est de demander le contenu d'une page ou un retour d'API (du contenu en JSON) et le traiter dans notre page. L'intérêt est, le plus souvent, de récupérer des informations stockés sur un autre site web pour les afficher sur le nôtre (mais sachez que l'on peut tout aussi bien envoyer des données pour les stocker/traiter).

En Vanilla JS avec Fetch

Documentation formelle et documentation pratique Un cours complet de Pierre Giraud sur le sujet.

Attention, fetch() n'est pas compatible avec Internet Explorer (voir le tableau de compatibilité sur CanIUse).

La fonction fetch() prend en paramètre obligatoire l'URL du serveur à contacter et, comme paramètre optionnel un objet de configuration (qui inclue la méthode HTTP à utiliser, GET par défaut). Cette fonction retourne une promesse qui contient la réponse (brute, non utilisable) du serveur. On peut alors la convertir à l'aide des méthodes suivantes pour la traiter :

  • text() retourne la réponse sous forme de chaine de caractères (pouvant être du HTML)
  • json() retourne la réponse en tant qu'objet JSON
  • formData() retourne la réponse en tant qu'objet FormData
  • arrayBuffer() retourne la réponse en tant qu'objet ArrayBuffer
  • blob() retourne la réponse en tant qu'objet Blob

Un exemple, attendant une réponse du serveur en JSON :

fetch('https://un-serveur.test')
    // On récupère une promesse, c'est-à-dire un code qui sera exécuté quand la partie précédente sera terminée 
    // (et qui utilisera ce qu'elle retourne)
    // Ici, on convertit notre réponse brut en un objet JSON exploitable
    .then(function (response) {
        return response.json();
    })
    // Une fois la réponse convertie en JSON, 
    // on la récupère dans le paramètre data, 
    // et nous pouvons l'exploiter. 
    // Ici, on l'affiche dans un console.log
    .then(function (data) {
        console.log(data);
    })
    // Si un problème survient dans l'une des étapes précédentes
    // L'erreur est attrapée par la méthode catch
    // et envoyée dans le paramètre error
    // Ici, on l'affiche dans un console.log
    .catch(function (error) {
        console.log(error);
    });

Avec JQuery

Documentation

JQuery a été mis en avant surtout pour cette fonctionnalité. À une époque où l'API Fetch n'existait pas, JQuery proposait une méthode simple et très efficace pour construire les requêtes AJAX. Aujourd'hui encore, elle reste ma préférée. Pour les curieux, je vous laisse chercher des tutos sur XMLHttpRequest, si vous aimez vous faire du mal 😉 .

Je ne vais vous montrer ici que la méthode $.ajax(), mais sachez qu'il existe 2 autres méthodes $.get() et $.post() qui peuvent encore réduire la taille de votre code. Cette méthode attend un argument, un objet de configuration. Voici un exemple des paramètres les plus utilisés :

$.ajax({
    url: 'https://un-serveur.test', // url / adresse à appeler 
    method: 'POST', // la méthode utilisée (GET, POST, PUT, PATCH, etc.)
    dataType: "json", // Le type des données attendu en retour. Attention, utiliser jsonp si vous récupérez du contenu d'un site différent du vôtre
    data: { // Les données à envoyer. Ici on utilise un objet JS.
        name: 'Tango',
        hp: 100,
        strength: 10,
        defense: 5
    },
    // Une fonction de callback à appeler en cas de réussite de l'appel
    success: function (response) {
        console.log(response);
    },
    // Une fonction de callback à appeler en cas d'échec de l'appel
    error: function (xhr, status, error) {
        console.log(xhr, status, error);
    }

});

Exercices

Tests locaux

Dans un premier temps, nous allons essayer de charger du contenu local (sur notre ordinateur), tant JSON que HTML.

  • Créer un fichier HTML et un fichier JS, lier les deux (<script src=""></script>)
    • Ajouter ce code au début de votre body

<div class="uneClasse">
    <ul id="player-list">
    </ul>
</div>
  • Récupérer les fichiers nécessaires à l'exercice et ajoutez-les à votre projet (Rangez-les dans un dossier data)
    • data/exercice-ajax-html.html

<li data-name="player1" data-hp="125" id="player1" data-strength="2" data-defense="12">
    Le joueur player1 a 125 points de vie, 2 points de force et 12 points de défense.
</li>
  • data/exercice-ajax-single.json
{
  "name": "player1",
  "hp": 100,
  "defense": 5,
  "strength": 10
}

  • data/exercice-ajax-tab.json
[
  {
    "name": "player1.1",
    "hp": 100,
    "defense": 5,
    "strength": 10
  },
  {
    "name": "player2",
    "hp": 100,
    "defense": 5,
    "strength": 10
  },
  {
    "name": "dungeonMaster",
    "hp": 200,
    "defense": 6,
    "strength": 12
  },
  {
    "name": "dungeonMaster2",
    "hp": 150,
    "defense": 10,
    "strength": 5
  }
]
  • Nous allons faire 3 requêtes AJAX pour modifier notre HTML et/ou créer des noeuds dans notre page
    • Une première, pour récupérer le HTML et l'intégrer dans la liste (on le récupère avec $.ajax ou fetch() et on l'ajoute en tant que contenu à notre noeud ul#player-list)
    • Nous allons ensuite récupérer chaque fichier JSON (exercice-ajax-single.json et exercice-ajax-tab.json), récupérer les données, et créer des éléments pour les afficher dans notre DOM. Chaque fichier contient un ou des objets player et nous allons nous servir de ces données pour ajouter des <li> dans la liste que nous avons importé dans le premier appel AJAX.
      • Pour chaque objet dans le fichier JSON, créer un noeud li de cette forme :

<li data-name="player1" data-hp="125" id="player1" data-strength="2" data-defense="12">
    Le joueur player1 a 125 points de vie, 2 points de force et 12 points de défense.
</li>

Indices

  • Le fichier data/exercice-ajax-single.json contient un objet (JSON) avec les informations nécessaires. Il nous faut récupérer la donnée (et la convertir au format JSON si vous utilisez fetch) et créer un noeud HTML avec les données qu'elle contient.
  • Le fichier data/exercice-ajax-tab.json contient un tableau JSON, avec plusieurs objets qu'il va falloir traiter de la même manière (le fonctionnement va être très similaire, il y aura juste une boucle autour 😉 ).

English version

First, we will load some content from our computer, JSON and HTML.

  • Create an HTML file, and a JS file (use script tag to link them)
    • Add this code at the beginning of its body

<div class="className">
    <ul id="player-list">
    </ul>
</div>
  • Download necessary files and add them to your project
    • data/exercice-ajax-html.html

<li data-name="player0" data-hp="125" id="player0" data-strength="2" data-defense="12">
    The player0 player has 125 health points, 2 in strength and 12 in defense.
</li>
  • data/exercice-ajax-single.json
{
  "name": "player1",
  "hp": 100,
  "defense": 5,
  "strength": 10
}

  • data/exercice-ajax-tab.json
[
  {
    "name": "player1.1",
    "hp": 100,
    "defense": 5,
    "strength": 10
  },
  {
    "name": "player2",
    "hp": 100,
    "defense": 5,
    "strength": 10
  },
  {
    "name": "dungeonMaster",
    "hp": 200,
    "defense": 6,
    "strength": 12
  },
  {
    "name": "dungeonMaster2",
    "hp": 150,
    "defense": 10,
    "strength": 5
  }
]
  • We will now make 3 AJAX requests to update our HTML page and/or create new nodes with JS
    • First request: get the HTML file and update the ul#player-list tag with its content (get it with $.ajax or fetch(), as you prefer)
    • Second and third : get the JSON files (exercice-ajax-single.json and exercice-ajax-tab.json), extract their data, create new nodes and add them to our DOM. Each file contains one or several player objects, and we will use these data to create li nodes (and add it to a ul node that we loaded in our first AJAX request).
      • For every object from our JSON, your li node should look like this:

<li data-name="player1" data-hp="125" id="player1" data-strength="2" data-defense="12">
    The player1 player has 125 health points, 2 in strength and 12 in defense.
</li>

Récupérer et afficher des données distantes

Nous allons récupérer des données depuis une API : https://official-joke-api.appspot.com/jokes/ten

Notre but, récupérer des données et les afficher dans une page HTML.

Les objets JSON renvoyés par cette API sont de la forme :

{
  "id": "number",
  "type": "string",
  "setup": "string",
  "punchline": "string"
}

Notre HTML de base :

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Jokes API !</title>
</head>
<body>
<h1>Jokes API</h1>
<section id="jokes"></section>
</body>
</html>

Pour chaque blague, nous allons créer un HTML de cette forme et l'ajouter dans #jokes (remplacer les données entre {} par celles de l'API).


<article id="joke-{id}" data-type="{type}">
    <h2>{setup}</h2>
    <p>{punchline}</p>
</article>

English version

Let's get some data from an API : https://official-joke-api.appspot.com/jokes/ten

Our goal is to get data and display them in a HTML page.

Received JSON objects look like this:

{
  "id": "number",
  "type": "string",
  "setup": "string",
  "punchline": "string"
}

Our base HTML:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Jokes API !</title>
</head>
<body>
<h1>Jokes API</h1>
<section id="jokes"></section>
</body>
</html>

For every joke we get, create a HTML node, and add it to the #jokes node. (replace {} values with the ones from the API)


<article id="joke-{id}" data-type="{type}">
    <h2>{setup}</h2>
    <p>{punchline}</p>
</article>

Boss de fin

Nous allons récupérer des données depuis une API plus complexe : une API sur les Pokémon

Dans un premier temps, nous allons récupérer la liste des pokémon de première génération : les informations sur la première génération.

Nous allons récupérer uniquement la propriété pokemon_species, mais nous allons en parcourir le contenu avec une boucle (attention, nous allons récupérer les informations des 3 premiers pokémons dans un premier temps (boucle for par exemple). Il y en a 150 au total).

Cette propriété contient un tableau contenant des objets :

{
  "name": "bulbasaur",
  "url": "https://pokeapi.co/api/v2/pokemon-species/1/"
}

Pour chaque pokémon ainsi récupéré, nous allons récupérer des informations détaillées à partir de l'url fournie dans la propriété url (et donc faire un nouvel appel AJAX vers cette url) :

  • récupérer leurs parents (propriété evolves_from_species)
  • récupérer les noms français (tant pour le Pokémon que pour ses parents).

Afficher chaque élément de la liste des pokémons sous cette forme :

<section data-id="{id}" data-url="{url}">
    <h2>{name}</h2>
    {name} est une évolution de <span data-parent-url="{parentUrl}">{parent}</span>
    <a href="" class="more">Plus d'informations</a>
</section>

Remplacer les valeurs :

  • {id} par l'identifiant du pokémon (exemple : 1)
  • {url} par l'url donnant les informations sur le pokémon (par exemple https://pokeapi.co/api/v2/pokemon/1)
  • {name} le nom français du pokémon (exemple : Bulbizarre)
  • {parent} le nom français du pokémon parent, s'il y en a un
  • {parentUrl} par l'url donnant les informations sur le(s) pokémon(s) parent(s), s'il y en a un (par exemple https://pokeapi.co/api/v2/pokemon/1)

Algo / pseudo-code

variable liste = récupérer('https://pokeapi.co/api/v2/generation/1/').pokemon_species
Pour i allant de 0 à 3, faire
  variable url = liste[i].url
  variable pokemon = récupérer(url)
  construireHMLT(pokemon)
FinPour 

English version

Let's get some data from a far more complex API : a pokemon API

First, let's get the list of pokemons from the first generation : https://pokeapi.co/api/v2/generation/1/.

We will only use the property pokemon_species and get its content (warning, we will only use the first 3 pokemons, with a for loop. There are 150 pokemons and it would be quite long to handle them all).

The pokemon_species property is an array of objects :

{
  "name": "bulbasaur",
  "url": "https://pokeapi.co/api/v2/pokemon-species/1/"
}

For each of those (3) pokemons, we will use the url property to get more details about the pokemon. From these data, we will find :

  • The pokemon's parents name (from the evolves_from_species property)
  • The pokemon's name in French (and same for its parents')

Display every element of the list like this:


<section data-id="{id}" data-url="{url}">
    <h2>{name}</h2>
    {name} est une évolution de <span data-parent-url="{parentUrl}">{parent}</span>
    <a href="" class="more">Plus d'informations</a>
</section>

replace the values:

  • {id} with the pokemon's id (example: 1)
  • {url} with the url that gives you informations on this pokemon (example: https://pokeapi.co/api/v2/pokemon/1)
  • {name} pokemon's french name (example : Bulbizarre)
  • {parent} parent pokemon's french name
  • {parentUrl} with the url that gives you informations on this pokemon (example: https://pokeapi.co/api/v2/pokemon/1)
Algo / pseudo-code
variable list = getDataFrom('https://pokeapi.co/api/v2/generation/1/').pokemon_species
For i from 0 to 3, do
  variable url = list[i].url
  variable pokemon = getDataFrom(url)
  buildHTML(pokemon)
EndFor
Dernières mise à jour :
Prev
JQuery
Next
Programmation orientée objet