web-dev-qa-db-fra.com

Exécution de Javascript lorsqu'un widget est ajouté dans le backend

J'ai des widgets auxquels des contrôles javascript sont associés.

Si le widget est présent lors du chargement de la page d'administration du widget, les contrôles fonctionnent correctement.

Lorsque j'ajoute un nouveau widget, ils ne fonctionnent pas correctement, je reçois le balisage, mais aucun événement javascript ne prend effet.

Si j'enregistre le nouveau widget, lorsque le formulaire est rechargé, les contrôles sont créés correctement et fonctionnent maintenant.

L'actualisation de la page corrige également le problème, mais uniquement pour les widgets existants. Les nouveaux widgets ont toujours ce problème.

Plus précisément, je lance selectize sur certaines entrées à ces points:

  • document prêt
  • Ajaxcomplete

J'ai vérifié que mon code est exécuté sur chaque événement comme souhaité, mais les résultats ne sont pas ceux attendus.

Voici un plugin de test qui illustre le problème:

https://Gist.github.com/Tarendai/8466299

Vous verrez que j'ai un compteur qui augmente avec chaque élément sélectionné détecté qu'il peut convertir.

Remarques:

  • Lorsque la page du widget est chargée, le compteur augmente dans la console JS comme prévu.
  • Lorsque j'ajoute un nouveau widget, le code est exécuté. Cependant, il ne trouve aucun élément sélectionné sur lequel il peut s'exécuter, comme le prouve found.length: 0. Cela ne devrait pas être le cas, car chaque nouveau widget de ce type devrait avoir un élément select
  • les éléments select ont une classe pour les identifier. Cette classe est supprimée une fois que la bibliothèque selectize est appliquée pour éviter la duplication et le traitement ultérieur des widgets existants.
  • Avant d’utiliser selectize, j’utilisais Select2, qui avait le même problème
  • En commentant le code AJAX, je m'attendrais à ce que les nouveaux widgets aient une entrée de sélection standard. Ils ne. Je ne sais pas pourquoi c'est le cas

Alors, comment faire fonctionner le contrôle de sélection sans demander à l'utilisateur d'actualiser/cliquer sur enregistrer avant d'apporter des modifications?

20
Tom J Nowell

Bonne nouvelle,

Je l'ai réparé.

Mes excuses pour avoir manqué votre Gist dans mon commentaire initial et pour vous donner une réponse que vous aviez déjà mise en œuvre. Cela m'apprendra à répondre au téléphone en train!

Votre utilisation de ajaxstop est correcte. Hell le JS fonctionne pour la plupart correctement, vous pouvez voir les styles CSS en cours d'initialisation et les modifications dans le DOM.

Le problème réside en fait avec votre sélecteur.

En effet, le contenu du widget n'est pas chargé via ajax. En fait, il le clone dans la colonne de gauche où il est masqué, puis déclenche un appel ajax pour enregistrer la position du widget dans la colonne de droite. Cela explique pourquoi ajaxstop fonctionne comme un régal, même si le contenu pensé est cloné. Cependant, comme il existe une version cachée du widget dans la colonne de gauche, votre système de surveillance est instancié sur ce point. En tant que tel, lorsque vous le faites glisser dans la colonne de droite, vous obtenez un clone mutilé du widget masqué.

Ainsi, vous devez sélectionner celui du côté gauche. Ci-dessous le code corrigé:

<script>
jQuery( document ).ready( function( $ ) {
    function runSelect() {
        var found = $( '#widgets-right select.testselectize' );
        found.each( function( index, value ) {

            $( value ).selectize();
                .removeClass( 'testselectize' )
                .addClass( 'run-' + window.counter );

            console.log( $val );
            window.counter++;
        } );
    }

    window.counter = 1;

    runSelect();

    $( document ).ajaxStop( function() {
        runSelect();
    } );
} );
</script>
12
MichaelJames

Comme l'a commenté @ aaron-holbrook, une approche plus propre consiste à:

jQuery(document).on('widget-updated widget-added', function(){
    // your code to run
});

Dans de nombreux cas, vous souhaiterez également exécuter le JS lors du chargement de la page ainsi que lors de la mise à jour des widgets. Vous pouvez le faire comme ça.

function handle_widget_loading(){
   // your code to run
}
jQuery(document).ready( handle_widget_loading );
jQuery(document).on('widget-updated widget-added', handle_widget_loading );

Il suffit de coller ici pour référence car les réponses sont beaucoup plus faciles à trouver que les commentaires

16
chifliiiii