Une des puissances du javascript dans Magento 2 est de permettre de faire du chargement assynchrone sans vraiment se forcer le cerveau. Que ce soit pour charger une liste de produits ou les résultats d’un filtrage. La logique mise en place dans KnockOut va vous permettre de faire facilement des listes. Cela passe par la maîtrise des boucles avec knockout. Si vous arrivez directement sur cette page, je ne saurez que vous conseiller de jeter un œil à l’initiation à knockout avant de continuer.
Pour illustrer notre propos, nous allons voir comment mettre en place un composant qui chargera les résultats de recherche en fonction de ce que l’utilisateur saisi dans un champ. Si vous souhaitez réellement faire cela, sachez qu’il existe déjà un widget dans Magento 2 qui le fait.
Le composant de vue
Tout d’abord, nous allons créer le composant de vue. Pour cela, il nous faudra principalement deux choses :
- une variable qui sera modifiée quand l’utilisateur tapera un mot de recherche
- un tableau observable qui va contenir les résultats de notre recherche.
Il faut songer que le temps de réponse du serveur peut être supérieur à la vitesse à laquelle tape un utilisateur. C’est pourquoi, dans cet exemple précis, j’ai recours à la limitation de fréquence (rate limit) pour les observables. Cela peut être utile quand l’utilisateur est amené à effectuer des modifications rapides d’un champ mais qui n’ont besoin d’une réponse qu’une fois la saisie finie (ou au moins en pause).
define(
[
'jquery',
'uiComponent'
],
function ($, Component) {
'use strict';
return Component.extend({
defaults: {
template: 'Vendor_Module/search/result' //le fichier créé dans frontend/web/template
},
'searchInput': ko.observable(''), //cette variable sera attachée au champ de saisie
'searchResults': ko.observableArray([]), //un tableau observable est créé pour être rattaché à au html
initObservable: function () {
let self = this;
this._super().observe({});
/*
* Cela va permettre de ne pas déclencher la fonction search à chaque modification du champ
* mais 0.4s après la dernière modification par l'utilisateur. Nous n'entrerons pas dans les
* détails aujourd'hui.
* L'idée est d'utiliser une variable tampon throttledSearch qui va nous permettre d'observer
* la modification du champ mais seulement passé le délai défini.
* Chaque fois que searchInput est modifié, on calcule throttledSearch avec le délai.
*
* https://knockoutjs.com/documentation/rateLimit-observable.html
*/
this.throttledSearch = ko.pureComputed(this.searchInput).extend({
rateLimit: {
method: "notifyWhenChangesStop",
timeout: 400
}
});
//On s'inscrit aux modifications de throttledSearch plutôt qu'à ceux de searchInput
this.throttledSearch.subscribe(function (value) {
self.search(value);
}, this);
return this;
},
/**
* Cette fonction sera appelée quand la valeur du champ sera modifié et qu'un délai depuis
* la dernière modification aura été respecté pour éviter les appels en boucle (voir fonction
* initObservable).
*/
search: function (value) {
let self = this;
$.post('vendor/module/search', {
dataType: 'json',
searchTerm: value,
contentType: 'application/json',
}.done(function (response) {
//les résultats sont correctement formatés pour être exploités directement
self.searchResults(response);
}));
}
});
}
);
JavaScriptUne fois que cette partie a été créé, nous allons pouvoir passer à la suite.
Le modèle de vue
Le html doit faire référence aux deux choses importantes de notre composant de vue. A savoir, le mot recherché qui doit être envoyé au composant et les résultats qui doivent être récupérés depuis le composant.
<!--
ici, on utilisera data-bind
* pour affecter la valeur du champ à la propriété searchInput du composant
* définir quand la valeur du champ est considérée comme mise à jour
* définir de contenu du placeholder avec une traduction
-->
<div class="field search placeholder-input-box">
<input id="search" class="search-input" data-bind="value: searchInput, valueUpdate: 'keypress', attr: {placeholder: $t('Search')}"/>
<label class="label" for="search">
<span data-bind="i18n : 'Search'"></span>
</label>
</div>
<div class="subblock-items">
<!--
les lignes suivantes vont permettre de mettre à jour la liste des termes recherchés en fonction
du tableau qui contient les termes recherchés. Il n'y a rien de plus à faire.
Pour cet exemple, on imagine que le JSON qui arrive du PHP contient déjà l'ensemble des informations
dont nous avons besoin pour créer notre bouton ou notre liste (ici label et url).
-->
<!-- ko foreach: { data: searchTerms, as: 'searchTerm' } -->
<span class="subblock-item"
data-bind="
text:searchTerm.label,
click: function() {window.location = searchTerm.url }"
></span>
<!-- /ko -->
</div>
HTMLEnfin, liez les via le scope comme cela est décrit dans l’initiation à knockout.
Différentes utilisations
Cela peut également servir à :
- filtrer des produits directement sur une catégorie
- mettre en place des questions interdépendantes pour un formulaire de contact
- lister les différents moyens de paiement proposés dans un bloc de réassurance
- afficher l’ensemble des magasins physiques du groupe
- …
Laisser un commentaire
Vous devez vous connecter pour publier un commentaire.