xpages 2 partial refreshes from a required field - xpages

I have an inputText which is a required field on my Document.
<xp:inputText value="#{Cdoc.txt_NumeCompanie}" id="txt_NumeCompanie"
required="true" defaultValue="#{javascript:param.value}">
<xp:this.validators>
<xp:validateRequired message="Numele companiei este obligatoriu." loaded="true">
</xp:validateRequired>
</xp:this.validators>
<xp:eventHandler event="onchange" submit="false" disableValidators="true">
<xp:this.script><![CDATA[ XSP.partialRefreshPost("#{id:scrollDiv}", {
onComplete: function() {
XSP.partialRefreshPost("#{id:pers}");
}
});
]]></xp:this.script>
</xp:eventHandler>
</xp:inputText>
I also checked the Process data without validation ( from the Server tab ... ). But still no refresh is taking place.

You do not include the required second parameter on your second partialRefreshPost. Try this:
XSP.partialRefreshPost("#{id:scrollDiv}", {
onComplete: function() {
XSP.partialRefreshPost("#{id:pers}", {});
}
});
Update: you can use the onComplete event of the eventHandler to run your 2nd partial refresh. So use the traditional partial refresh of the first component and then run your 2nd partial refresh through the onComplete event:
<xp:inputText value="#{Cdoc.txt_NumeCompanie}" id="txt_NumeCompanie" required="true" defaultValue="#{javascript:param.value}">
<xp:this.validators>
<xp:validateRequired message="Numele companiei este obligatoriu." loaded="true">
</xp:validateRequired>
</xp:this.validators>
<xp:eventHandler event="onchange" submit="true" refreshMode="partial" refreshId="scrollDiv">
<xp:this.onComplete><![CDATA[XSP.partialRefreshPost("#{id:pers}", {});]]></xp:this.onComplete>
</xp:eventHandler>
</xp:inputText>

By setting submit="false", you're preventing any server-side processing from being triggered by the eventHandler itself. That means disableValidators="true" is irrelevant, because the XPages lifecycle is not being processed from the eventHandler.
Instead the refresh is being generated from the client-side code, the XSP.partialRefreshPost. That doesn't have an option to disable validation, as covered here How to disable validators using the XSP.partialRefreshPost method?. disableValidators="true" doesn't and cannot influence the processing of the partialRefreshPost. So chances are your validation is still running. To confirm that, add an errors panel into the initial refresh area.
partialRefreshGet may work, I'm not sure.
My usual approach in these scenarios is to refresh a single area that comprises both areas you wish to refresh. Then set submit="true" and disableValidators="true". But bear in mind that even if validation is disabled, data conversion is still checked so if you enter a text value in a number field, the partial refresh would still fail.

Ok, first thing to do is open your toolbox and look at the network traffic. This will help you to understand what is going on. You can use FireBug in FireFox or Developer tools in Google Chrome.
What network traffic occurs for the above snippet?
Edit:
Still waiting to hear what network traffic is generated...
But just looking at your code... - try set submit="true". I had a look at some of the code I have, and I am not sure that the extra empty param is required :-)
Could you explain what you are trying to obtain?
Edit
Ok, I see what you want. I had a quick view in some code. I am not doing exactly the same that you are. However, when I nest the partial refreshes I typically do it this way:
<xp:button id="button1"
styleClass="btn btn-danger btn-lg#{FishingTripEdit.typeInput eq '1' ? ' inActive' : ''}">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial"
refreshId="inputTypeSelected" disableValidators="true">
<xp:this.action>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:MyBean.setData('0')}]]></xp:this.script>
</xp:executeScript>
</xp:this.action>
<xp:this.onComplete><![CDATA[XSP.partialRefreshGet("#{id:buttonTopHolder}")]]></xp:this.onComplete>
<xp:this.script><![CDATA[return document.getElementById("#{id:triggerAsk}").value!=='1' ? true : confirm("Sure?")]]></xp:this.script>
</xp:eventHandler>
</xp:button>
So for the "first" refresh I use the builtin markup - and onComplete I add the second as plain JavaScript. I know this is an example with a partialRefreshGet (which I prefer to use if at all possible due to less overhead). But perhaps it can give you an idea....

Related

xpages button - possible to change text or item while events are running?

Is it possible to change the text on an <xp:button> element when the code under the onclick event is running (and the partial refresh is not completed)?
The XPages way is to use the onStart and onComplete properties (there's also onError):
<xp:button value="Search" id="button1">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial"
onStart="changeText()" onComplete="unchangeText()">
<xp:this.action><![CDATA[#{javascript:serverFunction();}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
You can pass the id of the button to the functions using "#{id:button1}" and use it to retrieve the button in CSJS.
We have something like that in place for our xp:button elements. We change the text and also add an FontAwesome "spinning wheel" until code is finished. At the start of our funtion we change text and icon, after code is finished - we revert to original xp:button text.
We use jQuery to modify the button element, basically you can to that with plain JavaScript (innerHTML) or dojo as well.
<xp:button value="Save" id="button-save" xp:key="submitSave">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script><![CDATA[submitSaveFunction();]]></xp:this.script>
</xp:eventHandler>
</xp:button>
submitSaveFunction {
$("button[id$=button-save]").attr("disabled", "true").addClass("disabled").html('<i class="fa fa-spinner fa-pulse fa-fw"></i> Saving');
.....your code.....
$("button[id$=button-save]").removeAttr("disabled").removeClass("disabled").html('Save');
}

SSJS code is not executed in XPages onclick

In my code I have the following Event Handler
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" disableValidators="true"
refreshId="#{javascript:compositeData.refreshid}">
<xp:this.script><![CDATA[
alert('clicked');
]]></xp:this.script>
<xp:this.action><![CDATA[#{javascript:print("jkafkjsfjk");}]]></xp:this.action>
</xp:eventHandler>
Unfortunately, I never get jkafkjsfjk printed in the console while CSJS code works fine and there's clicked alert pops up.
I know that the most common reason of not executing it has to do with some required fields equal to null or empty.
However, I've commented everything out but the code isn't executed anyway..
How do I resolve that and what's the reason?
Thanks in advance.
A couple of things...
First, if your CSJS returns false then the SSJS never runs (which is handy when you want the user to confirm...). I guess you should be alright here - but you could return true to be safe....
Second, partial refresh's, refresh ids, and partial executions can do things that may not be what you expect. So for the test I would just do a complete refresh and skip the id.
What kind of object is the eventhandler set on?
I normally use these kind of event handlers for links or buttons like:
<xp:button value="Add zone" id="button2" styleClass="btn-xs btn-primary">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="fields">
<xp:this.action><![CDATA[#{javascript:AssociationAdmin.createZone()}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
And this works fine :-)
Here is an example with a confirmation first:
<xp:link escape="true" text="Delete" id="link5" styleClass="action" rendered="#{javascript:!AssociationAdmin.isCatchInfoInUse(row.getKey())}">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete" id="eventHandler5">
<xp:this.action><![CDATA[#{javascript:AssociationAdmin.removeCatchInfo(row.key);}]]></xp:this.action>
<xp:this.script><![CDATA[return window.confirm("Are you sure you want to delete these fields: #{javascript:row.getName()}?\n\nDeletion cannot be undone!!")]]></xp:this.script>
</xp:eventHandler>
</xp:link>
Further notes:
You may want to submit without validating. You can do this by adding disableValidators="true" to your eventhandler
Please remember to have an id on the control where you have your eventhandler. Just wasted an evening and morning with the most strange behaviour cased by the button opening dialog did NOT have and id attributee...
Hope these samples will get you going :-)
/John

xpages go to a previous principal xpage

My scenario:
There is a navigator, having some links which redirect the user to some .xsp. Those .xsp contains some views listing certain documents. The users can create new documents using:
<xp:this.action>
<xp:openPage name="/doc.xsp" target="newDocument"></xp:openPage>
</xp:this.action>
Inside this doc., they can create other docs. ( with other datasource declared ) inside a <xe:dialog>. It has only one save and close button, which redirects me: into the current doc. if I opened the dialog from there or it directs me to the .xsp described above.
The problem: if I create a new Doc. and from its inside I create some docs from the dialog, with my Save button, I must hit it 2 times ( in most cases ) to redirect me to those .xsp described above. Why? because in this case my desired destination .xsp is not the PreviousPage, but the PreviousPreviousPage, the PreviousPage being doc.xsp?action=newDocument and the current page it is doc.xsp?documentId=E1141A490316FD88C2257D3400322723&action=openDocument, considering the fact that the doc. was already saved to open the dialog and from the save and close button I just redirect the users back to the main doc.
<xp:button value="Save" id="buttonSave" styleClass="lotusFormButton"
rendered="#{javascript:currentDocument.isEditable()}">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" immediate="false" save="false"
id="eventHandler1">
<xp:this.action>
<xp:actionGroup>
<xp:saveDocument var="Cdoc"></xp:saveDocument>
<xp:openPage name="$$PreviousPage"></xp:openPage>
</xp:actionGroup>
</xp:this.action></xp:eventHandler>
</xp:button>
How can I resolve this issue?
I found this solution and for my case it seems to be the most useful.
Return-to-last-view
You just log the page name in a scope variable ( when you're opening a view - in my case the principal Xpage which contains the view ) , and from the Save button I just return to the last view opened ( contained by the xpage ).
I hope I got it right:
You may want to have a look at "navigation rules". Your save button e.g. could return a SSJS value:
return "home"
where 'home' is the name of your rule, directing you to your index.xsp.
So no matter what you did when you used your doc.xsp, how many dialogs you opened, if you click this button that uses the nav rule it will bring you to the page. You used the $$PreviousPage placeholder which simply generates a simple CSJS
history.go(-1)
which then will get you in the trouble you face now.
Try replacing the code for the Save button in the dialog with the following, assuming the id for the xe:dialog is dialog1:
<xp:button value="Save" id="buttonSave" styleClass="lotusFormButton"
rendered="#{javascript:currentDocument.isEditable()}">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:
Cdoc.save();
var c = getComponent("dialog1");
c.hide("refreshPanel1");
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
The optional "refreshPanel1" passed to the hide method is the id of the containing element on the XPage to perform a partial refresh when the dialog is closed.

How can I duplicate a "cancel" button using a toolbar

I am using the toolbar control and that has several actions on it to allow the user to switch document modes, save, return to the view, etc.
I want to add a cancel button to allow the user to cancel their edits and switch them back to read mode.
Since the same event is shared by all these actions (I am using simple actions in computed action groups) I can't check off the "Do not validate or update data". If I do a context.redirectToPage("newpage.xsp") that will cause validation to happen.
I want to be able "cancel" the validation and then perform some action like switch to read mode or to another XPage. Any suggestions?
I guess I need a context.DontSave() method...Is there a method I can use to disable the validation/updating when submitting?
Thanks,
Howard
You can create a standalone cancel button that discards changes and reloads the current page. In the example below I have not taken into account that the current page can contain parameters such as editDocument, documentId etc.
<xp:button id="cancel" value="Cancel" rendered="#{javascript:document.isEditable()}">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete" immediate="true" save="false" id="eventHandler1">
<xp:this.action>
<xp:actionGroup>
<xp:openPage name="#{javascript:view.getPageName()}"></xp:openPage>
</xp:actionGroup>
</xp:this.action></xp:eventHandler>
</xp:button>

Is it possible to programmatically set the partial refresh element for an event?

I have a custom control I use for view filtering and I'd like to set the viewPanel that it filters based on a property of the custom control but in order to do this I would need to partially refresh the viewPanel whatever the ID of that viewPanel is. I know I could put a facet in my custom control and put a panel around the facet and then just partially refresh that panel, but I was wondering if there is a way to do this without having to drop the viewPanel into a facet. Here is the button code:
<xp:button value="Filter" id="btnFilter">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="viewPanel1">
<xp:this.action><![CDATA[#{javascript:filterView();}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
Thanks
Oops, just realized I could do this by adding a computed element ID for the partial refresh set to the compositeData value. I missed that little triangle next to "Specify Element ID".
<xp:button value="Filter" id="btnFilter"> <xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="#{javascript:compositeData.viewPanel}">
<xp:this.action><![CDATA[#{javascript:filterView();}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
You could use the dynamic viewpanel of the extension library.

Resources