Utiliser fullcalendar avec Angular 2

logo

Fullcalendar est un plugin jQuery très célèbre pour la gestion des rendez-vous du côté client. Il peut interagir avec des frameworks Javascript. Avec les fonctionnalités fournis par AngularJs 1, nous pouvons facilement interagir avec fullcalendar, enregistrer des dates de rendez-vous via un Web Service en utilisant l’Ajax. Mais dans notre article, nous allons voir comment le faire avec Angular 2. (Télécharger ou cloner les exemples)

Il y a deux approches que nous allons étudier avec le plugin Fullcalendar de jQuery:

  • La séparation de la logique de jQuery et Angular 2
  • L’utilisation d’Angular 2 seulement. 

Méthode 1: Séparer la logique de jQuery et Angular 2.

Comment ça marche ?

Le but de cette méthode est de créer l’instanciation ainsi que les méthodes propres au plugin dans un fichier Javascript à part. Pour cela, nous allons utiliser le Javascript Orienté Objet (Création de  classes et méthodes).

Il y a quelques méthodes pour manipuler les Objets Javascript mais j’ai choisi le prototyping.

Nous allons aussi utiliser la création d’un événement personnalisé de jQuery pour envoyer et écouter au niveau d’Angular 2 s’il y a une action déclenchée par l’utilisateur dans le fullcalendar.

Dans le fichier Javascript (jq-fullcalendar.js)

function JQFullcalendar() {
    this.selector = ".fullCalendar";
    this.options = {
        // …
        // options de fullcalendar pour l’initiation
        // …
        // quelque méthode pour émettre un événement
        viewRender: function(view, element) {
            $(document).trigger("currentData", [view.title.split(" ")[0].toLowerCase()]) // évènement personnalisé et récupération du mois correspondant
        },
        select: function(start, end) {
            // …
            $(document).trigger("eventCreate", [eventData]); // création d’un évènement personnalisée
            // …
        }
    }
}
// Quelques méthodes pour notre classe JQFullcalendar
JQFullcalendar.prototype.draw = function() {
    $(this.selector).fullCalendar(this.options);
}
JQFullcalendar.prototype.method = function(options) {
    $(this.selector).fullCalendar(options.method);
}
JQFullcalendar.prototype.onJqCustomEvent = function(event, callback) {
    $(document).on(event, callback);
}
JQFullcalendar.prototype.renderEvents = function(selector, eventData) {
    $(selector).fullCalendar("renderEvents", eventData, true);
}

Notre classe s’appelle JQFullcalendar dans laquelle nous avons implémenté quelques méthodes.

  • JQFullcalendar.prototype.draw: pour l’instanciation de fullcalendar
  • JQFullcalendar.prototype.onJqCustomEvent: pour l’écoute de notre évènement personnalisé en utilisant la fonction .on() de jQuery.
  • JQFullcalendar.prototype.renderEvents: pour l’ajout d’une date dans fullcalendar si l’utilisateur a créé.
  • JQFullcalendar.prototype.method: pour le déclenchement des méthodes propres à fullcalendar.

Nous voyons dans l’option les méthodes select et viewRender de fullcalendar qui contiennent ces instructions :

$(document).trigger("currentData", ...);

Et

$(document).trigger("eventCreate", …) ;

C’est avec la méthode trigger() de jQuery que nous créerons nos propres évènements.

Notre fichier Javascript et la classe sont maintenant créés, passons dans notre fichier Angular 2.

Dans, app.component.ts:

// … Import des dépendances
// Déclaration de notre classe JQFullcalendar
declare var JQFullcalendar: any; // pour éviter l’erreur non définie
let jqFullcalendar = new JQFullcalendar(); // instanciation de notre classe
// … Déclaration du décorateur de module
// L’export de notre classe Angular 2
export class AppComponent implements AfterViewInit{
   constructor(private http: HttpRequestService) {} // injection de dépendance
   // C’est ici que ça se passe ! 😉
   ngAfterViewInit() {
       jqFullcalendar.draw();
       // écoute de l’évènement 
       jqFullcalendar.onJqCustomEvent("eventCreate", (event, data) => {
           jqFullcalendar.renderEvents(".fullCalendar", data);
       });
       // affichage des donnés selon le mois correspondant
       jqFullcalendar.onJqCustomEvent("currentData", (event, month) => {
           // effacer tous les événements dans l’agenda
           jqFullcalendar.method("removeEvents");
           // faire une requêtte 
           this.http.get("/data/" + month + ".json").subscribe(
               (response) => {
                   for (let i = 0; i < response["length"]; i++) {
                       // afficher les donnés de l’agenda
                       jqFullcalendar.renderEvents(".fullCalendar", response[i]);
                   }
               }
           );
       });
    }
}

Sur les lignes suivantes,

declare var JQFullcalendar: any; // pour éviter l’erreur non définie

let jqFullcalendar = new JQFullcalendar(); // instanciation de notre classe

 

nous instancions notre classe JQFullcalendar.

Maintenant, nous avons accès à toutes les méthodes et propriétés de la classe JQFullcalendar que nous avons créé manuellement.

Ce qui nous intéresse le plus commence sur la ligne ngAfterViewInit(). C’est dans cette fonction que nous allons exécuter nos actions.  

ngAfterViewInit() est une méthode de la classe AfterViewInit. Elle s’exécute quand la vue sera totalement initialisée.  

Examinons de près le code:

1 – Premièrement, nous créons notre instance de fullCalendar pour l’affichage côté client avec la ligne suivante:

jqFullcalendar.draw(".fullCalendar"); 

2 – Ensuite, nous écoutons l’événement émis par notre application. Par exemple, si l’utilisateur effectue une action, tel que l’ajout d’une date, alors la ligne suivante sera exécutée:

jqFullcalendar.onJqCustomEvent("eventCreate", …)

L’utilisation des évènements personnalisés est très pratique parce qu’à chaque fois qu’il y a une manipulation dans notre agenda, nous recevons comme un genre de notification, et ensuite, nous faisons notre manipulation selon nos besoins. Cela se passe dans la ligne:

   

 jqFullcalendar.onJqCustomEvent("currentData", …)

Donc, nous sommes capables d’afficher les données retournées par le serveur ou le Web Service s’il y a une requête.

Les avantages et inconvénients de cette méthode

Avantages

  • Tout est organisé car nous avons séparé la logique de notre classe JQFullcalendar d’ Angular 2. Ce que nous avons fait dans Angular 2, c’est juste utiliser les méthodes de notre classe.
  • La mise en place des effets visuels du site peut être intégrée lors de l’intégration des pages en utilisant le POO.
  • Très pratique pour les personnes qui débutent avec Angular 2 et qui veulent interagir des plugins Javascript avec celle-ci.

Inconvénients

  • La charge de travail augmente : exécuter les plugins utilisés dans le Javascript et qui seront ensuite intégrés dans Angular 2.
  • Compliqué si on ne sait pas la POO en Javascript.

Méthode 2 : L’utilisation d’Angular 2 seulement

Comment ça marche ?

Il faut savoir que les plugins Javascript utilisent déjà le concept POO. Donc nous pouvons facilement manipuler cet Objet dans d’autres fichiers Javascript. C’est ce que nous allons voir avec cette seconde méthode. Nous allons manipuler les méthodes du plugin dans Angular 2.

Revenons sur notre exemple.

Nous allons instancier le plugin fullcalendar purement dans Angular 2. Et rendre cette application modulable.

C’est dans un fichier nommé ngFullcalendar.component.ts que nous allons mettre notre instanciation du plugin ainsi que ses méthodes.

import { Component, AfterViewInit, Output, Input, EventEmitter } from '@angular/core';
declare var jQuery: any;
var $ = jQuery;
class FullCalendarMethod {
    viewRender
    select
   // méthode propre à fullcalendar 
}
// .. décorateur pour la création du module
export class FullcalendarComponent implements AfterViewInit {
    constructor() {}
    // default options
    defaultOption: Object = {
        // … options par défaut de fullcalendar
    }
    // l’instanciation de l’événement personnalisé avec l’annotation Output
    @Output() onSelect = new EventEmitter();
    @Output() onViewRender = new EventEmitter();
    // option pour surcharger l’option par défaut
    @Input() calendarOptions: Object;
    ngAfterViewInit() {
       // surcharge de l’option
        let extendDefaultOption = $.extend({}, this.calendarOptions, this.defaultOption);
        // surcharge de l’option en ajoutant les méthodes 
        this.calendarOptions = $.extend({}, extendDefaultOption, this.fullCalendarMethod());
        // instantiation de fullcalendar
        $(".fullcalendar").fullCalendar(this.calendarOptions);
    }
    fullCalendarMethod(): Object {
        let fullCalendarMethod = <FullCalendarMethod>{};
        fullCalendarMethod.viewRender = (view, element) => {
            let viewRenderParams = {
                _view: view,
                _element: element
            }
            this.onViewRender.emit(viewRenderParams);
        };
        
        fullCalendarMethod.select = (start, end) => {
            let dateRange = {
                _start: start,
                _end: end
            }
            this.onSelect.emit(dateRange);
        }
        // ajouter d’autre méthode fullcalendar ici
        return fullCalendarMethod;
    }
}

Dans l’import des dépendances, nous avons importé : Output, Input et EventEmitter.

Dans l’annotation @Output(), nous faisons l’instanciation de l’EventEmitter.

@Output() onSelect = new EventEmitter();

Et pour émettre un événement et envoyer une donnée, nous utilisons :

this.onSelect.emit(dateRange);

La méthode qui contient cette ligne est fullCalendarMethod.select, et  select est une méthode propre à fullcalendar. Si l’utilisateur ajoute une date dans l’agenda, alors, nous émettons la date (dateRange) ajoutée grâce à la méthode .emit() d‘EventEmitter

Et la ligne

@Input() calendarOptions: Object;

permet d’envoyer l’option.

L’annotation @Input, comme son nom l’indique, veut dire entrée et permet d’envoyer des valeurs à manipuler dans le composant sur lequel nous l’avons initié (FullcalendarComponent ). Tandis que l’annotation @Output, qui veut dire sortie, permet à son tour d’envoyer une valeur émise par l’EventEmitter dans le composant  sur lequel nous allons envoyer la valeur émise (AppComponent).

Dans la vue, affichons notre module.

<app-fullcalendar

   [calendarOptions]="options"

   (onViewRender)="fetchMonthEvent($event)"

   (onSelect)="addEvent($event)"></app-fullcalendar>

Il faut noter que nous avons écrit notre Input entre crochet, c’est la façon dont Angular 2 envoie une valeur. Cette valeur sera interprétée par le module FullcalendarComponent qui surchargera notre option par défaut.

Et notre Output est écrit dans une entre parenthèse. C’est là que nous faisons notre écoute et envoyons la valeur émise par l’événement. Quand il y a une modification dans l’affichage de l’agenda, comme, ajout de date, alors l’événement ci-dessous sera déclenché et émet les données.

(onSelect)="addEvent($event)"

$event est la donnée retournée.

Pour que ces actions seront exécutées, dans le composant que nous voulons afficher l’agenda (Ici, app.component.ts), nous créons la méthode addEvent($event) et la variables options.

 

// … import des dépendances

// … décorateur du module

export class AppComponent {

    // notre valeur de l’input

    options: Object = {

        // notre options qui va surcharger l’option par défaut

    }

    // Fonction pour écouter l’évènement personnalisé.

    addEvent(data) {

    // c’est ici que se passe l’action Ajax

        // cette fonction sera exécutée à chaque fois où il y a un changement

    }

}

Avantages et inconvénients

Avantages

  • Facile à adapter pour les applications qui utilisent Angular 2.
  • Module ré-utilisable.
  • Facilite la manipulation des événements personnalisés et l’envoi des valeurs grâce à @Output et @Input.
  • Concept MVW garder.

Inconvénients

Les effets visuelles (UI) seront développés lors du développement du site côté Angular 2.

Exemple, pour l’ajout des animations (fadeIn) lors de l’affichage de l’agenda après une requête ajax, nous faisons :

 

this._http.get(addVisit).subscribe(

    (res) => {

        $(“.fullcalendar”).fullcalendar(“renderEvent”, res);
        // action fadeIn
        $(“.fullcalendar”).fadeIn(300);

    }

)

Conclusion

C’est juste un exemple sur la manière d’utiliser fullcalendar avec Angular 2.

A vous de voir si vous voulez utiliser la première ou la seconde. Mais il est recommandé d’utiliser la seconde si le projet est full Angular 2.

Tous les plugins (jQuery ou pas) peuvent interagir avec Angular 2 en utilisant ce concept 😉

Pour voir les exemples, veuillez les télécharger sur le lien et suivez les instructions pour l’installation dans le README.me ou le Wiki.

 

Enregistrer

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *