Blog de Philip Doxakis    LinkedIn    GitHub    RSS

Avez-vous vraiment besoin de jQuery?

Introduction

En développement web, jQuery est une formidable librairie que vous utilisez probablement pour créer des pages web dynamiques. Elle permet de faire mille et une choses. À une certaine époque, elle permettait de pallier aux grandes différences entre les navigateurs web. De nos jours, c’est un peu moins vrai. On s’en sert principalement, car c’est une technologie ennuyeuse. Ce n’est pas péjoratif. Bien au contraire. La technologie est mature et présente peu ou pas de chance de changer à l’avenir.

De nos jours, il y a de nouvelles librairies plus intéressantes. Je pense à angularjs, react, vuejs, knockoutjs, etc. Bref, quelles technologies choisir en tenant compte du développement et de la maintenance?

On veut être à jour, moderne, mais en même temps, il ne faut pas se tirer dans le pied. Peu importe la technologie, selon moi, l’élément intemporel est qu’il faut faire des choix comportant idéalement le moins de dépendance. Car, si l’on prend une mauvaise décision, il faut pouvoir corriger le tir.

Quelle technologie ?

Dans cette optique, je vous propose donc qu’on s’intéresse à knockoutjs. Elle peut être intégrée/retirée progressivement. Elle n’est pas invasive et elle peut être utilisée pour une page seulement. Elle permet de faire sensiblement la même chose que jQuery. La différence fondamentale est qu’on ne modifie pas directement le DOM. On utilise plutôt une représentation du modèle en JavaScript. La vue se met à jour en fonction du modèle. On décrit la vue selon un template.

Oui, mais je dois mettre à jour le DOM. J’ai des besoins particuliers…

Je vous suggère de consulter la documentation. On peut créer des bindings. En gros, on isole les manipulations du DOM et on les rend plus génériques et réutilisables. Le modèle devient donc riche et il contient à peu près juste la logique d’affaires.

Intégration proposée

Bien souvent, ils encouragent à utiliser des requêtes ajax pour obtenir et soumettre les données des formulaires. On serait même tenté de créer un api web pour répondre à ce besoin.

Toutefois, je vous propose une manière de faire les choses avec moins de code JavaScript. Il s’agit d’une proposition. Libre à vous de prendre les parties que vous jugez intéressantes pour votre organisation.

Le compromis

Vous pourrez utiliser cette astuce lorsque vous avez un ensemble d’éléments associés à une entité qu’on crée ou modifie. (Relation 1 à plusieurs)

Prenons un exemple simple:

Supposons que l’entité est un groupe d’une classe d’école et que l’ensemble d’éléments associés est les élèves inscrits.

Il suffit de créer un formulaire classique en HTML pour les propriétés d’un groupe d’une classe d’école. Par exemple, il y aurait les propriétés: lieu et professeur assigné.

Pour ce qui est des élèves, on va mélanger knockoutjs + un formulaire classique.

L’astuce est:

  • On utilise knockoutjs pour gérer les éléments dynamiques. Dans notre cas: les élèves.
  • On définit le champ “Nom” du formulaire à l’aide de knockoutjs.

Autrement dit, on ramène un formulaire avec du JavaScript à un formulaire classique en HTML.

<!-- Formulaire classique -->
<input type="text" name="Lieu" />
<input type="text" name="Professeur" />

<!-- Partie dynamique -->
<div data-bind="foreach: Eleves">
    <input type="hidden" data-bind="value: Id, attr: { name: 'Eleves[' + $index() + '].Id' }" />
    
    <input type="text" data-bind="value: Nom, attr: { name: 'Eleves[' + $index() + '].Nom' }" />

    <a href="#" data-bind="click: $root.removeEleve">Supprimer</a>
</div>
<a href="#" data-bind="click: $root.addEleve">Ajouter</a>

Implémentation possible avec ASP.NET MVC

Si vous utilisez ASP.NET MVC, vous aurez donc la validation côté serveur.

Il faut prévoir la sérialiser du modèle en un objet JavaScript.

Son modèle c# vers JavaScript

Vous pourriez vous créer un helper pour faire la conversion.

using Newtonsoft.Json;
using System;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;

public static class HtmlExtensions
{
    public static MvcHtmlString GetDisplayName<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression
    )
    {
        var metaData = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);
        string value = metaData.DisplayName ?? (metaData.PropertyName ?? ExpressionHelper.GetExpressionText(expression));
        return MvcHtmlString.Create(value);
    }

    public static MvcHtmlString CSharpModelToJavascript<TModel>(
        this HtmlHelper<TModel> htmlHelper,
        string name,
        object model
    )
    {
        var script = "<script>" +
            "var " + name + " = JSON.parse(\"" +
                HttpUtility.JavaScriptStringEncode(
                    JsonConvert.SerializeObject(model)) + "\");" +
            "</script>";

        return MvcHtmlString.Create(script);
    }
}

Dans la vue, voici la syntaxe :

@Html.CSharpModelToJavascript("model", Model)

Objet JavaScript vers un “view model” knockoutjs

C’est bien beau créer son view model en JavaScript. Cela peut devenir répétitif. Il existe un outil pour faire le mapping à votre place. Il s’agit de : knockout.mapping. L’objectif est de réduire la quantité de code JavaScript.

<script>
    @Html.CSharpModelToJavascript("model", Model)
    
    // Créer le view model à partir d'un objet JavaScript.
    var viewModel = ko.mapping.fromJS(model);
    
    // Créer un élève (modèle)
    @Html.CSharpModelToJavascript("newModel", new EleveModel())

    // Événements dynamiques:
    viewModel.removeEleve = function (data) {
        viewModel.Eleves.remove(data);
    }
    viewModel.addEleve = function () {
        // Ajouter un élève. (On le crée en faisant une copie)
        viewModel.Eleves.push(ko.mapping.fromJS(newModel));
    }

    ko.applyBindings(viewModel);
</script>

Conclusion

Il existe d’autres librairies matures qui peuvent réellement faire la différence. Faites vos recherches et utilisez un outil adapté à vos besoins!