1

I'm trying to make basic image upload widget. The uploader is working, however a button Save is not active after selecting new image. There is a hidden input where the value of new image is updating. But even after the value updated, WordPress doesn't recognize it. Only if I manually edit this input, the Save button is activated.

So here is my PHP code:

  // setup the widget name, description etc.
  function __construct() {
    $widget_options = array(
      'classname'   => esc_attr( "widget-about text-center" ),
      'description'  => esc_html__( 'About me widget', 'lami' ),
      'customize_selective_refresh' => true
    );
    parent::__construct( 'lami_profile', 'Lami About Me', $widget_options);
  }


  // front-end display of widget
  function widget( $args, $instance ) {

    extract( $args );
    echo $args['before_widget'];

    if ( ! empty( $instance['image_url'] ) ) {
      $alt = get_post_meta( attachment_url_to_postid($instance['image_url']), '_wp_attachment_image_alt', true );
      ?>
        <img src="<?php echo esc_url( $instance['image_url'] ); ?>" class="widget-about-img" alt="<?php echo esc_attr( $alt ); ?>">
      <?php
    }


    echo $args['after_widget'];
  }


  // back-end display of widget
  function form( $instance ) {

    $instance = wp_parse_args(
      (array) $instance,
      array(
        'image_url' => '',
      )
    );

    $image = ( ! empty( $instance['image_url'] ) ? $instance['image_url'] : '' );

    ?>  


      <!-- Image -->
      <h4><?php esc_attr_e( "Choose your image", 'lami' ); ?></h4>
      <p>        
        <img class="deo-image-media" src="<?php echo esc_url( $image ); ?>" style="display: block; width: 100%;" />
      </p>
      <p>
        <input type="text" class="deo-image-hidden-input widefat" name="<?php echo $this->get_field_name( 'image_url' ); ?>" id="<?php echo $this->get_field_id( 'image_url' ); ?>" value="<?php echo esc_url( $image ); ?>" />
        <input type="button" class="deo-image-upload-button button button-primary" value="<?php esc_attr_e('Choose Image','lami')?>">
        <input type="button" class="deo-image-delete-button button" value="<?php esc_attr_e('Remove Image', 'lami') ?>">
      </p>


    <?php
  }


  // update of the widget
  function update( $new_instance, $old_instance ) {
    $instance = $old_instance;
    $instance['image_url'] = ( ! empty( $new_instance['image_url'] ) ) ? strip_tags( $new_instance['image_url'] ) : '';
  }

}


add_action( 'widgets_init', function() {
  register_widget( 'Lami_About_Widget' );
});

And JS code for Uploader and Buttons

(function($) {
  "use strict";

  /* WordPress Media Uploader
  -------------------------------------------------------*/
  function upload(type) {
    if ( mediaUploader ) {
      mediaUploader.open();
    }

    var mediaUploader = wp.media.frames.file_frame = wp.media({
      title: 'Select an Image',
      button: {
        text: 'Use This Image'
      },
      multiple: false
    });

    mediaUploader.on('select', function() {
      var attachment = mediaUploader.state().get('selection').first().toJSON();
      $('.deo-' + type + '-hidden-input').attr('value', attachment.url);
      $('.deo-' + type + '-media').attr('src', attachment.url);
    });
    mediaUploader.open();
  }

  $('body').on('click', '.deo-image-upload-button', function() {
    upload('image');
  });

  $('body').on('click', '.deo-image-delete-button', function() {
    $('.deo-image-hidden-input').attr('value', '');
    $('.deo-image-media').attr('src', '');
  });

})(jQuery);
  • By default, WordPress has an image uploader widget. Why do you need a custom one? – obiPlabon Feb 17 '18 at 12:01
  • This widget will also contain textarea and checkbox fields. I cut down all the other fields for now, just to focus on image upload. – Alexander Feb 17 '18 at 13:11
  • I would save only the id of the image and not the full url, unless you explicitly need to support external urls – Mark Kaplun Feb 17 '18 at 16:29
1

Updated

Actually, you have to trigger change event to activate the Save button. WordPress widget handler listens to only changes. When you update the input field value with JS, DOM doesn't trigger any change. That's why we have to trigger manually. Please check the following code -

$('.deo-' + type + '-hidden-input').val(attachment.url).trigger('change');
  • That was my previous code. But it didn't work. – Alexander Feb 17 '18 at 13:09
  • Please check the updated answer – obiPlabon Feb 17 '18 at 15:35
  • That's amazing, thanks a lot for the help! I've spent almost all day figuring out what's wrong :) – Alexander Feb 17 '18 at 17:01
  • That's great, glad to hear that it saved your time. – obiPlabon Feb 17 '18 at 17:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.