in_place_editing plugin, but my form setup was just too complex for it to work. (From doing some reading up online, the plugin also has some other issues and hasn't been maintained. Because of this there are several alternative plugins out there.) But I eventually wound up finding a solution I could adapt and use.So after implementing that, simple in-place editing worked beautifully! Unfortunately, simple in-place editing isn't quite enough for my app. When a page item is updated, sometimes I need it to update another item on the page. The script.aculo.us Ajax.InPlaceEditor is only designed to update one page item--the one that was edited. I tried working around it by changing something like this (in my controller action where I handled the AJAX call):
render :text => new_value
To something like this:
render :update do |page|
page.replace_html(original_page_id_to_update, :text => new_quantity)
page.replace_html(secondary_page_id_to_update, :text => new_value)
end
That didn't quite work. It updated the
secondary_page_id_to_update element correctly, but instead of putting new_quantity into original_page_id_to_update, it put in something like this:
try { Element.update("original_page_id_to_update", new_quantity); Element.update("secondary_page_id_to_update", new_value); } catch (e) { alert('RJS error:\n\n' + e.toString()); alert('Element.update(\"original_page_id_to_update\", new_quantity);\nElement.update(\"secondary_page_id_to_update\", new_value);'); throw e }
I was stumped on this for quite a while. Spent a lot of time scouring The Google for answers, digging into the script.aculo.us documentation for Ajax.InPlaceEditor, and examining the actual Ajax.InPlaceEditor code. What my web searches turned up was that I'm not the only person with this problem--I found several forum posts on different sites from people trying to do the same, or similar, things. Unfortunately, none of them had a solution. :(
So I went for a run to take a break, then came home to take a shower and like Archimedes, I had a "Eureka!" moment. (Though his was in the bath.) I realized what was happening was that both of my
replace_html calls were actually working, but as part of what Ajax.InPlaceEditor does it returns the final value of the render call, and sticks it into the field that was edited. This is just the default behavior, as it assumes you only want to update that one field.Looking into the Ajax.InPlaceEditor code, I found this (relevant lines in bold):
handleFormSubmission: function(e) {
var form = this._form;
var value = $F(this._controls.editor);
this.prepareSubmission();
var params = this.options.callback(form, value) || '';
if (Object.isString(params))
params = params.toQueryParams();
params.editorId = this.element.id;
if (this.options.htmlResponse) {
var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
Object.extend(options, {
parameters: params,
onComplete: this._boundWrapperHandler,
onFailure: this._boundFailureHandler
});
new Ajax.Updater({ success: this.element }, this.url, options);
} else {
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
Object.extend(options, {
parameters: params,
onComplete: this._boundWrapperHandler,
onFailure: this._boundFailureHandler
});
new Ajax.Request(this.url, options);
}
if (e) Event.stop(e);
}
What was happening was that it was creating a new Ajax.Updater, which is meant to update a single element with the return value from the url it calls, which turned out to be that chunk of Javascript above when I used the
render :update block. The Javascript was being eval'd correctly, and updating both my fields, but then Ajax.Updater was re-updating the 1st field with the result of the render block, which was that chunk of Javascript. (BTW, I think this Rails bug is the same thing, but they didn't see that anything was being eval'd because they only had the one field being updated, so their guess was that the eval was failing.)I tweaked the Ajax.InPlaceEditor code to replace the Ajax.Updater line with the Ajax.Request line, and suddenly everything worked! But that didn't seem like the right solution, so I looked at the logic in that block. It checks
options.htmlResponse, so I tried setting :htmlResponse to false where I set up the Ajax.InPlaceEditor, and voila! It worked.So hopefully this will be useful to people, and turns out to be very easy. Here's the summary:
- Use a
render :updateblock with as manyreplace_htmlcalls as you need (including one to update the in-place edit field itself). - Set
:htmlResponsetofalsewhen you set up your Ajax.InPlaceEditor.
And that's it!

2 comments:
Thank you for posting this! I was using the same updated in_pace_editor, and knew there was some way to make it stop trying to update the field, but your post was the first to solve the problem - just threw :htmlResponse => "false" into the :ajax section of the editable_content. Thanks!
Great, glad it was useful!
Post a Comment