Widget media uploader doesn’t opens after widget save

Ok, I finally found what causing the problem and want to share my solution here, in case if someone has the same experience. It’s very sad though that this information is not highlighted anywhere ( codex, wp blogs, stackexchange etc. ).

The first problem is how to bind click event to the button. If you bind it directly on button selector, after saving the widget WordPress will refresh it and unbind click event from that button. So the solution here is to click on the body and then delegate it to the button selector:

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

The second problem was that after widget save, the hidden input is not populating with url of the selected image anymore. That was happening because of how I cached the input and image elements into the variables outside of mediaUploader select event. Simply placing this elements inside is solving this problem:

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

So after all cleaning and optimizations, my code now looks like this:

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

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

    if ( mediaUploader ) {
      mediaUploader.open();
    }

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

    mediaUploader.open();

  });

Hope this information will be helpful for you 😉