This document explains the way to enhance a Display field in Form Widget to be able to use Ajax.InPlaceEditor. Refer to the following JIRA issue for the implementation progress of this enhancement: OFBIZ-1859. The initial code for this enhancement is checked in and the patch for improvements is posted on the same issue.
In Form Widget a display field is used to render any non-editable content. The text is usually rendered in a span (td if no widget-style is applied). We can use id attribute with the span tag. Our goal is to use Ajax.InPlaceEditor for a display field in form widget so that we can in place edit by clicking on any non-editable content rendered in our view.
Ajax.InPlaceEditor allows the use to edit a non-editable content by simply clicking on it. This turns the static element into an editable zone (either single-line or multi-line), and pops up submit and cancel buttons to allow user to commit or rollback the modification. It then synchronizes the edit on the server-side through AJAX, and makes the element non-editable again. There can be three types of in place editions of a non-editable content:
- single-line(default) : Editor has only one row.
- multi-line: If the non-editable content has line breaks or externally value for the rows option is supplied with the value>=3 a text-area with rows>=3 is rendered to edit the non-editable content.
- collection-editor: A select box is render with a set of selectable options for the non-editable content. Ajax.InPlaceCollectionEditor is used for this purpose.
Current implementation is focused on to provide single/multi line edit feature in a display field of Form Widget.
Here is the implementation for this particular enhancement.
Extending <display> element in Widget-Form.xsd
Added a new sub element <in-place-editor> and define following attributes with default values set for some of the attributes. These attributes allows the developer to set the options that are passed to Ajax.InPlaceEditor function.
- url (required)
- cancel-control ('link' | 'button' | false)
- field-post-creation ('activate' | 'focus' | false)
- html-response ('false' | 'true')
- ok-contol ('button' | 'link' | false)
- submit-on-blur ('false' | 'true')
- update-after-request-call ('true' | 'false')
Sub-elements of <in-place-editor>:
- <simple-editor>: It is must to include this sub element while using in-place-editor, else xml will not be parsed. This element has two attributes namely "rows" and "cols" which enables you to choose between single-line and multi-line edits.
- <field-map>: <in-place-editor> refers this already existing element of Widget-Form.xsd. It can have zero or more occurrences. This element is used to define the extra parameters that needs to be passed to the request for updating our non-editable content.
Handling <in-place-editor> Element
Defined a new class org.ofbiz.widget.form.ModelFormField.InPlaceEditor which will get attributes of <in-place-editor> element and set their values. It also handles the sub elements as well. Defined required methods and a constructor for the same.
Defined a new variable of org.ofbiz.widget.form.ModelFormField.InPlaceEditor class in org.ofbiz.widget.form.ModelFormField.DisplayField class. Added code in the constructor of org.ofbiz.widget.form.ModelFormField.DisplayField class to parse the <auto-complete-options> element and if found instantiate org.ofbiz.widget.form.ModelFormField.InPlaceEditor class.
Defined methods in org.ofbiz.widget.form.ModelFormField.DisplayField class to get and set (instantiate) object of org.ofbiz.widget.form.ModelFormField.InPlaceEditor class.
Modifications in org.ofbiz.widget.html.HtmlFormRenderer.renderDisplayField()
Implemented a function ajaxInPlaceEditDisplayField() in selectall.js which takes elment, url and a hash of options as parameters and calls Ajax.InPlaceEditor passing all these parameters to it.
Changes in Ajax.InPlaceEditor class of controls.js
In the current implementation if htmlResponse is set to true(which is set as default) Ajax.Updater is called which updates the edited element with the responseText once the request call is complete. In OFBiz framework, first a service returns a response which contains many information, and second we cannot set every non-pk attribute as an out parameter in a service. So this blocks us from properly updating the edited element. On the other hand if htmlResponse is set to false Ajax.Request is called which on successful completion does not update the edited element with new value. We can now use Ajax.Request but we need it to update the edited element with new value. For this I introduced a new option in Ajax.InPlaceEditor named updateAfterRequestCall which if set to true updates the element with new value after Ajax.Request call is completed and if set to false sustains the original behavior. First we grab the value of the editor in the global variable paramValue in handleFormSubmission() function. Than an onSuccess callback function updateElement() is called in Ajax.Request, which, if updateAfterRequestCall is set to true, updates the element with paramValue.