Ajax
Le module AMD elgg/Ajax
(introduit dans Elgg 2.1) fournit un ensemble de méthodes pour communiquer avec le serveur d’une manière concise et uniforme, ce qui permet aux plugins de collaborer sur les données de requête, la réponse du serveur et les données renvoyées côté client.
Contenu
Aperçu
Toutes les méthodes ajax effectuent ce qui suit :
Côté client, l’option
data
(si elle est donnée en tant qu’objet) est filtrée par le hookajax_request_data
.La requête est faite au serveur, que ce soit en affichant une vue ou un formulaire, en appelant une action, ou en chargeant un chemin d’accès.
La méthode renvoie un objet
jqXHR
, qui peut être utilisé comme promesse - Promise.Le contenu généré par le serveur est transformé en objet de réponse (
Elgg\Services\AjaxResponse
) contenant une chaîne (ou une valeur parsée en JSON).L’objet de réponse est filtré par l’événement
ajax_response
.L’objet de réponse est utilisé pour créer la réponse HTTP.
Côté client, les données de réponse sont filtrées par le hook
ajax_response_data
.La promesse - promise -
jqXHR
est résolue et toutes les fonctions de rappelsuccess
sont appelées.
Plus de notes :
Tous les hooks ont un type en fonction de la méthode et du premier argument. Voyez ci-dessous.
Par défaut, le module
elgg/spinner
est automatiquement utilisé lors des requêtes.Les messages utilisateur générés par
elgg_register_success_message()
etelgg_register_error_message()
sont collectés et affichés sur le client.Elgg intègre un gestionnaire d’erreurs par défaut qui affiche un message générique en cas d’échec de la sortie.
Les exceptions PHP ou les codes d’erreur HTTP d’accès refusé, ce qui entraîne l’utilisation du gestionnaire d’erreurs côté client.
La méthode HTTP par défaut est
POST
pour les actions, sinonGET
. Vous pouvez changer cela viaoptions.method
.Si une valeur
options.data
non vide est donnée, la méthode par défaut est toujoursPOST
.Pour la mise en cache côté client, définissez la méthode
options.method
surGET
etoptions.data.elgg_response_ttl
sur l’âge maximal que vous souhaitez en secondes.Pour enregistrer des messages système pour le chargement de la page suivante, définissez
options.data.elgg_fetch_messages = 0
. Vous pourriez vouloir faire cela si vous avez l’intention de rediriger l’utilisateur en fonction de la réponse.Pour empêcher l’API côté client d’exiger des modules AMD requis côté serveur avec
elgg_require_js()
, définissezoptions.data.elgg_fetch_deps = 0
.Toutes les méthodes acceptent une chaîne de requête comme premier argument. Cette chaîne est transmise à l’URL de récupération, mais n’apparaît pas dans les types de hooks.
Effectuer des actions
Considérez cette action :
// in myplugin/actions/do_math.php
elgg_ajax_gatekeeper();
$arg1 = (int)get_input('arg1');
$arg2 = (int)get_input('arg2');
// will be rendered client-side
elgg_register_success_message('We did it!');
echo json_encode([
'sum' => $arg1 + $arg2,
'product' => $arg1 * $arg2,
]);
Pour l’exécuter, utilisez ajax.action('<action_name>', options)
:
var Ajax = require('elgg/Ajax');
var ajax = new Ajax();
ajax.action('do_math', {
data: {
arg1: 1,
arg2: 2
},
}).done(function (output, statusText, jqXHR) {
alert(output.sum);
alert(output.product);
});
Notes pour les actions :
- Tous les hooks ont le type
action:<action_name>
. Donc, dans ce cas, trois hooks seront déclenchés : côté client
"ajax_request_data", "action:do_math"
pour filtrer les données de la requête (avant qu’elle soit envoyée)côté serveur
"ajax_response", "action:do_math"
pour filtrer la réponse (après que l’action a été exécutée)côté client
"ajax_response_data", "action:do_math"
pour filtrer les données de la réponse (avant que le code appelant ne les reçoive)
- Tous les hooks ont le type
Les jetons CSRF sont ajoutés aux données de la requête.
La méthode par défaut est
POST
.Une URL d’action absolue peut être donnée à la place du nom d’action.
Note
Lorsque vous définissez data
, utilisez ajax.objectify($form)
au lieu de $form.serialize()
. Cela permet au hook de plugin ajax_request_data
d’être déclenché, et à d’autres plugins de modifier / réagir à la requête.
Récupérer des données
Considérez ce script PHP qui s’exécute à http://example.org/myplugin_time
.
// in myplugin/elgg-plugin.php
return [
'routes' => [
'default:myplugin:time' => [
'path' => '/myplugin_time',
'resource' => 'myplugin/time',
],
],
];
// in myplugin/views/default/resources/myplugin/time.php
elgg_ajax_gatekeeper();
echo json_encode([
'rfc2822' => date(DATE_RFC2822),
'day' => date('l'),
]);
return true;
Pour récupérer sa sortie, utilisez ajax.path('<url_path>', options)
.
var Ajax = require('elgg/Ajax');
var ajax = new Ajax();
ajax.path('myplugin_time').done(function (output, statusText, jqXHR) {
alert(output.rfc2822);
alert(output.day);
});
Notes pour les chemins :
Les 3 hooks (voyez les Actions ci-dessus) auront le type
path:<url_path>
. Dans ce cas, « path:myplugin_time ».Si le gestionnaire de page renvoie une page Web normale,
output
sera une chaîne contenant le HTML de la page.Une URL absolue peut être donnée à la place du nom du chemin.
Récupérer des vues
Considérez cette vue :
// in myplugin/views/default/myplugin/get_link.php
if (empty($vars['entity']) || !$vars['entity'] instanceof ElggObject) {
return;
}
$object = $vars['entity'];
/* @var ElggObject $object */
echo elgg_view('output/url', [
'text' => $object->getDisplayName(),
'href' => $object->getUrl(),
'is_trusted' => true,
]);
Comme il s’agit d’un fichier PHP, nous devons d’abord l’enregistrer pour Ajax :
// in myplugin_init()
elgg_register_ajax_view('myplugin/get_link');
Pour récupérer la vue, utilisez ajax.view('<view_name>', options)
:
var Ajax = require('elgg/Ajax');
var ajax = new Ajax();
ajax.view('myplugin/get_link', {
data: {
guid: 123 // querystring
},
}).done(function (output, statusText, jqXHR) {
$('.myplugin-link').html(output);
});
Notes pour les vues :
Les 3 hooks (voyez les Actions ci-dessus) auront le type
view:<view_name>
. Dans ce cas, « view:myplugin/get_link ».output
sera une chaîne avec le contenu de la vue générée.Les données de la requête sont injectées dans la vue à l’intérieur de
$vars
.Si les données de la requête contiennent
guid
, le système définit$vars['entity']
à l’entité correspondante ou àfalse
si elle ne peut pas être chargée.
Avertissement
Dans les vues et les formulaires ajax, notez que $vars
peut être peuplé par les saisies du client. Les données sont filtrées comme avec get_input()
, mais peuvent ne pas avoir le type que vous attendez ou peuvent avoir des clefs inattendues.
Récupérer des formulaires
Considérez que nous avons une vue de formulaire. Nous l’enregistrons pour Ajax :
// in myplugin_init()
elgg_register_ajax_view('forms/myplugin/add');
Pour récupérer ceci utilisez ajax.form('<action_name>', options)
.
var Ajax = require('elgg/Ajax');
var ajax = new Ajax();
ajax.form('myplugin/add').done(function (output, statusText, jqXHR) {
$('.myplugin-form-container').html(output);
});
Notes pour les formulaires :
Les 3 hooks (voir Actions ci-dessus) auront le type
form:<action_name>
. Dans ce cas, « form:myplugin/add ».output
sera une chaîne avec le contenu de la vue générée.Les données de la requête sont injectées dans
$vars
dans la vue de votre formulaire.Si les données de la requête contiennent
guid
, le système définit$vars['entity']
à l’entité correspondante ou àfalse
si elle ne peut pas être chargée.
Note
Seules les données de la requête sont transmises à la vue du formulaire demandé (c’est-à-dire en tant que troisième paramètre accepté par elgg_view_form()
). Si vous devez transmettre des attributs ou des paramètres de l’élément de formulaire rendus par la vue input/form
(c’est-à-dire normalement passés comme deuxième paramètre à elgg_view_form()
), utilisez l’événement côté serveur view_vars , input/form
.
Avertissement
Dans les vues et les formulaires ajax, notez que $vars
peut être peuplé par les saisies du client. Les données sont filtrées comme avec get_input()
, mais peuvent ne pas avoir le type que vous attendez ou peuvent avoir des clefs inattendues.
Envoyer des formulaires
Pour envoyer un formulaire avec Ajax, il suffit de passer le paramètre ajax
avec des variables de formulaire :
echo elgg_view_form('login', ['ajax' => true]);
Redirections
Utilisez ajax.forward()
pour démarrer une animation d’attente - spinner - et rediriger l’utilisateur vers une nouvelle destination.
var Ajax = require('elgg/Ajax');
var ajax = new Ajax();
ajax.forward('/activity');
Réagir - « piggybacking » - lors d’une requête Ajax
Le hook ajax_request_data
côté client peut être utilisé pour ajouter ou filtrer les données envoyées par une demande elgg/Ajax
.
Supposons que lorsque la vue foo
est récupérée, nous voulons également envoyer au serveur quelques données :
// in your boot module
var Ajax = require('elgg/Ajax');
var hooks = require('elgg/hooks');
var ajax = new Ajax();
hooks.register(Ajax.REQUEST_DATA_HOOK, 'view:foo', function (name, type, params, data) {
// send some data back
data.bar = 1;
return data;
});
Ces données peuvent être lues côté serveur via get_input('bar');
.
Note
Si les données ont été fournies sous forme de chaîne (par ex. $form.serialize()
), les hooks de requête ne sont pas déclenchés.
Note
Le formulaire sera transformé en objet nommé FormData
, et le type de contenu de la requête sera déterminé en conséquence.
Réagir à une réponse Ajax
L’événement ajax_response
côté serveur peut être utilisé pour ajouter ou filtrer les données de réponse (ou métadonnées).
Disons que lorsque la vue foo
est récupérée, nous voulons également envoyer au client quelques données supplémentaires :
use Elgg\Services\AjaxResponse;
function myplugin_append_ajax(\Elgg\Event $event) {
/* @var $response AjaxResponse */
$response = $event->getValue();
// alter the value being returned
$response->getData()->value .= " hello";
// send some metadata back. Only client-side "ajax_response" hooks can see this!
$response->getData()->myplugin_alert = 'Listen to me!';
return $response;
}
// in myplugin_init()
elgg_register_event_handler(AjaxResponse::RESPONSE_EVENT, 'view:foo', 'myplugin_append_ajax');
Pour capturer les métadonnées renvoyées au client, nous utilisons le hook ajax_response_data
côté client :
// in your boot module
var Ajax = require('elgg/Ajax');
var hooks = require('elgg/hooks');
hooks.register(Ajax.RESPONSE_DATA_HOOK, 'view:foo', function (name, type, params, data) {
// the return value is data.value
// the rest is metadata
alert(data.myplugin_alert);
return data;
});
Note
Seule la valeur data.value
est renvoyée à la fonction success
, ou disponible via l’interface Deferred.
Note
Elgg utilise ces mêmes hooks pour diffuser des messages système via les réponses elgg/Ajax
.
Gérer les erreurs
Les réponses correspondent à l’une de ces trois catégories :
Succès HTTP (200) avec un statut
0
. Aucun appelelgg_register_error_message()
n’a été fait sur le serveur.Succès HTTP (200) avec le statut
-1
.elgg_register_error_message()
a été appelé.Erreur HTTP (4xx/5xx). Par ex. appeler une action avec des jetons expirés, ou une exception sur le serveur. Dans ce cas les fonctions de callback
done
ne sont pas appelées.
Le premier et le troisième cas sont les plus courants dans le système. Utilisez les callbacks done
et fail
pour différencier le comportement en cas de succès et d’erreur.
ajax.action('entity/delete?guid=123').done(function (value, statusText, jqXHR) {
// remove element from the page
}).fail(function() {
// handle error condition if needed
});
Requérir des modules AMD
Chaque réponse d’un service Ajax contiendra une liste de modules AMD requis côté serveur avec elgg_require_js(). Lorsque les données de réponse sont déballées, ces modules seront chargés de façon asynchrone - les plugins ne doivent pas s’attendre à ce que ces modules soient chargés dans leurs gestionnaires $.done() et $.then() et doivent utiliser require() pour tous les modules dont ils dépendent. En outre, les modules AMD ne doivent pas s’attendre à ce que le DOM ait été modifié par une demande Ajax lorsqu’ils sont chargés - les événements DOM doivent être délégués et les manipulations sur les éléments DOM doivent être retardées jusqu’à ce que toutes les requêtes Ajax aient été résolues.