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);
3
  • By default, WordPress has an image uploader widget. Why do you need a custom one?
    – obiPlabon
    Commented Feb 17, 2018 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
    Commented Feb 17, 2018 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 Commented Feb 17, 2018 at 16:29

1 Answer 1

2

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');
4
  • That was my previous code. But it didn't work.
    – Alexander
    Commented Feb 17, 2018 at 13:09
  • Please check the updated answer
    – obiPlabon
    Commented Feb 17, 2018 at 15:35
  • That's amazing, thanks a lot for the help! I've spent almost all day figuring out what's wrong :)
    – Alexander
    Commented Feb 17, 2018 at 17:01
  • That's great, glad to hear that it saved your time.
    – obiPlabon
    Commented Feb 17, 2018 at 17:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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