IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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

Symfony PHP Discussion :

Appeler une fonction javascript


Sujet :

Symfony PHP

  1. #1
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Mai 2004
    Messages
    803
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 803
    Par défaut Appeler une fonction javascript
    Bonjour,

    Dans un template, j'ai ce bouton qui in fine, permettra de générer des formulaires de photos à la volée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <button type='button' class='add_photo_link' oncclick="addPhotoForm();">Ajouter une photo</button>
    Dans le webpack Encore, j'ai un fichier js spécifique pour mon formulaire dans lequel j'ai ceci :

    alert('Coucou'); // pour tester l'intégation du fichier dans mon template

    export function addPhotoForm(){
    alert('Coucou2'); // Pour tester l'appel de ma fonction

    }
    [/CODE]

    Mon premier 'Coucou' s'affiche bien, ce qui prouve que mon fichier js est bien chargé. Par contre, lorsque je clique sur le bouton, 'Coucou2' ne s'affiche pas : ma fonction addPhotoForm() n'est donc pas appelée au clic sur le bouton.

    Quelqu'un aurait une idée de la manière dont je dois procéder?

    Merci d'avance.

  2. #2
    Expert confirmé
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 094
    Par défaut
    Bonsoir

    ton problème est similaire à celui de notre précédente conversation : tu as une fonction qui marche bien quand tu l’appelles depuis son propre fichier, mais pas en dehors.

    Je te propose de laisser tomber cet attribut onclick, et d’utiliser à la place un écouteur d’évènement. Tu vas voir, ce n’est pas très compliqué.

    Je vais partir du principe que tu n’utilises pas jQuery. Il faut commencer par attacher une fonction à l’évènement DOMContentLoaded. C’est l’équivalent de jQuery.ready() : ça permet de s’assurer que notre code est exécuté seulement une fois que tous les éléments de la page sont initialisés.
    Code JS : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    document.addEventListener("DOMContentLoaded", function () {
      // ...
    });

    Pour récupérer une référence sur ton bouton, on utilise querySelector, c’est une fonction qui prend un sélécteur CSS, exactement comme jQuery :
    Code JS : Sélectionner tout - Visualiser dans une fenêtre à part
    var button = document.querySelector("button.add_photo_link");
    Et on attache une fonction sur son évènement click :
    Code JS : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    button.addEventListener("click", function (event) {
      addPhotoForm();
    });

    En bonus, on peut rajouter un petit "use strict"; au début de la fonction pour s’assurer que notre code tourne en mode strict, ça ne mange pas de pain. D’ailleurs il est probable que tout soit déjà en mode strict grâce à Encore.

    En tout ça donne ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    document.addEventListener("DOMContentLoaded", function () {
      "use strict";
     
      var button = document.querySelector("button.add_photo_link");
      button.addEventListener("click", function (event) {
        addPhotoForm();
      });
    });
    Mets ça dans le même fichier que celui qui déclare la fonction addPhotoForm et ça devrait marcher. En fait, tu n’as même pas besoin d’exporter la fonction.
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  3. #3
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Mai 2004
    Messages
    803
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 803
    Par défaut
    Ok, merci. En fonction de ce que tu m'as indiqué et de la documentation que j'avais trouvée, voici ce que j'avais entre-temps réalisé avec jquery vu que je l'avais installé et que j'y fais appel dans asset/js/app.js via

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // Need jQuery? Install it with "yarn add jquery", then uncomment to require it.
    import $ from 'jquery';
    .

    Dans mon template "base.html.twig" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
            {% block javascripts %} 
                {{ encore_entry_script_tags ( 'app' ) }} 
     
                <!-- Renders app.js & a webpack runtime.js file
                <script src="/build/runtime.js"></script>
                <script src="/build/app.js"></script> -->
            {% endblock %}
    Dans mon template "createAdvert.html.twig" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    {% block javascripts %}
        {{ parent() }}
        {{ encore_entry_script_tags('addAdvert') }}
    {% endblock %}
    ...
    <button type="button" class="add_photo_link">Ajouter une photo</button>
    Et dans mon assets/js/addAdvert.js" :

    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
    var $collectionHolder ;    
     
    // setup an "add a photo" link
    var $addPhotoButton = $ ( '<button type="button" class="add_photo_link">Ajouter une photo</button>' );
    var $newLinkLi = $ ( '<li></li>' ). append ( $addPhotoButton );
     
    jQuery ( document ). ready ( function () {
        alert("OK");
        // Get the ul that holds the collection of photos
        $collectionHolder = $ ( 'ul.photos' );
     
        // add the "add a photo" anchor and li to the photos ul
        $collectionHolder . append ( $newLinkLi );
     
        // count the current form inputs we have (e.g. 2), use that as the new
        // index when inserting a new item (e.g. 2)
        $collectionHolder . data ( 'index' , $collectionHolder . find ( ':input' ). length );
     
        $addPhotoButton . on ( 'click' , function ( e ) {
        // add a new photo form (see next code block)
        addPhotoForm ( $collectionHolder , $newLinkLi );
        });
     
        function addPhotoForm ( $collectionHolder , $newLinkLi ) {
            // Get the data-prototype explained earlier
            var prototype = $collectionHolder . data ( 'prototype' );
     
            // get the new index
            var index = $collectionHolder . data ( 'index' );
     
            var newForm = prototype ;
            // You need this only if you didn't set 'label' => false in your tags field in TaskType
            // Replace '__name__label__' in the prototype's HTML to
            // instead be a number based on how many items we have
            // newForm = newForm.replace(/__name__label__/g, index);
     
            // Replace '__name__' in the prototype's HTML to
            // instead be a number based on how many items we have
            newForm = newForm . replace ( /__name__/g , index );
     
            // increase the index with one for the next item
            $collectionHolder . data ( 'index' , index + 1 );
     
            // Display the form in the page in an li, before the "Add a tag" link li
            var $newFormLi = $ ( '<li></li>' ). append ( newForm );
            $newLinkLi . before ( $newFormLi );
        }
    });
    Cependant, j'obtiens l'erreur suivante au chargement de la page :

    Nom : Capture.JPG
Affichages : 2452
Taille : 20,4 Ko

    Je ne comprends pas du fait que $ est bien déclarée dans mon app.js qui est bien chargé dans mon base.html.twig lui-même appelé dans mon template createAdvert.html.twig.

  4. #4
    Expert confirmé
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 094
    Par défaut
    Citation Envoyé par dubitoph Voir le message
    Je ne comprends pas du fait que $ est bien déclarée dans mon app.js
    J’avoue que je ne comprends pas bien non plus. As-tu vérifié l’ordre des scripts dans le code HTML généré ?

    Edit : je viens de voir que ton message d’erreur faisait référence au chemin assets/js/addAdvert.js. Est-ce que ça ne devrait pas plutôt être build/js/addAdvert.js ?
    As-tu ajouté la ligne suivante à ton webpack.config.js ?
    Code js : Sélectionner tout - Visualiser dans une fenêtre à part
        .addEntry('addAdvert', './assets/js/addAdvert.js')
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  5. #5
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Mai 2004
    Messages
    803
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 803
    Par défaut
    D'après la documentation et les exemples existants dans le fichier de configuration, ce serait bien vers le répertoire "assets" qu'il faudrait pointer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
       /*
         * ENTRY CONFIG
         *
         * Add 1 entry for each "page" of your app
         * (including one that's included on every page - e.g. "app")
         *
         * Each entry will result in one JavaScript file (e.g. app.js)
         * and one CSS file (e.g. app.css) if you JavaScript imports CSS.
         */
        .addEntry('app', './assets/js/app.js')
        .addEntry('addAdvert', './assets/js/addAdvert.js')
        //.addEntry('page1', './assets/js/page1.js')
        //.addEntry('page2', './assets/js/page2.js')
    Mais il est vrai qu'en te lisant, comme le tout est compilé vers le répertoire "build", c'est étrange qu'on doive faire comme cela...

  6. #6
    Expert confirmé
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 094
    Par défaut
    Oui, c’est ce que je voulais dire : des liens vers assets/ dans la configuration, mais des liens vers build/ dans tout ce qui est vu par le navigateur.
    Je répète ma question : as-tu vérifié l’ordre des scripts dans le code HTML généré ?
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  7. #7
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Mai 2004
    Messages
    803
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 803
    Par défaut
    Je viens de déplacer ce script juste avant la balise dans mon fichier "addAdvert.twig.html" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        {% block javascripts %}
            {{ parent() }}
            {{ encore_entry_script_tags('addAdvert') }}
        {% endblock %}
    Malheureusement, ça n'a rien changé :-(

  8. #8
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Mai 2004
    Messages
    803
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 803
    Par défaut
    Je viens maintenant de tracer l'ordre des appels et il se fait bien comme ceci lorsque je charge mon template :

    1. build/app.js
    2. asset/addAvert.js

  9. #9
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Mai 2004
    Messages
    803
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 803
    Par défaut
    J'ai trouvé! En fouillant, voici l'issue sur laquelle je suis tombée : pour que $ soit considérée comme globale, il faut ajouter dans le fichier de configuration.

    Encore merci pour ton attention et ton aide ;-)

+ Répondre à la discussion
Cette discussion est résolue.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo