Architecture(s) et
application(s) Web

CSC4101 - Interface dynamique côté navigateur en Javascript

19/10/2026

Récap séances précédentes

  • [X] HTTP (GET)
  • [X] PHP
  • [X] Doctrine
  • [X] Routeur Symfony
  • [X] HTML
  • [X] Twig
  • [X] CSS
  • [X] Formulaires
  • [ ] Sessions
  • [ ] Contrôle d’accès

Plan de la séquence

Objectifs de cette séance (1h) :

  1. Aller au-delà des formulaires basiques Symfony
  2. Interfaces dynamiques
  3. JavaScript
  4. Manipulation du DOM
  5. AJAX

Edition des OneToMany

Améliorons l’UX des formulaires…

Rappel modèle données :

  • Project et Todo reliées par un OneToMany

Version de base

project-edit-basic.png
Figure 1 : version du formulaire d’édition généré par make:crud

Ajout d’une association OneToMany

Propriété multi-valuée Project::todos

class ProjectType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('description')
            ->add('todos')
            ;

Champ par défaut : liste à sélection multiple

project-todos-basic.png
Figure 2 : version basique avec liste

Problème : comment sélectionner plusieurs valeurs ? (Crtl + clic)

Alternative : utilisation de checkboxes

class ProjectType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('description')
            ->add('todos', null, [
                            'multiple' => true,
                            'expanded' => true
                         ])
            ;

Par défaut, génère un champs ChoiceType … OK, merci la doc…

Résultat : propriété multi-valuée via des checkboxes

version-checkboxes.png
Figure 3 : sélection multiple via checkboxes

Encore faut-il réparer la sauvegarde

class ProjectType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('description')
            ->add('todos', null, [
              'multiple' => true,
              'expanded' => true,
              'by_reference' => false
          ])
            ;

'by_reference' => false nécessaire pour que ça sauvegarde les modifications sur les tâches du projet … merci la doc…

Mise en forme du formulaire

Comment faire un affichage en colonnes ?

colonnes.png
Figure 4 : séparation des champs en plusieurs colonnes

Modifier les gabarits en profondeur

Rappel : gabarit project/edit.html.twig généré par défaut par make:crud

{% extends 'base.html.twig' %}

{% block title %}Edit Project{% endblock %}

{% block body %}
    <h1>Edit Project</h1>

    {{ include('project/_form.html.twig', {'button_label': 'Update'}) }}

    <a href="{{ path('app_project_index') }}">back to list</a>

    {{ include('project/_delete_form.html.twig') }}
{% endblock %}

Sous-gabarit pour le formulaire project/_form.html.twig

{{ form_start(form) }}
    {{ form_widget(form) }}
    <button class="btn btn-primary">{{ button_label|default('Save') }}</button>
{{ form_end(form) }}

Éclater la structure des widgets du formulaire

{{ form_start(form) }}
    {% dump form.todos %}
    {{ form_errors(form) }}
    <div class="row">
        <div class="col">
            {{ form_row(form.title) }}
            {{ form_row(form.description) }}
        </div>
        <div class="col">
            
            {{ form_row(form.todos) }}
        </div>
    </div>
    <button class="btn">{{ button_label|default('Save') }}</button>
{{ form_end(form) }}

Améliorer l’affichage des checkboxes

todos-stylees.png
Figure 5 : affichage des tâches en HTML stylé

Surcharge du gabarit par défaut… c’est faisable, mais à quel coût…

{% extends 'base.html.twig' %}

{% form_theme form _self %}
{% block _project_todos_entry_widget %}
  {% set entity = form.parent.vars.choices[form.vars.value].data %}
  {% set checked = form.parent.children[form.vars.value].vars.checked %}
  <div class="form-check">
    <input type="checkbox" id="project_todos_{{ entity.id }}"
           name="project[todos][]" class="form-check-input"
           value="{{ entity.id }}"
       {% if checked %}
           checked="checked"
       {% endif %}
     />
    <label class="form-check-label" for="project_todos_{{ entity.id }}">
      {% if entity.title is empty %}(<i>unnamed todo #{{ entity.id }}</i>)
      {% else %}{{ entity.title }}
      {% endif %}
    </label>
  </div>
{% endblock %} {# _project_todos_entry_widget #}

{% block title %}Edit Project{% endblock %}

...

Et pour le projet ?

Faites-en sorte que ça fonctionne… mais on n’est pas là pour faire une vraie application, donc ne pas faire tout cela.

Des listes à sélection multiple peuvent suffire… même si Ctrl+clic ce n’est pas formidable.

Sinon, explosion de l’effort nécessaire.

Plan de la séquence

Objectifs de cette séance (1h) :

  1. Aller au-delà des formulaires basiques Symfony
  2. Interfaces dynamiques
  3. JavaScript
  4. Manipulation du DOM
  5. AJAX

Vues générées côté serveur

doc-statique.png
Figure 6 : Documents statiques

Vues générées côté client

« HTML dynamique »

dhtml.png
Figure 7 : Documents dynamiques avec Javascript

</principes>

Plan de la séquence

Objectifs de cette séance (1h) :

  1. Interfaces dynamiques
  2. JavaScript
  3. Manipulation du DOM
  4. AJAX
  5. Architectures modernes

JavaScript pour applications Web

Abrégé : JS

  • Langage de script orienté objet non typé
  • Pilier dans la création d’applications Web
    • Principalement utilisé côté client : interprété par les navigateurs Web
    • Mais peut aussi être utilisé côté serveur (exemple NodeJS)

Intérêt d’un script côté navigateur

  • Améliorer les temps de réponse (exécution côté client, pas de latence d’envoi vers le serveur)
  • Contrôler les données des formulaires avant envoi vers le serveur (éviter les envois erronés)
  • Réaliser des pages animées
  • Modifier le contenu, le style de la page courante en fonction des actions de l’utilisateur sur la page

Historique

  • Développé en 1995 par Brendan Eich pour Netscape (nom d’origine LiveScript)
  • Grand succès au début du Web (mais nombreuses incompatibilités entre navigateurs)
  • Nombreuses étapes de standardisation nécessaires
  • L’arrivée d’AJAX avec le Web 2.0 replace JavaScript au premier plan (> 2005)

Principes de base

  • Un noyau (le cœur du langage)
    • des opérateurs, des structures, des objets prédéfinis (Date, Array…)
  • Un ensemble d’objets associés au navigateur
    • fenêtre (window), document (document), formulaire (form), image (image)…
  • Programmation événementielle
    • Capter les évènements : clics, déplacement de la souris, chargement de la page …
    • Associer des fonctions aux événements

Plate-forme

  • L’interface DOM (Document Object Model) standardise les méthodes pour accéder par objets aux documents
  • Nombreuses bibliothèques (frameworks) aident à programmer.

    Ex: Dojo, Rialto, Angular, JQuery, Yui…

  • « bytecode » pour programmer à un plus haut niveau, dans un langage compilé en JS : TypeScript, …
  • JSON (JavaScript Object Notation) utilise la notation des objets JavaScript pour transmettre de l’information structurée

    {
      "nationalTeam":"Norway",
      "achievements":[
          "12 Olympic Medals",
          "9 World Championships",
          "Winningest Winter Olympian",
          "Greatest Nordic Skier"
         ],
      "name":"Bjoern Daehlie",
      "age":41,
      "gender":"Male"
    }
    

Utilisation

Intégration dans pages HTML

  • Code JS contenu ou référencé dans balises <script> et </script>
    • Soit directement :

      <head>
          <script> 
              code javascript (fonctions, variables...)
          </script>
      </head>
      
    • Soit dans un fichier séparé (ou URL externe) :

      <head>
          <script src="monprog.js"></script>
      </head>
      

Appel des fonctions JavaScript

  • à partir d’évènements dans les balises

    <input type="button"
           onClick="alert('clic sur bouton');">
    
  • à partir d’un lien

    <a href="javascript:affiche(menu);">
    
  • par d’autres fonctions

    function hello() {
      alert("hello");
    }
    

Gestion d’événements

  • Chaque événement a un traitement par défaut
  • On peut associer une fonction à un évènement, pour l’exécuter avant traitement par défaut
    • Si retourne faux (false), alors traitement par défaut pas exécuté
    • Si retourne vrai (true), alors traitement par défaut exécuté ensuite
  • Association fonction à évènement utilise un mot-clef de type « onEvent » (onClick, onLoad, onChange, onMouseOver, onMouseOut, onKeyDown…)

Exemples de réflexes

  • clic sur bouton :

    <input type="button" name="surface" value="Surface"
           onClick="Test(all);">
    
  • déplacement souris au-dessus :

    <a href="menu.html" onMouseOver="affiche();">
    
  • fin de chargement du document :

    <body onLoad="init(1);">
    

Exemples évènements / balises

Evénements Balises Fonctions
onBlur * désélection
onChange idem modification
onFocus idem sélection
onSelect password, text, textarea sélection de valeur
onClick a href, button, checkbox, radio, reset, submit clic
onMouseover a href, area souris pointe
onLoad body chargement page
onSubmit form soumission

Exemple de gestion d’événements

<html>
    <head> 
        <script language="JavaScript">
            function maFonction() {
                alert('Vous avez cliqué sur le bouton GO');
            }
            function autreFonction() {
                alert('Cliqué sur le lien "Cliquer ici"');
            }    
        </script> 
    </head>
    <body>
      <ol>
        <li>Appel sur évènement : 
            <input type="button" value="GO" onClick="maFonction();"> 
        </li>
        <li>Appel sur un lien : 
            <a href="javascript:autreFonction();">Cliquer ici</a> 
        </li>
      </ol>
      <a href="javascript:history.go(-1);">Retour</a>
    </body>
</html>

Objets JavaScript

  • JavaScript a des types primitifs et des objets
  • Types primitifs créés par affectation directe
  • Utilisation d’objets
    • Instanciation par un constructeur
    • Syntaxe à la java :
      • Accès aux attributs : monObjet.attributs
      • Accès aux méthodes : monObjet.méthode()
    • Modèle objet beaucoup moins strict que Java

Exemple

// Création d'une variable
var etienne = {
    nom : "etienne";
    branche : "marketing";
}

// Création d'un objet par constructeur
function Employe (nom,branche) {
    this.nom = nom;
    this.branche = branche;
    this.fullDescription = function () {
        return this.nom + " " + this.branche;
    };
}

var marc=new Employe("marc","informatique");

marc.fullDescription(); // appel de méthodes

Objets prédéfinis 1/2

Les objets du noyau

  • Object : création d’un objet
  • Function : création d’une fonction
  • Array : création d’un tableau
  • String : création d’une chaîne de caractères
  • Number : création d’un nombre
  • Date : création d’une date
  • Math : création d’un objet mathématique
  • etc.

Objets prédéfinis 2/2

Les objets du navigateur :

  • fenêtre,
  • document,
  • formulaires
  • …

Hiérarchie d’objets présents en mémoire dans le navigateur

  • Un navigateur (objet navigator),
    • Contient une fenêtre (window),
      • Qui contient son document HTML (document),
        • ses formulaires (form[]), ses images (image[]), ses liens (link[])…
  • Un formulaire contient
    • des boutons (button[]),
    • des listes déroulantes (select[])
      • qui contiennent des options (option[])
  • etc.

Attributs et méthodes

  • Les attributs d’un objet correspondent aux attributs des balises HTML (par exemple height, width, name, src … pour l’objet image)
  • Les méthodes correspondent aux fonctionnalités du navigateur (par exemple back, forward, go pour l’historique (history))
  • Certains attributs et méthodes sont communs à un ensemble d’éléments

Mise au point

Délicate avec les langages interprétés car :

  • Les erreurs n’apparaissent qu’à l’éxécution
  • Par défaut, les erreurs ne sont pas affichées

Outil : console JS

  • console de développement du navigateur
    • Possibilités variables selon les navigateurs
    • Indication des erreurs de syntaxe
    • Inspection du contenu des variables
    • Débogueur, points d’arrêt, affichage des variables
  • Affichage d’informations sur la console :
    • Affichage des erreurs de syntaxe éventuelles
    • Par programme avec la fonction consoleLog(« message  » + variable)

</JavaScript>

Plan de la séquence

#<li data-fragment-index=« 1 » class=« fragment fade-out »>JQuery</li>

  1. Interfaces dynamiques
  2. JavaScript
  3. Manipulation du DOM
  4. AJAX
  5. Architectures modernes

DOM

Document Object Model (Modèle Objet du Document)

  • Modèle de la structure des documents HTML
  • Interface de programmation standardisée par le W3C (API DOM)
  • Implémentée par les navigateurs avec plus ou moins d’extensions
  • Références :

Exemple d’arbre DOM

exempleDom.png

<html>
  <head>
    ...
  </head>
  <body>
    <h1>DOM</h1>
    <div id='main'>
      <p name="p1">Le DOM trop top</p>
      <p class="p2">DOM API</p>
    </div>
    <h2>Exemples</h2>
  </body>
</html>

Manipulation avec JavaScript

  • Le DOM offre un ensemble de méthodes de parcours de l’arbre pour accéder et/ou modifier son contenu
    • ajouter des éléments
    • supprimer des éléments
    • ajouter et/ou modifier des attributs
    • etc.

Exemple d’utilisation du DOM

  • Le DOM comporte de nombreuses méthodes pour accéder à un élément, de différentes façons :
    • par son identifiant : <div id="intro">
    • par sa position dans l’arbre : (fils, parent…)
    • par son type : ensemble des paragraphes, des niveaux h2, …

Utilité

  • Modifier l’apparence
  • Par exemple, changer dynamiquement le lien (attribut class) avec des définitions de feuilles de style : interfaces réactives
  • Exemple : masquage, démasquage des slides dans reveal.js, utilisé pour les diapos projetées en CM

</manipulation_DOM>

Plan de la séquence

Objectifs de cette séance (1h) :

  1. Interfaces dynamiques
  2. JavaScript
  3. Manipulation du DOM
  4. AJAX
  5. Architectures modernes

AJAX ?

mebedjmfokgfnhjk.png
Figure 8 : Illustration When you say AJAX

AJAX

Asynchronous JavaScript And XML

  • Ne plus lire l’acronyme littéralement (XML)
  • AJAX signifie qu’on intègre différentes technologies
    • centrées sur Javascript
    • requêtes HTTP asynchrones vers serveurs
  • Traitement de données supplémentaires récupérées sur serveur(s)
  • Exemple : construction progressive d’un formulaire en fonction des réponses de l’utilisateur.

Classe XMLHttpRequest (XHR) de JavaScript

  • Élément clef de la technologie AJAX
  • Créé en 1999 par Microsoft comme objet ActiveX
  • Intégré comme objet JavaScript par Mozilla.
  • Création : new XMLHttpRequest();
  • Ensuite, utilisation comme tout objet via ses
    • propriétés
    • et/ou ses méthodes

Principe de fonctionnement

  • Un évènement (clic, saisie de texte…) provoque l’exécution d’une fonction JavaScript
  • Cette fonction
    1. instancie un objet XMLHttpRequest
    2. transmet sa requête HTTP à un serveur (GET d’un document ou POST de données, ou …)
    3. récupère la réponse lorsque celle-ci est disponible (asynchrone)
    4. met à jour la partie concernée de la page courante (un champ de saisie, une division…)

Sous-requêtes HTTP

ajax.png

Exemple d’application

Construction de formulaires dynamiques avec Symfony

</AJAX>

Take away

  • JavaScript (programmation événementielle)
  • manipulation du DOM
  • AJAX : requêtes asynchrones

Postface

Crédits illustrations et vidéos

Copyright

  • Document propriété de ses auteurs et de Télécom SudParis (sauf exceptions explicitement mentionnées).
  • Réservé à l’utilisation pour la formation initiale à Télécom SudParis.