web-dev-qa-db-fra.com

Est-ce que des formulaires/entrées dynamiques sont possibles dans Widget?

Je suis nouveau dans le développement de plugins WordPress et je viens de commencer à travailler avec le widget. Ma question est: Quelles sont les limites de WordPress Widget?

J'ai essayé d'utiliser jQuery pour rendre le formulaire de widget plus interactif/dynamique, mais cela ne semble pas fonctionner du tout. Par exemple, j'ai un bouton qui, une fois cliqué, ajoutera une chaîne de caractères "Hello!" à un div qui a id "ici".

<div id="here"></div> 
<input type="button" id="add" value="Click Me!" " />

<script>

    jQuery(document).ready(function(){ 
             //call when the button is click
             $(document).on('click', '#add', function() {
                  $('#here').append('<p>Hello</p>');
             });
        });


</script>
  1. Pourquoi le paragraphe de "Bonjour" n'apparaît-il pas sur le formulaire? Est-ce parce que la forme du widget l'empêche de le faire?

  2. J'ai aussi entendu parler de Backbone.js qui rafraîchit le front-end, mais je ne sais pas si cela fonctionnera.

  3. Si possible, expliquez comment fonctionne la classe entière des widgets wordpress. Merci d'avance!

Mise à jour: j'ai déjà essayé ce qui est suggéré, mais cela ne fonctionne toujours pas. Voici mon code.

repeat.php

     <?php
    /**
     * Plugin Name: Repeat Field
     *
     */



     class repeat_field_widget extends WP_Widget {

        /**
         * Sets up the widgets name etc
         */
        public function __construct() {
            $widget_ops = array(
                'classname' => 'repeat_field_widget',
                'description' => 'Repeat Field for Name input',
            );
            parent::__construct( 'repeat_field_widget', 'Repeat Field', $widget_ops );
        }

        /**
         * Outputs the content of the widget
         *
         * @param array $args
         * @param array $instance
         */
        public function widget( $args, $instance ) {
            // outputs the content of the widget
        }

        /**
         * Outputs the options form on admin
         *
         * @param array $instance The widget options
         */
        public function form( $instance ) {
            // outputs the options form on admin
    ?>
        <div id="here"></div>
        <input type="button" id="addRepeat" value="Click Me!" />

      <?php
        }

        /**
         * Processing widget options on save
         *
         * @param array $new_instance The new options
         * @param array $old_instance The previous options
         */
        public function update( $new_instance, $old_instance ) {
            // processes widget options to be saved
        }
    }


    function register_repeat_field_widget() {
        register_widget( 'repeat_field_widget' );
    }
    add_action( 'widgets_init', 'register_repeat_field_widget' );

    function repeat_field_widget_scripts() {
    wp_enqueue_script( 'repeat-field-widget-scripts', get_template_directory_uri() . '/repeat.js', array( 'jquery' ), '1.0.0', true );
}
add_action( 'wp_enqueue_scripts', 'repeat_field_widget_scripts' );

repeat.js

    jQuery(document).ready(function($){
       //call when the button is click
       $("#addRepeat").click(function() {
           $('#here').append('<p>Hello</p>');
       });
    });
2
Sengngy Kouch

MerciDave RomseyetMark Kaplunpour avoir signalé le fait de ne pas utiliser d'identifiant HTML dans WordPress Widget. Je trouve enfin une solution à mon besoin.

Solution:

Nous devons ajouter des variables prédéfinies dans les 3 fonctions (widget, formulaire, mise à jour). Dans mes codes, ils s'appellent "spotlight_image_link1, spotlight_image_link2, etc.". Ensuite, dans la "fonction de formulaire", donnez leur identifiant en utilisant le code php. S'il vous plaît lire mon code ci-dessous pour plus d'informations.

Que peut faire ma solution?

Au fond, ce n’est pas totalement dynamique car il faut au préalable prédéfinir tous les projecteurs. Dans mon cas, je n'ai prédéfini que deux projecteurs pour simplifier la lecture du code.

Voici à quoi ça ressemble: enter image description here 

Logique derrière la scène:

  • chaque fois que le "Cliquez sur moi!" bouton est cliqué, un projecteur sera ajouté.
  • Il existe un tableau de suivi appelé "suivi" qui garde en mémoire les projecteurs prédéfinis déjà utilisés. Lorsque tous les projecteurs sont utilisés, désactivez la case à cocher "Cliquez sur moi!" bouton.
  • Lorsque vous cliquez sur "Supprimer les projecteurs", supprimez ce projecteur et réactivez l'option "Cliquez sur moi!". bouton. Notez que le nom de chaque bouton de suppression est ajouté avec un numéro. Cela nous permet de savoir quel projecteur doit être supprimé.
  • Le projecteur n'est enregistré que si et seulement si l'entrée n'est pas vide. Cette condition est dans la boucle "while" de la fonction "form".

Limitation:

À partir de maintenant, chaque fois que nous avons cliqué sur "Enregistrer", l'ordre des projecteurs est réorganisé de 1 à n. Ce n'est pas très convivial, mais je prévois d'utiliser Ajax pour synchroniser le serveur frontal avec le serveur principal. Je ne sais pas encore comment.

Code source:

  • Depuis WordPress 4.7.2, cela fonctionne sans erreur.
  • Placez tout le code source dans le fichier "repeat.php" de votre répertoire de plugins. Si vous ne savez pas comment, veuillez le rechercher sur Google.

repeat.php

    <?php
/**
 * Plugin Name: Repeat Field
 *
 */

 class repeat_field_widget extends WP_Widget {

    /**
     * Sets up the widgets name etc
     */
    public function __construct() {
        $widget_ops = array(
            'classname' => 'repeat_field_widget',
            'description' => 'Repeat Field for Name input'
        );
        parent::__construct( 'repeat_field_widget', 'Repeat Field', $widget_ops );
    $tracker1;
    }

    /**
     * Outputs the content of the widget
     *
     * @param array $args
     * @param array $instance
     */
    public function widget( $args, $instance ) {
        // outputs the content of the widget
    $spotlight_add_row = ! empty( $instance['spotlight_add_row'] ) ? $instance['spotlight_add_row'] : '';
    $spotlight_row_appender = ! empty( $instance['spotlight_row_appender'] ) ? $instance['spotlight_row_appender'] : '';

    /**============== Spotlight 1 =========================*/
    $spotlight_image_link1 = ! empty( $instance['spotlight_image_link1'] ) ? $instance['spotlight_image_link1'] : '';
    $spotlight_add_image1 = ! empty( $instance['spotlight_add_image1'] ) ? $instance['spotlight_add_image1'] : '';
    $spotlight_image_preview1 = ! empty( $instance['spotlight_image_preview1'] ) ? $instance['spotlight_image_preview1'] : '';
    $spotlight_name1 = ! empty( $instance['spotlight_name1'] ) ? $instance['spotlight_name1'] : '';
    $spotlight_description1 = ! empty( $instance['spotlight_description1'] ) ? $instance['spotlight_description1'] : '';
    $spotlight_link1 = ! empty( $instance['spotlight_link1'] ) ? $instance['spotlight_link1'] : '';

    /**============== Spotlight 2 =========================*/
    $spotlight_image_link2 = ! empty( $instance['spotlight_image_link2'] ) ? $instance['spotlight_image_link2'] : '';
    $spotlight_add_image2 = ! empty( $instance['spotlight_add_image2'] ) ? $instance['spotlight_add_image2'] : '';
    $spotlight_image_preview2 = ! empty( $instance['spotlight_image_preview2'] ) ? $instance['spotlight_image_preview2'] : '';
    $spotlight_name2 = ! empty( $instance['spotlight_name2'] ) ? $instance['spotlight_name2'] : '';
    $spotlight_description2 = ! empty( $instance['spotlight_description2'] ) ? $instance['spotlight_description2'] : '';
    $spotlight_link2 = ! empty( $instance['spotlight_link2'] ) ? $instance['spotlight_link2'] : '';
    }

    /**
     * Outputs the options form on admin
     *
     * @param array $instance The widget options
     */
    public function form( $instance ) {
        // outputs the options form on admin
    $instance = wp_parse_args( (array) $instance, array( 'spotlight_add_row' => '', 'spotlight_row_appender' => '', 'spotlight_image_link1' => '', 'spotlight_add_image1' => '', 'spotlight_image_preview1' => '', 'spotlight_name1' => '', 'spotlight_description1' => '', 'spotlight_link1' => '',
    'spotlight_image_link2' => '', 'spotlight_add_image2' => '', 'spotlight_image_preview2' => '', 'spotlight_name2' => '', 'spotlight_description2' => '', 'spotlight_link2' => '' ));

    //Create Add and delete button
    $spotlight_add_row = $instance['spotlight_add_row'];
    $spotlight_row_appender = $instance['spotlight_row_appender'];

    /**================== Spotlight 1 ==============*/
    $spotlight_image_link1 = $instance['spotlight_image_link1'];
    $spotlight_add_image1 = $instance['spotlight_add_image1'];
    $spotlight_image_preview1 = $instance['spotlight_image_preview1'];
    $spotlight_name1 = $instance['spotlight_name1'];
    $spotlight_description1 = $instance['spotlight_description1'];
    $spotlight_link1 = $instance['spotlight_link1'];

    /**================== Spotlight 2 ==============*/
    $spotlight_image_link2 = $instance['spotlight_image_link2'];
    $spotlight_add_image2 = $instance['spotlight_add_image2'];
    $spotlight_image_preview2 = $instance['spotlight_image_preview2'];
    $spotlight_name2 = $instance['spotlight_name2'];
    $spotlight_description2 = $instance['spotlight_description2'];
    $spotlight_link2 = $instance['spotlight_link2'];

    $starter = 1; //Store which number to continue adding spotlight.
    $num = 1;
    $max_spotlight = 2; //number of spotlight allowed.
    static $tracker = array(0,0); //setup a tracker for each spotlight, zero mean none active.

    while($num <= $max_spotlight){
      $tempImage = 'spotlight_image_link' . $num;

       if ($$tempImage != ''){
        $starter++;
        $tracker[$num - 1] = 1;
?>
        <!-- Image input -->
        <div>
        <p class="spotlight-para">Spotlight <?php echo $num; ?></p>
        <p> <?php $tempImage = 'spotlight_image_link' . $num;  $tempDeleteName = 'deletespotlight_'. $num;?> <!-- store the combined name. -->
            <label for="<?php echo esc_attr( $this->get_field_id( $tempImage ) ); ?>"><?php esc_attr_e( 'Image\'s link:', 'text_domain' ); ?></label>
            <input
                   class="widefat"
                   id="<?php echo $this->get_field_id($tempImage); ?>"
                   name="<?php echo $this->get_field_name($tempImage); ?>"
                   type="text"
                   value="<?php echo esc_attr($$tempImage); ?>"
                   />
           <input style="float:right;" id="delete-spotlight" name="<?php echo $tempDeleteName; ?>" type="button" value="Delete Spotlight" class="button"/>
           <br />
        </p>
        </div>
<?php
      }
     $num++;
    }
    $id_prefix = $this->get_field_id(''); //get the widget prefix id.
?>
    <span id="<?php echo $this->get_field_id('spotlight_row_appender'); ?>"> </span>
    <div>
      <br />
      <input
            class="button"
            type="button"
            id="<?php echo $this->get_field_id('spotlight_add_row'); ?>"
            value="Click Me!"
            onclick="repeater.uploader('<?php echo $this->id;?>', '<?php echo $id_prefix;?>'); return false;"
            />
    </div>

    <script>
    jQuery(document).ready(function($){
      var tracker = <?php echo json_encode($tracker); ?>;
      var c1 = <?php echo json_encode($starter - 1); ?>;//index of the array.

      //disbale add button when reaches max spotlight.
      if(tracker.every(x => x > 0)){
        $('#' + '<?php echo $id_prefix; ?>' + 'spotlight_add_row').attr("disabled",true);
      }

      repeater = {
          //TRY to mass Number into this function........
          uploader :function(widget_id, widget_id_string){
            //Find the non active element
            var i;
            for (i = 0; i < <?php echo $max_spotlight; ?>; i++){
              if ( tracker[i] == 0){
                c1 = i;
                break;
              }
            }
            c1++;
            //alert(c1);



            $("#" + widget_id_string + "spotlight_row_appender").append('<div> <p class="spotlight-para">Spotlight '+c1+'</p><p> <label for="<?php echo esc_attr( $this->get_field_id( "spotlight_image_link'+c1+'")); ?>"><?php esc_attr_e( 'Image\'s link:', 'text_domain' ); ?></label>  <input  class="widefat" id="<?php echo $this->get_field_id("spotlight_image_link'+c1+'"); ?>"  name="<?php echo $this->get_field_name("spotlight_image_link'+c1+'"); ?>" type="text" value="" />  <input style="float:right;"id="delete-spotlight" name="deletespotlight_'+c1+'" type="button" value="Delete Spotlight" class="button"/><br /> </p></div>');
            //check element as active
            tracker[c1-1] = 1;

            //if all element is > 0, disable the deleteButton.
            if(tracker.every(x => x > 0)){
              $('#' + '<?php echo $id_prefix; ?>' + 'spotlight_add_row').attr("disabled",true);
            }
            //alert(c1);
            return false;
          }
      };

      $(document).on('click', '#delete-spotlight', function() {

        $(this).parent().parent().remove(); //remove the field.
        $('#' + '<?php echo $id_prefix; ?>' + 'spotlight_add_row').removeAttr("disabled"); //reset add button.

        //Get the name, and parse to get the ID.
        var deleteButtonName = this.name;
        var stringDeleteButton = deleteButtonName.split("_").pop();
        var deleteButtonID = parseInt(stringDeleteButton);

        tracker[deleteButtonID-1] = 0; //reset element
        //alert(tracker);
      });

    });
    </script>
  <?php
    }

    /**
     * Processing widget options on save
     *
     * @param array $new_instance The new options
     * @param array $old_instance The previous options
     */
    public function update( $new_instance, $old_instance ) {
        // processes widget options to be saved
    $instance = $old_instance;
    $instance['spotlight_add_row'] = sanitize_text_field($new_instance['spotlight_add_row']);
    $instance['spotlight_row_appender'] = sanitize_text_field($new_instance['spotlight_row_appender']);

    $increment = 1;
    while ( $increment <= 2 ){
      //increment variables
      $increment_image_link = 'spotlight_image_link' . $increment;
      $increment_add_image = 'spotlight_add_image' . $increment;
      $increment_image_preview = 'spotlight_image_preview' . $increment;
      $increment_description = 'spotlight_description' . $increment;
      $increment_name = 'spotlight_name' . $increment;
      $increment_link = 'spotlight_link' . $increment;

      $instance[$increment_image_link] = sanitize_text_field( $new_instance[$increment_image_link] );
      $instance[$increment_add_image] = sanitize_text_field( $new_instance[$increment_add_image] );
      $instance[$increment_image_preview] = sanitize_text_field( $new_instance[$increment_image_preview]);
      $instance[$increment_name] = sanitize_text_field( $new_instance[$increment_name] );
      $instance[$increment_description] = sanitize_text_field( $new_instance[$increment_description] );
      $instance[$increment_link] = sanitize_text_field( $new_instance[$increment_link] );

      $increment++;
    }
    $starter = 1;
    $num = 1;

    return $instance;
    }
}


function register_repeat_field_widget() {
    register_widget( 'repeat_field_widget' );
}
add_action( 'widgets_init', 'register_repeat_field_widget' );

Remarque rapide:

Je sais que ce n'est pas le code le plus propre, le plus sécurisé et le meilleur, mais j'apprends toujours. J'espère que cela aidera toute personne confrontée aux mêmes problèmes que moi.

2
Sengngy Kouch

Les formulaires de widget sont délicats pour la manipulation de JS. En général, vous ne devez jamais utiliser d'identifiants pour détecter des éléments dans le formulaire, mais une combinaison de classes et de find(), parent() etc.

La raison en est qu'il peut y avoir plus d'un formulaire sur la page HTML. Il est certain que sur la page d'administration du widget, un formulaire "modèle" ne s'affiche pas et IIRC est utilisé pour générer le formulaire d'un nouveau widget. Cela signifie qu'il y aura au moins deux éléments avec le même ID et qu'une tentative d'y accéder par les API DOM ne donnera pas un résultat cohérent.

1
Mark Kaplun