Réponse AJAX en cascade pour accéder aux objects “hasChildren” qui ne sont pas inclus dans l’object JSON

J’essaie de créer un menu déroulant comportant des objects de niveau enfant et petit-enfant auxquels je dois accéder et qui ne sont pas inclus dans la réponse initiale d’un appel ajax.

J’utilise cette structure pour mon appel ajax en cascade:

$.ajax({ url:"../../api/getEnum", data: {itemFilter: "", Id: "~some guid~"}, dataType: "json", success: function(data){ var dropdownObject = []; dropdownObject.push(''); $(data).each(function(){ //optgroup level if($(this)[0].HasChildren == true){ dropdownObject.push(''); $.ajax({ url:"../../api/getEnum", data: {itemFilter: "", Id: $(this)[0].Id}, dataType: "json", success: function(data){ $(data).each(function(){ //prepend level if($(this)[0].HasChildren == true){ var prependage = $(this)[0].Text; $.ajax({ url:"../../api/getEnum", data: {itemFilter: "", Id: $(this)[0].Id}, dataType: "json", success: function(data){ $(data).each(function(){ dropdownObject.push('' + prependage + ": " + $(this)[0].Text + ''); }) } }) } }) } }) dropdownObject.push(''); } else { dropdownObject.push('' + $(this)[0].Text + ''); } }); $('#dropDown').html(dropdownObject.join('')); $("#dropDown").sortinggger("chosen:updated"); //needs to be done to sortinggger the update of my drop down with "Chosen plugin" after all options have been built. } }) 

Voici un exemple du résultat de données avec lequel je travaille:

 ...{Id: "~some guid~", Text: "Medium", Name: "Medium", HasChildren: true,…}... 

Donc, si HasChildren est true, je dois mettre en cascade un nouvel appel à l’API par rapport au GUID du parent. En raison de l’asynchronicité d’AJAX, je pense que l’interface utilisateur ne construit que les options de niveau supérieur sans enfants. Pour les performances, je ne veux pas désactiver l’async, mais je ne sais pas comment obtenir mes réponses au bon moment et dans le bon ordre.

Je pense que j’aurais probablement besoin de créer une fonction de rappel pour gérer le séquencement, puis d’exécuter le déclencheur de mise à jour à la fin de celui-ci, mais je n’ai pas beaucoup d’expérience avec cela et je ne suis pas sûr que ce soit la bonne direction.

Merci pour l’aide!

Tout d’abord, il y a 2 affirmations que je ne comprends pas (lignes 7 à 8):

 var areaOption = []; dropdownObject.push(''); 

Peut-être que le premier est utile ailleurs, alors ok (bien que vous fassiez probablement mieux de le mettre en dehors de la success: fonction).
Mais je ne vois pas comment le deuxième pourrait être légitime.

Structure de données source.

En ce qui concerne les niveaux nesteds, je suis surpris que vous disposiez de 3 niveaux, alors qu’il semble que seuls 2 pourraient faire le travail. Quand les enfants existent, vous construisez quelque chose comme ceci:

    

où le 2ème niveau est utile uniquement pour obtenir du “texte de niveau 2”.
De manière schématique, il apparaît que la structure source correspondante était la suivante:

 calling Id: "~some guid~" returns {Id: "level-1-id", Text: "Level-1 text", HasChildren: true} >>>  calling Id: "level-1-id" returns {Id: "level-2-id", Text: "Level-2 text", HasChildren: true} >>> (nothing) calling Id: "level-2-id" returns {Id: "level-3-id", Text: "Level-3 text", HasChildren: false} >>>  

Donc, si vous avez la main sur la structure de données source, vous feriez mieux d’utiliser quelque chose comme ceci:

 calling Id: "~some guid~" returns {Id: "level-1-id", Text: "Level-1 text", HasChildren: "Level-2 text"} >>>  calling Id: "level-1-id" returns {Id: "level-3-id", Text: "Level-3 text", HasChildren: false} >>>  

Note: ici, j’ai gardé les noms “niveau 2” et “niveau 3” pour plus de cohérence, alors qu’il n’y a plus que 2 niveaux.

Utilisation de jQuery.

Je suis surpris que vous répétiez le tableau JSON reçu avec $(data).each(function() : ce formulaire est destiné à traiter les objects jQuery, alors que pour les tableaux et pour d’autres objects non-jQuery, nous sums supposés utiliser $.each(data, function() .

J’ai donc passé quelques tests et j’ai été surpris de constater que cela fonctionnait aussi, même si cela ne devrait pas en quelque sorte! Vous pouvez trouver l’enquête détaillée rapscope dans la question que j’ai postée à ce sujet .

Un autre point concerne la façon dont vous abordez chaque élément passé par l’itération ci-dessus: $(this)[0].HasChildren est inutilement compliqué, car il encapsule successivement this dans un object jQuery puis l’extrait!
Vous devriez simplement utiliser this.HasChildren .

Suggéré un moyen simple de réaliser tout le travail.

Construire HTML en tant que stream linéaire de chaînes n’est pas un moyen facile, car:

  • la balise de fermeture pour doit apparaître _après que les internes ont été créées
  • mais le mode asynchrone d’Ajax rend difficile de savoir quand le faire

À l’inverse, jQuery est facile à utiliser pour construire et chaque fois que nécessaire.
Notez que cela signifie que nous devons utiliser jQuery.append() au lieu de jQuery.html() pour le faire.

En ce qui concerne l’aspect nested des données source, le moyen le plus simple consiste à utiliser la récursivité plutôt que d’utiliser $.ajax plusieurs fois dans des niveaux nesteds.
Cela présente également l’avantage de réduire le code et de le rendre plus lisible.

Voici l’extrait fondé sur toutes les considérations ci-dessus.
Notez que je l’ai aussi simplifiée suite à ma précédente suggestion d’utiliser simplement HasChildren (renommé Children pour plus de clarté) pour fournir les informations sur nested. Pour une il n’est même pas nécessaire qu’il soit présent.

 function buildMenu(Id, $parent, prependage) { $parent = $parent || $('#dropdown'); $.ajax({ url:"../../api/getEnum", data: {itemFilter: "", Id: Id}, dataType: "json", success: function(data) { $.each(data, function() { if (!this.Children) { // create a simple \ '); } else { // create an  $parent.append('\ \ \ '); // call for  

Pour être sûr, j’ai testé avec une version légèrement modifiée, vous pouvez essayer de vérifier que cela fonctionne comme prévu:

  [ ["Id" => "level-1-1", "Text" => "Text-1-1"], ["Id" => "level-1-2", "Text" => "Text-1-2"], ["Id" => "level-1-3", "Text" => "Text-1-3", "Children" => "level-1-3"], ["Id" => "level-1-4", "Text" => "Text-1-4"], ["Id" => "level-1-5", "Text" => "Text-1-5", "Children" => "level-1-5"], ], 'level-1-3' => [ ["Id" => "level-1-3-1", "Text" => "Text-1-3-1"], ["Id" => "level-1-3-2", "Text" => "Text-1-3-2"], ["Id" => "level-1-3-3", "Text" => "Text-1-3-3"], ], 'level-1-5' => [ ["Id" => "level-1-5-1", "Text" => "Text-1-5-1"], ["Id" => "level-1-5-2", "Text" => "Text-1-5-2"], ["Id" => "level-1-5-3", "Text" => "Text-1-5-3"], ], ]; if ($Id = @$_REQUEST['Id']) { echo json_encode($menus[$Id]); exit; } ?>