Insertion du shortcode WordPress dans JS via une requête AJAX

Publié par Jean-Michel le

I am trying to insert WordPress shortcode into JS but haven’t managed so far. I found some jQuery code that I needed to translate into vanilla JS and I am pretty sure I did not do the right thing since it’s not working. I do not fully understand the code I came across, which means I need some help understanding where I’ve gone wrong and why my shortcode isn’t showing on my site. Maybe the PHP code is not correctly linked to the JS file, I’m not too sure.

The goal is to have the shortcode (a WP form in this case) show in the modal when it’s clicked on. Any help is greatly appreciated!

Here is the jQuery code (AJAX request):

        $.ajax({
          url: `<?php echo admin_url('admin-ajax.php'); ?>`,
          type: "GET",
          data: {
            action: "runThisPhpFunction",
          },
          success: function (data) {
            $("#trigger_target").html(data);
          },
        });

And here is my JS code for the modal, into which I am trying to place the shortcode:

function newsletterModal() {
  const ajaxurl = `<?php echo admin_url('admin-ajax.php'); ?>`;

  const btn = document.querySelector("#menu-item-2745");
  btn.setAttribute("id", "trigger_my_shortcode");
  const modal = document.createElement("div");
  modal.setAttribute("id", "trigger_target");
  modal.classList.add("modal");

  modal.innerHTML = `<div class="modal-content">
    <span class="close">&times;</span>
    <h2>Sign up to our newsletter</h2>
    <h5>And get hold of your 10% discount!</h5>
    <p>insert  here</p>
    </div>`;

    btn.onclick = function (e) {
    e.preventDefault();
    modal.style.display = "block";

    document
      .querySelector("#trigger_my_shortcode")
      .addEventListener("click", (e) => {
        e.preventDefault();

          fetch(ajaxurl, {
          type: "GET",
          data: {
            action: "runThisPhpFunction",
          },
          success: function (data) {
            document.querySelector("#trigger_target").html(data);
          },
        });
      });
  };

  modal.querySelector(".close").onclick = function () {
    modal.style.display = "none";
  };
  window.onclick = function (e) {
    if (e.target == modal) {
      modal.style.display = "none";
    }
    document.body.appendChild(modal);
  };
}

Et le code functions.php :

function runThisPhpFunction() {
    if ( isset($_REQUEST) ) {

      echo do_shortcode( '' );

    }
    die();
  }
  add_action( 'wp_ajax_runThisPhpFunction', 'runThisPhpFunction' );
  add_action( 'wp_ajax_nopriv_runThisPhpFunction', 'runThisPhpFunction' );

Solution n°1 trouvée

Il se passe beaucoup de choses avec votre code, donc la réponse ne sera pas courte. Il est généralement recommandé de diviser votre code en fonctions plus petites qui ont toutes un objectif spécifique. J’ai donc pris la liberté de réécrire certaines fonctions afin qu’elles vous aident à vous rendre là où vous devez aller.

Le code ci-dessous fonctionne comme suit : La buildModalfonction construit tout le code HTML de votre modal et peut prendre a formcomme argument. Cela formdevrait être du texte car il doit être interpolé (combiné) avec vos autres éléments dans la même chaîne.

La buildModalfonction sera appelée depuis la getFormAndBuildModalfonction. La getFormAndBuildModalfonction utilise fetchpour envoyer une requête au serveur et interprète la réponse comme du texte. Ce texte est votre formulaire, qui sera transmis au buildModalpour construire le modal avec le formulaire dedans.

Le bouton avec #menu-item-2745sera le déclencheur pour envoyer la demande et créer le formulaire.

Travailler de cette façon signifie que chaque fois que vous cliqueriez sur votre bouton, il appellerait le serveur, créerait un nouveau modal et l’afficherait sur la page. Ensuite, lors de la fermeture du modal, il supprime le modal de la page.

J’ai essayé d’expliquer autant que possible ce qui se passe dans le code et ce que fait chaque étape. Si certaines choses ne sont toujours pas claires, s’il vous plaît faites le moi savoir et j’essaierai d’éclaircir.

function buildModal(form) {
  const modal = document.createElement("div");
  modal.id = "trigger_target"
  modal.classList.add("modal");

  /**
   * Create close button here so we can attach the
   * event listener without having to select it later.
   */
  const modalClose = document.createElement("span");
  modalClose.classList.add("close");
  modalClose.addEventListener("click", function() {

    /**
     * Remove the modal completely from the document.
     * This isn't mandatory and you can change it if you'd like.
     */
    modal.remove();
  });

  const modalContent = document.createElement("div");
  modalContent.classList.add("modal-content");

  /**
   * The form will be a string of HTML that gets injected
   * into another string of HTML here below. The innerHTML setter
   * will then parse the entire string, with form, to HTML.
   */
  modalContent.innerHTML = `
    <div class="modal-content">
      <h2>Sign up to our newsletter</h2>
      <h5>And get hold of your 10% discount!</h5>
      <p>${form}</p>
    </div>`;

  /**
   * First append the close button, then the content.
   */
  modal.append(modalClose, modalContent);

  /**
   * Return the HTML modal element.
   */
  return modal;
}

Ici, j’ai ajouté comment utiliser PHP en JavaScript et un moyen de résoudre le problème de sélection du bouton. Il existe deux solutions à ce problème, l’une est ici au deuxième commentaire et l’autre solution est dans l’extrait PHP après celui-ci.

/**
 * Check the PHP snippet at the bottom how this gets here.
 * This is the result of the array turned into JSON and then
 * placed into the document with wp_add_inline_script.
 *
 * Sidenote: __wp__ looks ugly, but it will make sure that if
 * a browser might get updated and a new property is added to the
 * window object, it will never overwrite or break anything because
 * the name is so unique.
 */
const ajaxurl = __wp__.ajax;

/**
 * Select the button and listen for the click event.
 * When clicked, fire the getFormAndBuildModal function.
 *
 * Update: with selecting elements it is paramount that the element is
 * above the <script> tag in the document.
 * Otherwise the element would not yet exist and the result would come up empty.
 * Another way is to wait for the document to give a signal when every element has been rendered with the DOMContentLoaded event.
 */
// document.addEventListener('DOMContentLoaded', function(event) {
//  const button = document.querySelector("#menu-item-2745");
//  button.addEventListener("click", getFormAndBuildModal);
// });

const button = document.querySelector("#menu-item-2745");
button.addEventListener("click", function(event) {
  event.preventDefault();
  getFormAndBuildModal();
});

function getFormAndBuildModal() {
  /**
   * Fetch uses the GET method by default.
   * All you need to do is to add the action to the URL
   * so that WP knows what action to call on the server.
   */
  fetch(`${ajaxurl}?action=runThisPhpFunction`)

  /**
   * Fetch can take while to load, so it uses a promise.
   * With .then() we say what happens after fetch is finished.
   * Fetch gives us a response object as a result, which we need to inspect.
   */
  .then(response => {

    /**
     * If the response has gone wrong, show an error.
     */
    if (!response.ok) {
      throw new Error("runThisPhpFunction request has failed");
    }

    /**
     * Otherwise we use the content that the response has send us.
     * Currently the "body" (your form) of the response is just bits and bytes.
     * We can tell the response how we want to use the response.
     * With the .text() method we turn the raw data into a string.
     * That string can later be used as HTML. :)
     */
    return response.text();
  })

  /**
   * response.text() also returns a promise, just like fetch. So to go to the next step
   * we use another .then() function. In here we have our form in a string.
   * Now we can build the modal and pass the form as an argument. The modal
   * will be build and the form turned into HTML and put in the correct position.
   * When the buildModal function is done it returns the result.
   * Now append it to the body and it's done.
   */
  .then(form => {
    const modal = buildModal(form);
    document.body.append(modal);
  });
}

Ici, j’ai ajouté quelques ajouts supplémentaires pour mettre le script en file d’attente et comment transformer PHP en JavaScript de la bonne manière. 😉

function enqueue_my_custom_script() {
  /**
   * Instead of printing PHP variables directly inside JavaScript,
   * you could use this method to let PHP do that for you.
   * The array here below we be turned into a JSON string,
   * which will later be turned into a JavaScript object that you
   * can use in your main script.
   */
  $wp_js_data = json_encode(
    array(
      'ajax' => admin_url( 'admin-ajax.php' ),
    )
  );

  /**
   * The last parameter of wp_register_script (there are 5) will
   * determine if the script will be placed in the <head> tag when
   * the value is false, or before the end of the </body> tag when
   * the value is true. The latter will make sure that your JS executes
   * AFTER all other HTML elements have been rendered. With this you don't
   * have to listen for the DOMContentLoaded event in JavaScript.
   *
   * Use get_stylesheet_directory_uri() to get the path to your child
   * theme directory instead of hard linking to your sheet. This will
   * output the URL to the directory of your style.css file of your theme.
   */
  wp_register_script( "scriptjs", get_stylesheet_directory_uri() . "/script.js", array(), null, true );

  /**
   * Here we create a global variable on the window object. This makes
   * the data is available in every JavaScript file. Here we insert the JSON string
   * that will be turned into a usable JS object.
   *
   * Be sure to output this script BEFORE the "scriptjs" file.
   */
  wp_add_inline_script( "scriptjs", "window.__wp__ = {$wp_js_data}", "before" );

  /**
   * This used to be the first line. wp_register_script only registers
   * the script but does not output it. This enables you to do something
   * like wp_add_inline_script before outputting the script.
   * wp_enqueue_script makes sure that the registered script will be
   * placed in the document.
   */
  wp_enqueue_script( "scriptjs" );
}
add_action( "wp_enqueue_scripts", "enqueue_my_custom_script" );

Catégories : Wordpress

Jean-Michel

Jean-Michel est en charge de la partie blog du site. Il met en place la stratégie de contenu et répond aux questions fréquentes sur Wordpress.

0 commentaire

Laisser un commentaire

Avatar placeholder

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *