I've just started using the xe:applicationLayout for an application. I have added a "Basic Node" to the "Place Bar". I want to run some server side JavaScript code onClick of the node/button. I have tried computing the onClick property of the Basic Node, but this doesn't do anything and it seems like the onClick only runs client side JavaScript.
Is there a property or node that can run SSJS? Thanks for any help.
Set the submittedValue property of the node. ( the procedure is the same for all places in the application layout; here is an example snippet for the banner.ApplicationLinks )
<xe:this.bannerApplicationLinks>
<xe:basicContainerNode styleClass="firstApplication" label="${langString_CRM['CREATE']}">
<xe:this.children>
<xe:basicLeafNode submitValue="company_new"
Then add an event handler to your page and run your SSJS depending on the submitted value
<xp:eventHandler event="onItemClick" submit="true"
refreshMode="partial" disableValidators="true" refreshId="cois_application_layout"
execMode="partial">
<xp:this.action><![CDATA[#{javascript:
var submittedValue=context.getSubmittedValue();
// evaluate the submitted value here ...
Not the nicest version but it works.
Add buttons to the XPage and hide then using css.
In your application layout add a client side script that gets a handle to the buttons using
dojo.byId and do a click() on them. Then it's easy to have different panels update when you click on different buttons.
Related
I have a span tag with an onCLick event handler. I would like to disable the event handler based on the value of a scope variable. The scope variable is being set when I click a checkbox.
How can I do this?
Thanks for your input!
Dan
In client side part of the event use this code.
return !#{sessionScope.disableEvent};
That should render as
return !false; // continues to SSJS
or
return !true; // no SSJS
Event handlers have a rendered-attribute that you can calculate.
If the span in question is in the area that's being refreshed, you can use this attribute to control if the event handler is active or not.
E.g.
<xp:eventHandler event="onclick" rendered="#{viewScope.someVariable == 'someValue'}" ... />
I have a Xpage with two custom controls containing editable fields tied to the single data source on the Xpage. On the Xpage I use a xe:dialog that contains a button to save the data source document1 (using SSJS). No validation is occurring yet. I use a xe:dialogButtonBar to call the xe:dialog (using CSJS) which opens fine and then click the OK button containing Action Save Document data source.
diablogButtonBar onClick call to open dialog.
XSP.openDialog("#{id:dialogSaveAsDraft}");
With this configuration the document is saved but the editable fields are not created nor data saved. The Xpage has the following two properties set, computeWithForm: onsave, action:editDocument but have tried createDocument too.
Here is the twist: If I take the button in the xe:dialog and place it outside the xe:dialog, the button works and the Xpage and all editable fields save properly.
What am I missing? I have done almost exactly the same thing before but instead of using the xe:dialogButtonBar I used a string of buttons. I wanted to use the xe:dialogButton Bar to organize the UI.
Can some one explain why that would occur?
The problem is about the form submission. When you launch the dialog, editable fields on the other parts of the page are not submitted (dialog is launched upon partial refresh). Therefore the back-end component tree is not aware of the field updates of the client-side.
You can either open the dialog from the SSJS (so it submits the page) or create a "noupdate" submission with onComplete script to launch the dialog.
<xp:link
escape="true"
text="Open Dialog with SSJS"
id="link1">
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="norefresh"
action="#{javascript:getComponent('dialogSaveAsDraft').show()}">
</xp:eventHandler>
</xp:link>
<xp:link
escape="true"
text="Open Dialog with onComplete"
id="link2">
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="norefresh"
onComplete="XSP.openDialog('#{id:dialogSaveAsDraft}');">
</xp:eventHandler>
</xp:link>
If you use ComputeWithForm then you have to have a DisplayErrors control. That is where validation error messages will appear. Do you have that? If not you could be getting a validation error from the formulas on the form and they have no place to display the error messages. By the way, using ComputeWithForm is not really a good thing to do. You should repeat your validation logic directly on the XPage. Otherwise, you got too many things going on, the validation/translation that happens at the XPage level and again at the form level.
My button code :
<xp:button value="Raport" id="button1" styleClass="lotusFormButton"
style="float:right;">
<xp:eventHandler event="onclick"
submit="true" refreshMode="complete" immediate="false"
save="true" id="eventHandler2">
<xp:this.action><![CDATA[#{javascript:context.redirectToPage("export_hidden.xsp");
getcomponent('exampleDialog').hide()}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
It just go to the export_hidden.xsp ( XAgent for creating an excel file ) but without closing the dialog.
I tried reverse the 2 actions, but same results.
I appreciate your time.
Add a client-side call to XSP.closeDialog('#{id:exampleDialog}') in the onComplete event of the eventHandler.
If I understand you correctly you want to send an attachment to the user but remain on the same page. and after the attachment is delivered close the dialogbox.
the problem above is that your code tries to do two things at once. both clse the dialog and deliver the attachment. That isn't possible.
I see two solutions I would try.
Remove the getcomponent('exampleDialog').hide() and execute that thru a button onclick on a second hidden button in the oncomplete event.
If that don't work, set the url to the export_hidden.xsp in an hidden iframe in your dialogbox and also do a on button click on a hidden button the closes the dialogbox
Doing the CSJS with partial update on the dialog box, along with context.redirectToPage(xAgentName) will work, Domino 9.0.1 FP9.
I'm having an issue with some server side validation and I can't tell if this is the expected behavior in XPages or if I'm missing something simple here.
I have a field that has a computed validation formula - basically, it becomes required when a viewScope variable gets set.
My submit button sets the viewScope and does a full refresh.
I would expect the form to be submitted, the validation formula gets evaluated, and if it fails the validation failure would be displayed. But when I click my submit button the form is submitted without error. If I click it again, validation fails as expected.
To illustrate my issue I created a simple example:
<xp:inputText id="inputText1" required="#{javascript:viewScope.validate}">
<xp:this.validators>
<xp:validateRequired message="This field is required."></xp:validateRequired>
</xp:this.validators>
</xp:inputText>
<xp:button value="Submit" id="button1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete" immediate="false" save="true">
<xp:this.action><![CDATA[#{javascript:viewScope.validate=true;}]]></xp:this.action>
<xp:this.script><![CDATA[dojo.attr(dojo.byId("#{id:inputText1}"),"aria-required","true")]]></xp:this.script>
</xp:eventHandler>
</xp:button>
<xp:br></xp:br>
<xp:message id="message1" for="inputText1"></xp:message>
As you can see, I also tried adding the aria-required attribute with csjs within the button in the hopes it would initiate validation.
If validation is working as expected are there any suggestions for getting dynamic validation like this to function properly? I know I can do something with querySave on the data source (I excluded a data source from the example for simplicity) but was hoping there is a simpler solution than that.
It looks like the problem is misunderstanding the lifecycle. You're specifying whether the field is required in a viewScope variable. When the page is first loaded, the viewScope is false, so the field is not required. After you submit, the viewScope variable is set, the page rendered again. Only now does the field become required, but it is only required the next time the form is submitted.
If you want the field to be required, you'll need the required property to be evaluated to true and passed to the browser before the form is submitted.
There are a number of alternatives for the functionality you're trying to manage, running SSJS and failing if certain criteria are met.
One is to use the validator property rather than calculating the required property. The validator allows you to run code but you will need to use this.getSubmittedValue() to check the field's value - the validator runs earlier in the lifecycle before the submittedValue is passed to the value property.
The second option is to put the validation in the Submit button. You can use facesContext.addMessage(). If you google xpages facesContext addMessage there are plenty of examples of how to do it. Then do "return false" to abort.
It looks like you might want conditional validation. I wrote a blogpost about this a while back:
Making validation behave properly
I have the following LINK control on the form and would like to call the managed bean method onclick and do partial refresh (refreshing specifing part of the page). But I just found out, that this doesnt work, I can see that clicking on link sends XHR request to server, but the managed bean method call (entire onClick SSJS event) is not triggered. If I redesign thi as button controll, thigs are working properly, but I need link in this case. Is it some bug or my misuse of concept?
<xp:link escape="true" text="" id="link2" >
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" disableValidators="true" refreshId="create_recipe_form_panel">
<xp:this.action><![CDATA[#{javascript:F.getRecipe().adjustWt()}]]></xp:this.action>
</xp:eventHandler>
</xp:link>
I would say: misuse of concept. A links should "send you somewhere else" while a button "does something for you". So most likely the link destination and the click action get in each others way. Use a button and give it a class. Play with the css until you have the visual you desire.