I’ve posted a bug-report about this a few months ago (on WordPress trac (Widget Instance Form Update Bug)) and I thought I’d try writing about it here too. Maybe someone has a better solution to this issue than me.
Basically the problem is that if you drop a widget into a sidebar, the widget form doesn’t get updated until you manually press save (or reload the page).
This makes unusable all the code from the form()
function that relies on the widget instance ID to do something (until you press the save button). Any stuff like ajax requests, jQuery things like colorpickers and so on will not work right away, because from that function it would appear that the widget instance has not yet been initialized.
A dirty fix would be to trigger the save button automatically using something like livequery:
$("#widgets-right .needfix").livequery(function(){
var widget = $(this).closest('div.widget');
wpWidgets.save(widget, 0, 1, 0);
return false;
});
and add the .needfix
class in form()
if the widget instance doesn’t look initialized:
<div <?php if(!is_numeric($this->number)): ?>class="needfix"<?php endif; ?>
...
</div>
One drawback of this solution is that if you have lots of widgets registered, the browser will eat lots of CPU, because livequery checks for DOM changes every second (tho I didn’t specifically test this, it’s just my assumption 🙂
Any suggestions for a better way to fix the bug?
I did battle with a similar situation recently. Ajax in widgets is no joke! Need to write some pretty crazy code to get things to work across instances. I’m not familiar with live query, but if you say it checks the DOM every second, I might have a less intense solution for you:
You can pass this function a selector or jQuery object and it will return the instance ID of the current instance. I could find no other way around this issue. Glad to hear I’m not the only one 🙂
I don’t like answering my own question, but I feel this is the best solution so far:
This will fire the widget-save ajax request, just after a widget-save request has completed (if there was no response with the form html).
It needs to be added in the
jQuery(document).ready()
function.Now, if you want to easily re-attach your javascript functions to the new DOM elements added by the widget form function simply bind them to the “saved_widget” event:
Ran into this recently and it seems that in the traditional “widgets.php” interface any javascript initialization should be run directly for existing widgets (those in the
#widgets-right
div), and indirectly via thewidget-added
event for newly added widgets; whereas in the customizer “customize.php” interface all widgets – existing and new – are sent thewidget-added
event so can just be initialized there. Based on this the following is an extension of theWP_Widget
class which makes it easy to add javascript initialization to a widget’s form by overriding one function,form_javascript_init()
:An example test widget using this:
I think something exists in WordPress 3.9 that might help you. It’s the widget-updated callback. Use it like this (coffeescript):