Object added with event listener isn’t available until editing doc for second time

While implementing the solution suggested in this thread I have come across two problems:

  1. The fields associated with an Object aren’t displayed until I save and then edit the document for a second time. I presume this is because the Object isn’t present until after save, or I’m calling $doc.getObject(‘Content Manager.Code.Content Manager Reduced Class’).xWikiClass before the event listener actually adds the object.

  2. Server side validation redirects to preview of page instead of back to edit when validation returns False.

I would be extremely grateful if anyone can help address these two issues.

This is what I’ve done to allow display (during edit) of 3 input fields attached to the XObject inserted by an event listener on document create:

Firstly, and for testing purposes, I’ve added the following two lines to “editwysiwyg.vm”. I’ll probably move these to a better location when I get everything working.

#set($mydoc = $xwiki.getDocument("Content Manager.Code.Form and Validation")) 
$mydoc.getRenderedContent()

Where “Content Manager.Code.Form and Validation” contains:

        <div class="xform">
            ## Iterate over the properties of the Content Manager Reduced Class
			#set($discard = $doc.use('Content Manager.Code.Content Manager Reduced Class'))
            #set($class = $doc.getObject('Content Manager.Code.Content Manager Reduced Class').xWikiClass)
            #foreach($prop in $class.properties)
                <b>$prop.prettyName</b>
                $doc.display($prop.getName())
            #end 
	    </div> 

    ## Invoke validation
    <input type="hidden" name="xvalidate" value="1" />
    ## Set the Groovy script which will be used for validation
    <input type="hidden" name="xvalidation" value="Content Manager.Code.Content Manager GroovyValidation" />

    #if(($xcontext.validationStatus.errors&&$xcontext.validationStatus.errors.size()>0)||($xcontext.validationStatus.exceptions&&$xcontext.validationStatus.exceptions.size()>0))
    <div class="validation-errors" style="border: 1px solid grey; padding: 10px;">
    This is a recap of all errors in this page (change the form to show errors only at the top or only next to the fields):

    #foreach($error in $xcontext.validationStatus.errors)
    <font color="red">$xwiki.parseMessage($error)</font><br />
    #end

    #foreach($exp in $xcontext.validationStatus.exceptions)
    <font color="red">$exp</font><br />
    #end
    </div>
    #end

Note that when placed in a sheet this code works fine, so I’m assuming my problems have something to do with the fact I’m calling it from a template file.

Sounds like you are not reacting to the right event. In you use case you should listen to DocumentUpdatingEvent event and directly modify the XWikiDocument you get as parameter of the onEvent. Then this document will be saved after your listener.

I thought that might be the case too to start with, but the same event listener successfully does other things on page create.

Here is my code for context:

getEvents looks like this:

{{groovy}}
import org.xwiki.bridge.event.*
xcontext.method.output.value = [new DocumentCreatingEvent(), new DocumentUpdatingEvent()]
{{/groovy}}

And the actual object add code in onEvent looks like this:

import com.xpn.xwiki.objects.BaseObject;
import org.xwiki.model.reference.EntityReference;
import org.xwiki.model.reference.DocumentReference;

def docSource = xcontext.method.input.get(1)
[...]
    def xc = xcontext.getContext();
    def docRef = services.model.createDocumentReference('', ['Content Manager', 'Code'], 'Content Manager Reduced Class')
    BaseObject newuserrightsobject3 = docSource.getXObject(docRef, true, xc)
[...]

Thanks,
Ben

So you seems to be using the right “*ing” event. Not so sure I fully understand what is your issue actually.

What do you exactly mean by “displayed” in the first message exactly ? Are you talking about the object editor UI, some form in a sheet you wrote ?

Side note:

You really don’t need to go trough services.model.createDocumentReference in Groovy, it’s mostly here to workaround the fact that Velocity does not allow creating objects. And in your case you should use LocalDocumentReference which does take a wiki reference.

Thanks for the side note Thomas, I will adjust accordingly.

It’s a form that was originally in a sheet, but I want this to be applied to every new page created within a space, even pages created from imported word documents, so I have changed my approach to that suggested on the thread mentioned in my original question.

This is what it should look like when editing a page with the WYSIWYG editor, three drop down list fields between the editor and the version summary box:
Capturedsfdasf

So from what I understand the situation is the following:

  • a xclass MySpace.MyClass associated to a sheet MySpace.MySheet
  • a listener automatically adding MySpace.MyClass xobjects to documents when they are saved

-> when you go to one of these documents you don’t see the sheet

is that it ?

I removed the association to any sheet from the xclass as I don’t want it overriding the sheet of whatever page the object gets added to. It could be a diagram doc, doc imported from word, custom AWM doc, etc.

As I’ve removed the sheet, I am adding the display code for the xobject in a template file, in this case “editwysiwyg.vm”. This is important because I want a user to be able to change the values of it’s properties when editing a page.

When I first create a new doc, the object’s fields don’t appear, neither does the object if I click on Edit >> Objects. However, once I have saved the doc (i.e. for the first time) I can click edit again and the fields appear, similarly Edit >> Objects now reveals the object.

Ignoring my validation problem for a moment (which I believe to be associated with the fact that I am calling it from a template file), essentially problem 1 could be re-worded as: Object only appears on doc update but not on create despite event listener listening to both events (I’m assuming the save button triggers a doc update event)

Note that I’m using XWiki 9.5.1

The document is not created when you enter edit mode. Click Cancel and you’ll see. The document is created when you click Save the first time. So the behavior you describe is normal considering that both events you are listening too are called after you click Save.

Read again my comment on Help customising Diagram.DiagramSheet - #4 by mflorea and you’ll see that you can add the object from the template, if it doesn’t exist already, and with the help of the “updateOrCreate” object policy it will be saved.

Hope this helps,
Marius

Ah… OK, starting to make more sense now. Is there a more detailed list and explanation of events and what actually triggers them anywhere? At the moment I’m also interested in knowing if there is a PreviewEvent and what event gets triggered when moving a doc from one location to another?

As I can’t use a sheet for displaying my objects properties I’ve added #set($contentManagerClass = $doc.getObject('Content Manager.Code.Content Manager Reduced Class', true)) and <input type="hidden" name="objectPolicy" value="updateOrCreate" /> to “Content Manager.Code.Form and Validation” and removed everything from the event listener. I should have thought of that in the first place.

I still can’t get this bit to work though:

Do I somehow need to tell xvalidate to redirect to the correct editor? The code works fine when placed in an AWM sheet but doesn’t seem to like being called from a template file with:

Thanks,
Ben