Support in-place edit for properties of not-yet-existing objects

At the moment, when you create an in-place editable property for the property of an object but the object doesn’t exist yet, simply nothing is displayed where the edit field should be. I propose to change this with the following new features:

  • Support data-object-policy="updateOrCreate" to enable object creation when the property is saved (transforms into objectPolicy=updateOrCreate parameter on save) in editableProperty.js.
  • editableProperty.js uses the display.vm template to display the value both in edit and view mode so this needs to support not-yet-existing objects by displaying the default value (currently, nothing is displayed). Internally, display.vm calls #displayObjectProperty from display_macros.vm. I see two options:
    1. Just create a new object in #displayObjectProperty if no existing object is found, i.e., change its behavior (currently, the behavior is to just output nothing)
    2. Also pass the objectPolicy parameter (or another parameter) to display.vm and translate this into a new option for #displayObjectProperty that would trigger the behavior to create an object if it doesn’t exist yet.

While the first option is easier to implement, the second option has the advantage not to change existing behavior. Do you have any preferences?

I need this feature for enabling heading numbering either in the info tab if the New User Interface Extension Point (UIXP) for Page Information should be accepted or in an additional tab otherwise. I would like to re-use the existing UI and backend to avoid creating redundant code and to make it consistent for the user while hiding the complexity that the object that stores the configuration might not exist yet.

In the second option, you are proposing to create the object while viewing a form that you might not actually save in the end ?

This would actually be the behavior with both options, in both cases #displayObjectProperty would create a temporary object to display the edit/view HTML, just that the first option would always do that if the object doesn’t exist while the second option would only do that if a (new) parameter is passed.

I don’t really understand what you propose then.

I don’t know in-place editor code, so I don’t know what exactly data-object-policy is but the point of updateOrCreate option in SaveAction is to create the missing object automatically while saving. But maybe those are two totally different things ?

Okay, I’ll try to explain this in other words. The in-place editor is what is used to enable in-place editing of object properties both in apps created using AWM and also in the information tab at the bottom of the page. Currently, this only works if the object already exists but you cannot just display some default value for non-existing objects and when you click edit, the form is displayed and when you click save, the object is created. To support this behavior, we need two components:

  1. Display the default value and the edit form also if the object doesn’t exist
  2. Create the object on save

For the first point, we need server-side support in display.vm as this is what is used to display the value and the form (via some Ajax request), this is the second point in my proposal above. For saving, the second point here, we then need to pass the objectPolicy=updateOrCreate parameter to the server, and I propose to read the objectPolicy parameter from a data-attribute of the dt element where we already store other parameters in data attributes like the name and the type of the property as I don’t think this parameter should be set by default.

The not very clear part for me was what exactly did you mean by “creating a new object”. It seems like you are not really proposing to actually add an object in the stored document and just propose a hack done only on the cloned Document instance which does not exist anywhere else than in the current thread, right ?

That’s a good point which I’ve also just discovered. My PoC code actually just called the newObject method on the document instance whose documentation didn’t imply to me that it would modify the document as it just says “Creates a New XWiki Object of the given classname”. However, by reading the code I found out that it indeed modifies the document which is not good indeed. I’ve started to investigate other ways, e.g., using a clone of the document, though so far I haven’t found how this works in Velocity. Do you have any suggestions how this could work?

Depends where is your code located. If you are in a script and manipulate Document (and not XWikiDocument) then you are fine since as I said what you modified is a cloned version of the document and not the cached one. If you have in Java and manipulate a XWikiDocument coming directly from XWiki#getDocument you might want to clone it before modifying it.

I am in a velocity script so I should be fine, I’m just worried that this might have side effects in other parts. E.g., if another script that is executed afterwards wants to display the author, the author might be changed (or does each script get its own clone?). While this is not an issue in the Ajax request, the macro could also be used in other contexts (and in fact I would like to also use the same macro in the UI extension to display the default value). I’ve just checked what the object editor does, and it also seems to just add a new object to $doc in editobject.vm.

Not each script. The question is more, is the context isolated or not, for example two Velocity scripts in the same wiki content will share the same $doc instance.