DevExtreme, la suite à adopter de toute urgence pour développer des web apps (1/2)

Lors d’un nouveau projet de développement logiciel sur client léger, il est fréquent de recourir à des librairies d’éléments complets, évolutifs et personnalisables afin d’accroître la rentabilité en accélérant le temps en recherche et développement.

Nous ne sommes jamais à l’abri de choisir un outil qui ne sera pas pérenne face aux évolutions et qui se fera oublier s’il n’évolue pas au rythme des exigences métiers. Je vous propose de découvrir DevExtreme, une suite de composants JavaScript et HTML5, plusieurs fois élue meilleure suite de composants multiplateformes.  

DevExtreme : présentation

DevExtreme s’installe facilement au travers de distribution de « packages » bien connus tels que npm, Bower, NuGet ou tout simplement en téléchargeant un installeur, une archive depuis leur site internet.

Utilisant DevExtreme sous Angular, je travaille essentiellement en Typescript sous Visual Studio Code, mais n’importe quel IDE s’adapterait très bien à cette solution qui est très bien documentée et typée, ce qui permet par exemple une lecture aisée de ces composants ainsi qu’une autocomplétion.
Les fonctionnalités web de cette librairie sont développées afin d’être utilisées sur quasi tout navigateur, et d’expérience, travaillant des sur navigateurs récents, je n’ai jamais rencontré de problème lié à la compatibilité.

De plus, les débogueurs de ces navigateurs permettent, comme pour toute application web, de dérouler pas à pas le code afin de maîtriser au mieux ses réalisations applicatives. Toutefois, il peut être assez ardu au début de saisir la logique d’une librairie aussi complète que DevExtreme. C’est pourquoi en plus de pages de démonstration multi-langages sur le site de l’éditeur, des pages de documentation dynamique sont associées aux exemples de démonstration. Un centre de support via un forum d’aide est également disponible. Et si vous optez pour une version commerciale, un support technique (avec accès prioritaire en option) vous suivra pour le temps de votre abonnement.

Cette suite de composants est libre d’accès et d’usage à des fins non-commerciales et propose une solution complète payante pour un usage commercial comprenant le « Theme Builder » ainsi que 12 mois de mise à jour et de support (une version complète avec option de support prioritaire en sus est également disponible).

La licence commerciale de DevExtreme permet de distribuer des applications libres de droit construites au travers de ces composants, même une fois l’abonnement expiré. Cette licence peut être renouvelée pour 12 mois supplémentaire avec une réduction d’environ 40% si son prolongement est acté dans le mois suivant sa péremption. Cette licence est à attribuer à chacun des développeurs de l’équipe de développement travaillant avec cette suite de composants. Elle est cessible entre développeur et existe en tarifs préférentiels pour des achats par lots.

Les fonctionnalités de DevExtreme

DevExtreme propose une collection complète de plus de 65 composants UI pour web apps et applications mobiles tels que les « Datagrid », « Charts » et « Forms ». Très réactifs et performants, ces éléments applicatifs sont couramment utilisés en informatique de gestion et informatique industrielle.

Vous pourrez rapidement élaborer une application web, de sa structure HTML responsive conçue au travers de plusieurs thèmes (il est possible d’exporter, d’importer, d’éditer et/ou de surcharger vos styles et thèmes avec le « Theme Builder »), en passant par une série de composants faciles à mettre en place, comme une grille de données paginée avec un système de recherche avancée et d’export des éléments remontés.

Pour prendre en main ces différents widgets, chaque composant est présenté sur le site de l’éditeur au travers d’exemples tous modifiables et testables dynamiquement avec plus de 250 cas d’utilisation dans différents langages de programmation. La solution est facile et rapide à assimiler car chaque composant se déclare et se personnalise de la même manière. Une fois cette logique acquise, on gagne un temps précieux dans l’implémentation et l’utilisation des composants au sein de l’applicatif web développé.

 

MULTIPLATEFORMES

Que vous développiez sous Angular avec Typescript, en JavaScript avec jQuery, ou encore ASP.net, DevExtreme propose les mêmes fonctionnalités.

 

EXEMPLE PAR LA PRATIQUE

Voyons l’usage de cette solution autour d’un exemple développé en Angular avec Typescript et basé sur la création de quelques composants : un système de notification « Notify » permettant d’indiquer les actions, une Datagrid* « DxDatagrid » simple avec filtres, une pagination et une Toolbar* présentant un bouton de mise à zéro des filtres en sus. Pour pointer de la souris l’aspect personnalisable de la suite DevExtreme, nous surchargerons la dernière colonne de cette Datagrid en y ajoutant, à travers un template de cellule, un composant de bouton « DxButton » ouvrant un popup « DxPopup » (laissé par défaut pour l’exemple) sur l’événement « click » de ce bouton.

APERÇU D’UNE DATAGRID SIMPLE

La Datagrid est l’expression d’une Datasource simple présentant une liste d’enregistrements de l’objet ExampleData créé pour l’occasion.

Liste d’objets ExampleData :

let data: ExampleData[] =
[
 {id : 1, name: "Dx Radio",status: "todo",custom: true},
 {id : 2, name: "Dx datagrid",status: "error",custom: true},
 {id : 3, name: "Dx popup",status: "done",custom: false},
 {id : 4, name : "Dx button",status : "warning",custom : true},
 {id : 5, name: "Dx form",status: "in progress",custom: false},
 {id : 6, name: "Dx Text",status: "done",custom: true}
];

ExampleData typing :

export classExampleData{
 id: number;
 name: string;
 status: string;
 custom: boolean;
}

 

LES COMPOSANTS DEVEXTREME EN DÉTAIL

Pour notre exemple, nous développons sous Angular avecTypescript, les composants DevExtreme préfixés « DX », rapidement mis en place si on est familiarisé avec les concepts de base et les modèles d’Angular :

<dx-button
 type="default"
 [disabled]="data.value"
 text="label of button"
 [visible]="true" 
 (onClick)="click($event, data)">
</dx-button>

Dans ce bout de code, nous retrouvons une notion d’Angular concernant les liaisons d’un attribut ou d’un évènement au moyen d’une syntaxe :

Dans ce bout de code, nous retrouvons une notion d’Angular concernant les liaisons d’un attribut ou d’un événement au moyen d’une syntaxe :

  • [] pour les attributs, class, interpolation… « One-Way Option Binding » :

« From the source-to-view »

  • () pour les événements

« One-way from view target to data source »

  • [()] ou encore le « Two-Way Option Binding »

« Two-way sequence: view-to-source-to-view »

Dans cette directive, nous aurions pu envisager de déclarer toutes les variables de ses attributs dans le Controller de la Single Page Application (SPA) et de les lier avec la syntaxe [attr]= «variable public» proposée par Angular.

L’intérêt de cette approche réside dans le proverbe « qui peut le plus, peut le moins » : en effet on peut opter pour une approche moins dynamique avec une valeur statique comme ici pour l’attribut « text »,  l’attribut typé « string » et qui peut prendre une valeur statique sans One-way binding. On peut aussi renseigner directement la valeur attendue ; c’est le cas de l’attribut « visible » du dx-button présenté. A noter que cette valeur typée « boolean » sera prise en compte avec One-way binding. De plus, valorisé à ‘true’, cet attribut « visible » n’a d’intérêt que la sémantique de l’exemple du fait que sa valeur par défaut est fixée à ‘true’ par DevExtreme, et que nous ne souhaitons pas masquer dynamiquement ce bouton.
Il est même possible de passer par une approche jQuery qui initialisera un objet « Dx » au moyen d’une configuration prise en charge par la directive. Pratique pour éditer et sauvegarder une configuration du composant à partir d’un « json » sérialisé en base de données ou en variable de session.

 

DÉFINITION DE LA DATAGRID DANS LA VUE

DÉCLARATION DE LA DATAGRID DANS LA VUE

<!-- Datagrid with toolbar and custom column -->

<dx-data-grid #datagrid [dataSource]="dataSource"

  (onToolbarPreparing)="toolbarPreparing($event)">
  • La datagrid peut se définir par défaut juste par son tag
  • La datasource est liée au controller
  • On définit l’appel à la methode « toolbarPeraring() » durant l’événement « onToolbarPreparing » déclenché par le composant.

ACTIVATION DES FILTRES DATAGRID PAR SIMPLE ATTRIBUT “VISIBLE”

  <!-- Header Filtering. -->

  <dxo-filter-row [visible]="true"></dxo-filter-row>
  • On déclare les filtres.

Note : Chaque composant possède de nombreux événements permettant toute une série d’actions.

CONFIGURATION DE LA PAGINATION

  <!-- Pagination. -->

  <dxo-paging [pageSize]="3" [pageIndex]="0"

              [enabled]="true"></dxo-paging>

  <dxo-pager [allowedPageSizes]="[3, 6, 10, 25]"

    [visible]="false" [showPageSizeSelector]="true"   

    [showNavigationButtons]="true" [showInfo]="true"></dxo-pager>
  • On paramètre la pagination
  • On spécifie les outils de navigation de cette pagination

DÉCLARATION DES COLONNES DE LA DATAGRID

<!-- Columns -->

  <dxi-column dataField="id" caption="ID#" [visible]="true"

              width="50" alignment="center"></dxi-column>

  <dxi-column dataField="name" caption="Name" [visible]="true"

              width="150"></dxi-column>

  <dxi-column dataField="status" caption="Status" [visible]="true"

              width="100" alignment="center"></dxi-column>

  <dxi-column dataField="custom" caption="Custom"

              cellTemplate="cellTemplate" [allowFiltering]="false"

              [allowSorting]="false" alignment="center"

              width="150"></dxi-column>
  • On déclare les colonnes de la Datagrid. On peut choisir de les laisser par défaut, de les restreindre ou de les personnaliser.
  • Tous les éléments de configuration sont listés et présentés en détails dans la documentation de DevExtreme.
  • Sur la dernière colonne nommée « custom », nous avons défini un template de cellule dans l’attribut « cellTemplate ».

SURCHARGE DE LA DERNIÈRE COLONNE AVEC UN TEMPLATE PERSONNALISÉ

<div *dxTemplate="let data of 'cellTemplate'">

    <!-- In the last column of the datagrid we add an action button -->

    <dx-button type="default" [disabled]="data?.value" 
                         text="label of button" (onClick)="click($event, data)">
    </dx-button>

  </div>




</dx-data-grid>
  • Au sein du « dx-data-grid » nous déclarons le template html cellTemplate en y ajoutant tout ce dont nous avons besoin.
  • Dans notre exemple nous rajoutons un composant DevExtreme : le « dx-button »
  • Nous le configurons de manière à le désactiver en fonction d’une valeur spécifique à l’occurrence de l’objet « ExampleData », un texte, un type, et on y lie une méthode sur l’événement «  Click ».

PETIT TOUR CÔTÉ CONTROLLER

  • Pour plus de visibilité, nous déclarons une variable refreshBtnToolbar en dehors de l’événement « toolbarPreparing ».
  • Les items de Toolbar sont configurés avec :
    •  Une location afin de choisir son emplacement
    • Un widget permettant de lui donner la nature du composant DevExtreme à utiliser
    • Un objet « options » regroupant la configuration du composant défini dans le widget

EXEMPLE DXBUTTON COMME WIDGET D’UNE TOOLBAR

// DxButton widget with composant configuration in options 

public refreshBtnToolbar: DxToolbarComponent.items = {

        location: "after",

        widget: "dxButton",

        locateInMenu: "auto",

        options: {

              icon: "pulldown",

              hint: "Clear & Reload",

              onClick: (e: Event): void => this.ClearRefreshAction(e)

        }

};

Lors de la construction de la Datagrid, on peut intervenir à différents moments (création des lignes, des cellules, de la barre d’outils…).

  • L’évènement toolbarPreparing permet d’éditer cette toolbar.
  • En récupérant « event » passé par cet événement, nous pouvons manipuler l’instance de l’objet « DxToolbarComponent » et ainsi en éditer ses items.

 AJOUT D’ÉLÉMENTS LORS DE L’ÉVÉNEMENT DE PRÉPARATION DE LA TOOLBAR

// Event DevExtreme during the datagrid’s toolbar building

private toolbarPreparing(event: Event) {
    // we get back the list of DxToolbarComponent.items instance
    const toolbarItems: DxToolbarComponent.items = event.toolbarOptions.items;
     // jQuery typical form
    // we add a DxButton widget in toolbar by passing a configuration object
    toolbarItemsref.push(this.reshBtnToolbar);
    // We can edit the properties them as we wish from the moment
   // we get back the DxToolbarComponent.items instance
    toolbarItems.forEach(
      // for each toolbar item we change the location at « before »
      (item: DxToolbarComponent.items): void => {
        item.location = "before";
      });
 }
  • Il est alors facile d’ajouter aux items de la toolbar le widget configuré ci-dessus (cf. figure 10), par une simple méthode « push ».
  • La boucle « forEach » développée ci-contre permet de cibler les actions de personnalisation et de contrôle que nous avons dans tous les composants. En effet, dans cet exemple nous parcourront tous les items présents dans la toolbar et nous en changeons leurs « location ».

ACTION DE SUPPRESSION DES FILTRES ET RECHARGEMENT

@ViewChild("datagrid", { static: false }) _datagrid: DxDataGridComponent;


  private ClearRefreshAction (event: Event) {

          // Notify
         notify({

            message: `Click on the toolbar button "Clear & Reload" triggered!`,

            type: "success",

            position: { at: "center", my: "center",  offset: "0 52" },

            width: 250,  duration: 500

          });

          // Event Clear filter action

          this._datagrid.instance.clearFilter();

          // Reload Datagrid

          this._datagrid.dataSource = this.dataSource;

          this._datagrid.instance.getDataSource().reload();

  }
  • A cet élément bouton, nous avons ajouté l’appel à la méthode « ClearRefreshAction() » sur l’événement « Click »
  • Le paramètre d’événement passé en argument de la méthode peut nous permettre de récupérer l’instance du DxButton au besoin.
  • L’instance de la Datagrid est récupérée au moyen du @ViewChild proposé par Angular. A noter qu’avec une approche jQuery nous aurions pu récupérer l’instance de cette manière : $(“#dataGridContainer”).dxDataGrid(“instance”)
  • Pour effacer les filtres et recharger la Datagrid, il suffit de se laisser guider. Toutes les méthodes sont déjà développées pour le composant.

DÉCLARATION D’UNE DXPOPUP BASIQUE DANS LA VUE

Voyons maintenant de plus près un composant régulièrement utilisé : le « popup ». Il se configure directement depuis la vue sans passer par le controller.

<dx-popup
  [width]="260"  [height]="240"  [showTitle]="true"  [title]="currentRow.name"
  [dragEnabled]="false"  [closeOnOutsideClick]="true"  [(visible)]="popupVisible"
  (onShown)="shown($event)">

  <div *dxTemplate="let data of 'content'">

    <div class="popup-property-details">
      <pre>{{ currentRow | json }}</pre>

    </div>

  </div>

</dx-popup>

Nous voyons dans cet extrait que la configuration est très accessible, la simple lecture de sa déclaration se suffit à elle-même pour imaginer le rendu que nous obtiendrons.

  • L’attribut « visible » est défini comme « Two-Way Option Binding » afin que la variable « popupVisible » puisse renseigner l’état du popup
  • La méthode « shown() » est définie pour l’événement « onShown » déclenché à l’ouverture du popup. Dans cet exemple, cette méthode permet l’affichage d’une notification DevExtreme.

 

 

Découvrez la suite dans le prochain article mardi prochain. Je vous proposerai d’aller plus en détail dans la configuration du composant “Datagrid”.

Article initialement paru dans Programmez! n°234