Make WordPress Core

Opened 14 years ago

Closed 7 years ago

#14686 closed defect (bug) (wontfix)

Widget Instance Form Update Bug

Reported by: digitalnature's profile digitalnature Owned by:
Milestone: Priority: normal
Severity: normal Version: 3.0.1
Component: Widgets Keywords: has-patch
Focuses: Cc:

Description

Hi.

When dragging and dropping a widget into a sidebar the widget form doesn't get properly updated, unless you manually press the "Save" button. However the widget instance data is saved (you can see the widget in the frontend even if you don't press 'save').

This problem is noticeable when you're developing a widget and want to display some widget options in the form based on the widget's location or position. You can't do this because $widget->id or $widget->number appear to be initialized within the form() function only after you press Save...

I can provide the code of a test widget if necessary

Attachments (2)

14686.diff (397 bytes) - added by scribu 14 years ago.
doesn't fix anything
widgets.js.patch (432 bytes) - added by dgwyer 12 years ago.

Download all attachments as: .zip

Change History (18)

#1 @scribu
14 years ago

  • Keywords reporter-feedback added

I can provide the code of a test widget if necessary

Please do.

#2 @digitalnature
14 years ago

a basic example:

class test_widget extends WP_Widget{
  function test_widget(){
    $this->WP_Widget(false, 'test');
  }

  function widget($args, $instance){
    echo 'front-end';
  }

  function form($instance){
    print_r($this);
  }
}
add_action('widgets_init', create_function('', 'register_widget("test_widget");'));

$this->id, $this->number and other variables are only available after you press the Save button.

#3 @scribu
14 years ago

  • Keywords widgets reporter-feedback removed

Confirmed: when the widget is saved for the first time, the form is not updated.

That's because $wp_registered_widget_controls[$widget_id] is NULL.

To fix this, we have to get rid of all the global $wp_registered_widget_* rubbish.

@scribu
14 years ago

doesn't fix anything

#4 @scribu
14 years ago

A dumb workaround would be to automatically click the Save button via JavaScript.

#5 @mdawaffe
14 years ago

  • Keywords needs-patch added
  • Milestone changed from Awaiting Review to Future Release

#6 @mfields
14 years ago

  • Cc michael@… added

#7 @dgwyer
13 years ago

I ran into this problem today. Thought it was something wrong I was doing until I got pointed to this ticket.

My specific issue was not being able to access the jQuery '.click' event when a new widget is dragged into a widget area. You can only do so once the widget has been Saved.

I wanted to hide/show an advanced section of widget options via a jQuery toggle button. This works great apart from the very first time the widget is dragged into the widget area.

As as a stop gap I am looking into automatically clicking the Save button via JavaScript, but this method is a bit of a hack, so it would be great if this was given a closer look for the next release or two.

#8 @dgwyer
13 years ago

  • Version changed from 3.0.1 to 3.3

When you first drag a widget into a widget area the 'save-widget' and 'widgets-order' ajax requests are fired, and when you manually click to save the widget the 'save-widget' ajax request is fired again.

However, the widget object is not accessible on the first ajax request. If the widget object could be set on the FIRST ajax request then there wouldn't be a problem.

Just wondering why it only sets the widget object on the second 'save-widget' ajax response?

Last edited 13 years ago by dgwyer (previous) (diff)

#9 @azaozz
13 years ago

The first 'save-widget' is run to actually create the widget instance in PHP (i.e. let the back-end know there's a new instance of that widget and run any PHP hooks on it). Then all of the new widget instance's HTML is loaded into the new widget "wrap" on the front as return from that XHR request. This includes any changes made by the PHP hooks.

Don't think there's a way around this, seems we can fire a custom event after the initial XHR to trigger changes that need to be made by JS on adding new widget instance.

#10 @SergeyBiryukov
13 years ago

  • Version changed from 3.3 to 3.0.1

Version number indicates when the bug was initially introduced/reported.

#11 @digitalnature
13 years ago

I posted a fix here, still kind of "hacky":
http://wordpress.stackexchange.com/a/37707/1986

This basically fires another save action again after the buggy save action has completed...

I would prefer a proper fix though, by making the first save action return widget instance form HTML

Last edited 13 years ago by digitalnature (previous) (diff)

@dgwyer
12 years ago

#12 @dgwyer
12 years ago

Added a patch that fixes the issues in this ticket. It basically fires another XHR request when a widget is FIRST dragged into a widget area.

The patch along with the test widget code above works fine. Plus, JS/jQuery is available to the widget, without having to manually click Save, so you can easily add jQuery tabs or toggle advanced widget options etc.

Seeing as this extra XHR request fires ONLY the first time a widget is dragged into a widget area I think it's an acceptable fix.

Obviously it would be preferable to have the form HTML returned along with the first XHR request but it seems this is not possible without some fundamental changes to the widget code (see comment 9 from azaozz).

It 'almost' tantalizingly seems like this is possible looking at the code in ajax-actions.php as the initial XHR request returns nothing back to widgets.php. However there is no access to the global $wp_registered_widget_controls variable in wp_ajax_save_widget() during the initial XHR request so we can't just return the form HTML as a response.

Last edited 12 years ago by dgwyer (previous) (diff)

#13 @dgwyer
12 years ago

  • Keywords has-patch added; needs-patch removed

#14 follow-up: @dgwyer
10 years ago

The patch I added works on the widgets admin page but not on the Customizer. When adding new widget instances on the Customizer similar code is needed to make sure the widget form gets properly updated.

#15 in reply to: ↑ 14 @westonruter
10 years ago

Replying to dgwyer:

The patch I added works on the widgets admin page but not on the Customizer. When adding new widget instances on the Customizer similar code is needed to make sure the widget form gets properly updated.

When implementing widgets in the Customizer, I intentionally made it so that the widget form would not submit when first added. If you try submitting an empty widget form, oftentimes a widget form may then display a validation/error message about a field being required. It would be a poor experience if adding a widget would be immediately followed by an error message displayed.

#16 @westonruter
7 years ago

  • Milestone Future Release deleted
  • Resolution set to wontfix
  • Status changed from new to closed

This will be fixed on the widgets admin screen and in the customizer when widgets make use of a default instance. See #35574.

Note: See TracTickets for help on using tickets.