Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

jQuery Discussion :

Créer un bouton avec event


Sujet :

jQuery

  1. #1
    Membre actif
    Créer un bouton avec event
    Bonjour,
    Je tente de créer un bouton en jquery depuis un bon moment avec handler lui étant directement lié
    J'ai donc un tableau que je remplis et au dernier champs je veux rajouter un bouton qui me permettra de générer une popup
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    function fillTableEtape1(table, data){
        tbody = $("<tbody>");
        table.children('thead').find("td:first-child").text(data.date_num+' - '+data.date);
        var btn = $('<button>')
            .html($("<i>").addClass("fas fa-chart-line"))
            .addClass("btn btn-link p-0")
            .click(function(event) {
                console.log("ui"); 
            });
     
        $.each(data, function(cle, val) {
            if($.isPlainObject(val)){
                tbody.append( $('<tr>').append( $('<th>').prop('colspan', 7).text(cle.toUpperCase()) ) );
                $.each(val, function(cle, val) {
                    tbody.append(
                        $('<tr>')
                            .append( $('<td>').html(cle+'') )
                            .append( $('<td>').html(val.nbr+'') )
                            .append( $('<td>').html(val.marge+'') )
                            .append( $('<td>').html( Math.round(val.jrs_posit)+'' ) )
                            .append( $('<td>').html(val.suffixe+'') )
                            .append( $('<td>').html(val.nom_action+'') )
                            .append( $('<td>').html( btn ))
     
                    );
                });
            }
        });
        tbody = tbody.html().replace(/NaN/g, "--").replace(/undefined/g, "--").replace(/null/g, "--");
        table.children('tbody').html(tbody);
        return true;
    }

    Probleme 1: il n'y à que la derniere ligne qui affiche le bouton
    Probleme 2: je n'arrives pas à afficher mon message d'alerte donc il ne rentres pas dans le fonction click
    Merci d'avance

  2. #2
    Membre actif
    Bonjour,
    Non non c'est la bonne syntaxe
    https://api.jquery.com/jQuery/#jQuery2

    If the HTML is more complex than a single tag without attributes, as it is in the above example, the actual creation of the elements is handled by the browser's .innerHTML mechanism. In most cases, jQuery creates a new <div> element and sets the innerHTML property of the element to the HTML snippet that was passed in. When the parameter has a single tag (with optional closing tag or quick-closing) — $( "<img />" ) or $( "<img>" ), $( "<a></a>" ) or $( "<a>" ) — jQuery creates the element using the native JavaScript .createElement() function.
    Enfait cela fait appel au self-closed

    Voici d'ailleurs ce que cela donnes
    Code HTML :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    <tr><th colspan="7">ACH</th></tr>
    <tr><td>max</td><td>1</td><td>142.86</td><td>5</td><td>25</td><td>Derichebourg</td><td></td></tr>
    <tr><td>min</td><td>1</td><td>6.02</td><td>2</td><td>17</td><td>Bouygues</td><td></td></tr>
    <tr><td>moy</td><td>17</td><td>27.60</td><td>3</td><td>--</td><td>--</td><td></td></tr>
    <tr><th colspan="7">VTE</th></tr>
    <tr><td>max</td><td>1</td><td>8.53</td><td>2</td><td>32</td><td>Essilor</td><td></td></tr>
    <tr><td>min</td><td>1</td><td>8.53</td><td>2</td><td>32</td><td>Essilor</td><td></td></tr>
    <tr><td>moy</td><td>1</td><td>8.53</td><td>2</td><td>--</td><td>--</td><td></td></tr>
    <tr><th colspan="7">INDEF</th></tr>
    <tr><td>nbr</td><td>19</td><td>--</td><td>--</td><td>--</td><td>--</td><td><button class="btn btn-link p-0"><i class="fas fa-chart-line"></i></button></td></tr>

    J'ai suis passé à la ligne pour chaque <tr> histoire que cela soit un peu plus lisible



    Ajout: et si tu observes à la fin il y a chaque fois un <td></td> "en trop" en réalité c'est la que les boutons sont sensé s'insérer.
    Seulement je ne sais pas pourquoi seul la dernière boucle insert le bouton (je suppose qu'il crée en réalité qu'un seul bouton et qu'a chaque tours il le déplace)
    et deuxième soucis ce bouton n'a malgré tout pas le handler attaché à lui

  3. #3
    Membre émérite
    Ah oui, j'ai répondu trop vite..., mais bon si tu veux résoudre le problème du clic sur le bouton, essaies d'attacher l'événement click par délégation dans ta fonction comme ça :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    table.on('click','button.btn-link',function(event) {
           console.log("ui"); 
    });


    Pour le deuxième problème, je n'ai aucune idée de la structure du data mais tu peux cloner le bouton au moment de l'ajout, comme ça :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
     
    .append( $('<td>').html( btn.clone() ))

  4. #4
    Membre actif
    Ce message n'a pas pu être affiché car il comporte des erreurs.

  5. #5
    Membre émérite
    Citation Envoyé par Sparky95 Voir le message
    du coup et bien via ton idée je vais directement créer le bouton dans la boucle et ça devra fonctionner.
    Justement, l'utilité de la délégation c'est d'attacher les événements en dehors de la boucle.

    Sinon, et si tu as un ID de la table
    Code html :Sélectionner tout -Visualiser dans une fenêtre à part
    <table id="laTable"></table>
    tu peux mettre le code en dehors de la fonction :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    $("#laTable").on("click",'button.btn-link',function(event) {
          console.log("ui"); 
    });
    function fillTableEtape1(table, data){.......}


    Je vois aussi que tu remplaces undefined et NaN et null par des tirets avec cette ligne :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
     
     tbody = tbody.html().replace(/NaN/g, "--").replace(/undefined/g, "--").replace(/null/g, "--");


    Si tu veux supprimer cette ligne, renomme le deuxième val du deuxième each (le deuxième paramètre de function) par (val1 ou val2 ou comme tu veux...)
    Code javascript :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    $.each(data, function(cle, val) {
       ....
       $.each(val, function(cle, val1) {
       ....

  6. #6
    Membre actif
    je viens de le faire comme tu m'as conseillé cela fonctionnes
    Voici le code maintenant
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     
     
        // FONCTIONS
            function fillTableEtape1(table, data){
                tbody = $("<tbody>");
                table.children('thead').find("td:first-child").text(data.date_num+' - '+data.date);
                $.each(data, function(cle, val) {
                    if($.isPlainObject(val)){
                        // tab += '<tr><th scope="col" colspan="7" class="text-capitalize">'+cle.toUpperCase()+'</th></tr>';
                        tbody.append( $('<tr>').append( $('<th>').prop('colspan', 7).text(cle.toUpperCase()) ) );
                        $.each(val, function(cle, val) {
                            tbody.append(
                                $('<tr>')
                                    .append( $('<td>').html(cle+'') )
                                    .append( $('<td>').html(val.nbr+'') )
                                    .append( $('<td>').html(val.marge+'') )
                                    .append( $('<td>').html( Math.round(val.jrs_posit)+'' ) )
                                    .append( $('<td>').html(val.suffixe+'') )
                                    .append( $('<td>').html(val.nom_action+'') )
                                    .append( $('<td>')
                                        .html( $("<button>")
                                                .html($("<i>").addClass("fas fa-chart-line"))
                                                .addClass('btn btn-link btn-table p-0')
                                                .bind('click', [val.suffixe, val.date_num ], function(event) {
                                                    console.log("ui2.0");
                                                })
                                            ))
     
                            );
                        });
                    }
                });
                tbody = tbody.html().replace(/NaN/g, "--").replace(/undefined/g, "--").replace(/null/g, "--");
                table.children('tbody').html(tbody);
                table.click('button.btn-table',function(event) {
                    console.log("ui"); 
                });
                return true;
            }
    });


    maintenant j'aurais également voulu lier les var suffixe et date_num au bouton comment puis-je faire ça?
    J'ai essayé avec un bind histoire de voir si je n'étais pas chanceux mais non

    Citation Envoyé par Toufik83 Voir le message
    Je vois aussi que tu remplaces undefined et NaN et null par des tirets avec cette ligne :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
     
     tbody = tbody.html().replace(/NaN/g, "--").replace(/undefined/g, "--").replace(/null/g, "--");

    Mon but est de remplacer les cases vides par des -- ce n'est donc pas là, le dérangeant. Là ou cela me déranges plus, question propreté du code c'est ceci .append( $('<td>').html(cle+'') ) j'ai voulu faire des toString() mais du fait que je n'avais pas les données pour tous plutôt que de faire des if partout j'ai fait un concat. avec un string vide histoire de transformer le tout en string.(le casting ne fonctionnait pas)
    Et de la j'ai remplacé les données qui me ressortaient un vide en --

  7. #7
    Membre émérite
    as-tu lu ce que je disais dans mon post précédent ?
    Citation Envoyé par Toufik83 Voir le message
    Si tu veux supprimer cette ligne, renomme le deuxième val du deuxième each (le deuxième paramètre de function celui en rouge) par (val1 ou val2 ou comme tu veux...)
    Code javascript :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $.each(data, function(cle, val) {
       ....
       $.each(val, function(cle, val1) {
       ....
    bind ? cette méthode est dépréciée dans jQuery version 3.x, il ne faut pas l'utiliser !

    Citation Envoyé par Sparky95 Voir le message
    maintenant j'aurais également voulu lier les var suffixe et date_num au bouton comment puis-je faire ça?
    Tu peux utiliser soit $.data() soit data-attribute :

    Avec $.data()
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
     
    $("<button>").data({"suffixe":val.suffixe, "date_num":val.date_num})


    Avec data-attribute :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
     
    $("<button data-suffixe='"+val.suffixe+"' data-dateNum='"+val.date_num+"'>")

  8. #8
    Membre actif
    Citation Envoyé par Toufik83 Voir le message
    as-tu lu ce que je disais dans mon post précédent ?
    Oui oui j'ai lu mais je ne vois pas en quoi cela changes quelque chose. Je l'ai tout de même testé mais comme je le pensais cela ne changes rien
    c'est juste le nom d'une variable qui change mais au final si la donnée de la variable n'existe pas cela ressortira malgré tout undefined ou NaN

    Quand à ton systeme de data ça m'a l'air d'être ce que je cherchais je ne connaissais pas merci

  9. #9
    Membre actif
    Par contre j'ai un soucis du coup avec le handler.
    Lorsque je click sur le bouton, l'objet pris en action(le $(this) ) n'est du coup pas le bouton mais le tableau comment puis-je du coup récupérer les data du bouton actionné?

  10. #10
    Membre émérite
    Citation Envoyé par Sparky95 Voir le message

    Je l'ai tout de même testé mais comme je le pensais cela ne changes rien
    c'est juste le nom d'une variable qui change mais au final si la donnée de la variable n'existe pas cela ressortira malgré tout undefined ou NaN
    Quelle est la structure de data que tu parcours avec les 2 $.each ?

    Pour la deuxième question, c'est parce que tu attaches mal l'écouteur de clic sur les boutons, essaies ceci :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    table.on("click",'button.btn-table',function(event) {
        console.log("suffixe :"+$(this).data("suffixe"));//affiche le data("suffixe") 
    });

  11. #11
    Membre actif
    un tableau à multi dimensions récupéré en ajax d'une bdd https://prnt.sc/rr0gla

    Ajout: je viens de test console.log("suffixe :"+$(this).data("suffixe")); et j'obtiens suffixe :undefined

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    function fillTableEtape1(table, data){
    	console.log(data);
    	tbody = $("<tbody>");
    	table.children('thead').find("td:first-child").text(data.date_num+' - '+data.date);
    	$.each(data, function(cle, val) {
    		if($.isPlainObject(val)){
    			tbody.append( $('<tr>').append( $('<th>').prop('colspan', 7).text(cle.toUpperCase()) ) );
    			$.each(val, function(cle, val) {
    				tbody.append(
    					$('<tr>')
    					.append( $('<td>').html(cle) )
    					.append( $('<td>').html(val.nbr+'') )
    					.append( $('<td>').html(val.marge+'') )
    					.append( $('<td>').html( Math.round(val.jrs_posit)+'' ) )
    					.append( $('<td>').html(val.suffixe+'') )
    					.append( $('<td>').html(val.nom_action+'') )
    					.append( $('<td>').html(
    						$("<button>").addClass('btn btn-link btn-table p-0')
    							.data({
    								"suffixe": val.suffixe+"",
    								"date_num": val.date_num+""
    							})
    							.html( $("<i>").addClass("fas fa-chart-line") )
    					))
    				);
    			});
    		}
    	});
    	tbody = tbody.html().replace(/NaN/g, "--").replace(/undefined/g, "--").replace(/null/g, "--");
    	table.children('tbody').html(tbody);
    	table.click('button.btn-table',function(event) {
    		console.log($(this));
    		console.log("suffixe :"+$(this).data("suffixe"));
    	});
    	return true;
    }

  12. #12
    Membre émérite
    Le problème se situe ici :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
     
    table.children('tbody').html(tbody);

    Là tu insère un tbody dans l'ancien tbody, ce qui donne une fausse structure du tableau, il faut mettre le contenu de tbody en utilisant .children() ou .find("*") ... comme tu veux :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    table.children('tbody').html(tbody.children());
    // ou bien 
    table.children('tbody').html(tbody.find("*"));


    Exemple testé :
    Code html :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <table id="test">
    <thead><tr><th colspan="7"></th></tr></thead>
    <tbody></tbody>
    </table>


    Et le script jQuery :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
     
    $(function(){
    var dataAjax={
      ach:{
      	max:{suffixe:25,nom_action:"Derichebourg",marge:"142.86",jrs_posit:5,nbr:1},
            min:{suffixe:17,nom_action:"Bouygues",marge:"6.02",jrs_posit:2,nbr:1},
            moy:{nbr:17,marge:"27.6",jrs_posit:"3.4"}
      },
      vte:{
      	max:{suffixe:32,nom_action:"Essilor",marge:"8.53",jrs_posit:2,nbr:1},
            min:{suffixe:32,nom_action:"Essilor",marge:"8.53",jrs_posit:2,nbr:1},
            moy:{nbr:1,marge:"8.5",jrs_posit:"2.0000"}
      },
      indef:{
      	nbr:{nbr:19,date_num:200},
            date:"15/10/2002",
            date_num:37544
      }
    };
    function fillTableEtape1(table, data){
        //click sur les boutons .btn-table (par délégation)
        table.on('click','.btn-table',function(event) {
           console.log("suffixe :"+$(this).data("suffixe")); 
        });
     
        var tbody = $("<tbody>");
     
        //d'après la structure que tu m'a montré, les variables date_num et date existent seulement dans l'objet dataAjax.indef, donc pour les récupérer : data.indef.date_num et data.indef.date:
        table.children('thead').find("td:first-child")
        .text(data.indef.date_num+' - '+data.indef.date);
     
        //on crée le bouton une seule fois et en dehors des each !
        var btn = $('<button>')
        .append($("<i>").addClass("fas fa-chart-line"))
        .addClass("btn btn-link btn-table p-0");
     
     
        $.each(data, function(cle, val) {
            if($.isPlainObject(val)){ 
                tbody.append( $('<tr>').append( $('<th>').prop('colspan', 7)
                .text(cle.toUpperCase()) ) );
                $.each(val, function(cle1, val1) { //cle1 et val1 !!
     
                     tbody.append(
                        $('<tr>')
                            .append( $('<td>').html(cle1))
    			//conditions ternaire pour remplacer les (null,undefined,NaN)
                            .append($('<td>').html(val1.nbr?val1.nbr:'--'))
                            .append($('<td>').html(val1.marge?val1.marge:'--'))
                            .append($('<td>').html(val1.jrs_posit?Math.round(val1.jrs_posit):'--'))
                            .append($('<td>').html(val1.suffixe?val1.suffixe:'--'))
                            .append($('<td>').html(val1.nom_action?val1.nom_action:'--'))
                            .append(
                                $('<td>')
                                .html( 
                                  btn.clone()//cloner le bouton 
                                  .data({
                                    "suffixe":val1.suffixe?val1.suffixe:"aucun suffixe",
                                    "date_num":val1.date_num?val1.date_num:"aucun date num"
                                  })
                                )
                          )
                     )
                });
           }
        });
        //là tu n'as plus besoin de cette ligne qui remplace les undefined nan null....
        //tbody = tbody.html().replace(/NaN/g, "--").replace(/undefined/g, "--").replace(/null/g, "--");
        table.children('tbody').append(tbody.find("*"));//ici .children(),ou bien .find(*) mais pas tbody
        return true;
    }
    fillTableEtape1($("#test"),dataAjax);
    });

  13. #13
    Membre actif
    Ecoute merci beaucoup car je n'aurais jamais trouvé.
    De plus j'ai remarqué qu'il fallait utiliser on.click et non $.click et ça je n'aurais jamais trouvé non plus car je pensais que c'était des alias.
    Sais-tu d'ailleurs pourquoi le Click ne fonctionnes pas?
    Pour le système des ternaires je connaissais
    Date et date_num étant la même valeur pour tous il s'agit de 2 valeurs suivant indef et non enfants de indef.(elles sont donc au même palier que indef)

  14. #14
    Membre émérite
    Citation Envoyé par Sparky95 Voir le message

    Sais-tu d'ailleurs pourquoi le Click ne fonctionnes pas?
    Parce que :
    • d'après la documentation, $.click accepte un seul argument function(){} qui se déclenche au moment de clic sur un élément html.
    • L'utilisation de on est nécessaire lorsqu'on veut manipuler des éléments insérés dynamiquement (après le chargement de la page) par javascript.

  15. #15
    Membre actif
    Bonjour,
    Saurais-tu pourquoi les data toggle et target ne fonctionnent pas alors que data-toggle et data-target eux fonctionnent?
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    .append( $('<td>').addClass('p-0').html(
                                    (val1.suffixe)?
                                    btn.clone()
                                      .data({
                                        //fonctionnes pas (toggle et/ou target)
                                        // 'toggle': 'modal',
                                        // 'target': '#config_etape_1_modal_grap',
                                        'suffixe':val1.suffixe? val1.suffixe : 'aucun suffixe',
                                        'date_num':data.date_num? data.date_num : 'aucun date num',
                                        'date_num':data.date_num? data.date_num : 'aucun date num',
                                        'avant': 5,
                                        'apres': 20
                                    })
                                    //fonctionnes
                                    .attr({
                                        'data-toggle': 'modal',
                                        'data-target': '#config_etape_1_modal_grap'
                                    })
                                    : null
                                ))

  16. #16
    Membre émérite
    Salut,

    Le problème est résolu ou quoi ?

    Déjà ton code de .html devrait être :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    .html(
                 (val1.suffixe)?
                        btn.clone()
                         .data({
                             //fonctionnes pas (toggle et/ou target)
                             // 'toggle': 'modal',
                             // 'target': '#config_etape_1_modal_grap',
                             'suffixe':val1.suffixe,//pas la peine de remettre la condition ternaire ici, vu que tu es déjà dans le bloc val1.suffixe? (ligne 3) 
                             'date_num':data.date_num? data.date_num : 'aucun date num',
                             //'date_num':data.date_num? data.date_num : 'aucun date num', pourquoi deux fois ?
                             'avant': 5,
                             'apres': 20
                         })
                         //fonctionnes
                         .attr({
                             'data-toggle': 'modal',
                             'data-target': '#config_etape_1_modal_grap'
                          })
                  : null
    )

  17. #17
    Membre actif
    pour le date_num c'est une erreur d’inattention
    Par contre j'ai voulu utiliser la modal de bootstrap et via le data() target et toggle cela ne fonctionnes pas alors que data-target et data-toggle cela fonctionnes pourquoi?

  18. #18
    Membre émérite
    Bonjour,

    Tu fais certainement une erreur quelque part, parce que avec cet exemple ça fonctionne.
    Code html :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <table id="conteneur">
        <thead></thead>
        <tbody></tbody>
    </table>

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    $("#conteneur").on("click","button",function(){
        console.log("data.toggle  :"+$(this).data("toggle")+", data.target :"+$(this).data("target"));
    });
     
    var btn=$("<button>");
     
    $('#conteneur tbody').html(
       $("<td>")
    	 .addClass('p-0')
       .append(
    	    btn.text("OK")
    	    .clone()
    	    .data({'toggle': 'modal','target': '#config_etape_1_modal_grap'})
    	  )
    );

  19. #19
    Membre actif
    Chez moi le log fonctionnes aussi mais la partie modal elle, ne fonctionnes pas.

  20. #20
    Membre émérite
    montre le code html du modal.