Non rendered field bound to managed bean not firing setter - xpages

I suspect this is a silly question, but here goes...
I have two fields on a custom control, both are bound to managed bean properties (as opposed to document fields). The second field is only rendered when a specific value is chosen in the first field.
What I am seeing is that the setter for the second field is not firing after it has been rendered (the getter is firing just fine).
I have worked around the problem by computing the CSS display property on the second field to be block or none depending on the value in the first field. Everything works fine in this situation, it seems to be specifically related to whether the second field is rendered when the page is first loaded.
***Edit
Here's the sample code block:
<div class="control-group">
<xp:label value="Party Type:" id="partytypelabel" for="party_typetv">
</xp:label>
<div class="controls">
<xp:comboBox id="party_typetv" value="#{InvolvedRecord.partytypetv}"
required="true" defaultValue=""
readonly="#{javascript:!InvolvedManager.isInEditMode()}">
<xp:selectItem itemLabel="<select>" itemValue="">
</xp:selectItem>
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:InvolvedManager.getPartyTypes()}]]></xp:this.value>
</xp:selectItems>
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" disableValidators="true" refreshId="partyfields">
</xp:eventHandler>
</xp:comboBox>
</div>
</div>
<xp:panel id="partyfields" tagName="fieldset">
<xp:this.rendered><![CDATA[#{javascript:InvolvedManager.hasPartyType()}]]></xp:this.rendered>
<xp:div styleClass="control-group">
<xp:label for="Adverse_Party_TypeTL" value="Type:" id="adversepartytypelabel">
</xp:label>
<div class="controls">
<span>
<xp:comboBox id="Adverse_Party_TypeTL"
value="#{InvolvedRecord.adversepartytypetl}" readonly="#{javascript:!InvolvedManager.isInEditMode()}">
<xp:selectItem itemLabel="<select>"
itemValue="">
</xp:selectItem>
<xp:selectItem itemLabel="Company" itemValue="Company">
</xp:selectItem>
<xp:selectItem itemLabel="Individual" itemValue="Individual">
</xp:selectItem>
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" disableValidators="true" refreshId="adversepartyfields">
</xp:eventHandler>
</xp:comboBox>
</span>
</div>
</xp:div>
</xp:panel>
***End Edit
This is running on an 8.5.3 server.
Has anyone seen anything like this or maybe offer an explanation as I am confused!

You could render the component in all phases except the renderphase. This would allow to set the value during update phase, but would hide it to the client.
Here is an example:
Conditionally hidden edit box in a partially refreshed panel
EDIT:
<xp:this.rendered>
<![CDATA[#{javascript:
if( view.isRenderingPhase() ){
return InvolvedManager.hasPartyType();
}else{
return true;
}
}]]>
</xp:this.rendered>

Are you actually entering data into these fields after they have been rendered? I have found on many occasions that a field specifically bound to a managed bean does not actually even do anything unless some data has been entered into it. For instance, I have seen this: render the field dynamically, don't do anything to it, save the data source, no field whatsoever on the document. If I do that same activity but add data to the field, then it all works. Not an answer. Just some info.

Related

Are xp:dataContext variables read-only?

From examples I've seen in the Mastering XPages book and around the web, an xp:dataContext variable should be writable but I can't get it to work.
Below is a simplified version of my code. A button calls an xe:dialog containing a panel with a dataContext variable attended and initial value of "", expecting to be able to write to it from the radioGroup data binding. When the radio is set to a certain value (in this case, != "Yes") I want to unhide a div but it doesn't work. The div does not appear and the txt1 computed text field never changes to reflect the value of the radio.
I have tried both an onclick and onchange event handler but neither seems effective. Are dataContext variables read-only?
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xe="http://www.ibm.com/xsp/coreex">
<xp:button id="btn" value="Button">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial">
<xp:this.action><![CDATA[#{javascript:getComponent('dlg').show()}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xe:dialog id="dlg" title="Dialog">
<xp:panel id="panel1" readonly="false">
<xp:this.dataContexts>
<xp:dataContext var="attended" value="" />
</xp:this.dataContexts>
<xp:radioGroup id="activityAttended" value="#{attended}">
<xp:selectItem itemLabel="Yes" />
<xp:selectItem itemLabel="No" />
<xp:selectItem itemLabel="Maybe" />
<xp:eventHandler id="event1" event="onclick" submit="true"
refreshMode="partial" refreshId="target" />
</xp:radioGroup>
<xp:div id="target">
radio: <xp:text id="txt1" value="#{attended}" />
<xp:div id="div1" rendered="#{attended != 'Yes'}">
<xp:text id="txt2" value="#{attended}" />
</xp:div>
</xp:div>
</xp:panel>
</xe:dialog>
</xp:view>
To my knowledge, you can't assign to the variable name for a dataContext. What you could do would be to make the value bound to something that contains another value, like a Map or custom object, and then alter properties on that.
For example, if you made it like var="contextProps" value="${javascript:new java.util.HashMap()}", you could then do things like #{contextProps.attended != 'Yes'} and value="#{contextProps.attended}". Usually, you'll want a more-fleshed-out object than a generic HashMap for this, but it can serve as an example or a useful container in a pinch.

Xpages: Hide/Show div based on radio button values

I am binding all of my components to a java source. One field is a radio button, and if the user selects "Other" as a value, then I must show an field labeled "Other" for the user to fill in.
I cannot use SJSS to get the value of the radio button as it doesn't exist yet. But then how do I found out what the user selected? In the change event should I set a viewScope var and refresh the secondary area and check for the value of the viewScope var?
<xc:cc_CommonFormField
id="cc_CommonFormField14"
label="Savings"
placeholder="">
<xp:this.facets>
<xp:radioGroup
xp:key="field"
id="radioGroup1"
value="#{doc.prjSav}">
<xp:selectItem
itemLabel="Financial"
itemValue="Financial">
</xp:selectItem>
<xp:selectItem
itemLabel="Safety"
itemValue="Safety">
</xp:selectItem>
<xp:eventHandler
event="onchange"
submit="true"
refreshMode="partial" refreshId="refresh1">
</xp:eventHandler>
</xp:radioGroup>
</xp:this.facets>
<div id = "refresh1">
<div id = "innerRefresh"
rendered="#{javascript:what to put here}">
</xc:cc_CommonFormField>
<xc:cc_CommonFormField placeholder="Enter Other Reason...">
<xp:this.facets>
<xp:inputText
id="inputText3"
xp:key="field"
value="#{doc.prjOther}">
</xp:inputText>
</xp:this.facets>
</xc:cc_CommonFormField>
</div>
</div>
Here is the code that is correct:
<xc:cc_CommonFormField
id="cc_CommonFormField14"
label="Savings and/or Revenue From the Project"
placeholder="">
<xp:this.facets>
<xp:radioGroup
xp:key="field"
id="radioGroup1"
value="#{doc.prjSav}">
<xp:selectItem
itemLabel="Financial"
itemValue="Financial">
</xp:selectItem>
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="norefresh">
<xp:this.script><![CDATA[var result=null;
for(var i=0; i<document.forms[0].elements.length; i++){
if(document.forms[0].elements[i].name=="#{id:radioGroup1}" ){
if(document.forms[0].elements[i].checked == true){
result=document.forms[0].elements[i].value;
break; //remove this if for check box groups and collect multiple values above instead
}}}
var sel = x$("#{id:innerRefresh}");
if (result == "Other")
{
x$("#{id:innerRefresh}").removeClass("scoHidden");
x$("#{id:innerRefresh}").addClass("scoVisible");
}
else
{
x$("#{id:innerRefresh}").removeClass("scoVisible")
x$("#{id:innerRefresh}").addClass("scoHidden");
}
XSP.partialRefreshGet("#{id:innerRefresh}")]]></xp:this.script>
</xp:eventHandler></xp:radioGroup>
</xp:this.facets>
</xc:cc_CommonFormField>
<div id="refresh1">
<xp:div id="innerRefresh" styleClass="scoHidden">
<xc:cc_CommonFormField placeholder="Enter Other Reason...">
<xp:this.facets>
<xp:inputText
id="inputText3"
xp:key="field"
value="#{doc.prjOther}">
</xp:inputText>
</xp:this.facets>
</xc:cc_CommonFormField>
There are 2 approaches to solve this:
- server side rendering using SSJS
- client side rendering using JS
When you opt for the former, you have to submit your data (partial including the hidden div) to recompute your rendered property.
Client side: you render the div in any case, but give it a class attribute that maps to CSS display:none.
In your client side JS you add an onChange handler to the radio buttons and change the class to something visible (and back if others are unselected). This saves you from a server round trip.
Only caveat: (best handled in your Java) you need to dismiss an eventually entered value in the field for other if other wasn't selected.

My dialog control does not update my xpage

I try to update items via a dialog control.
But my control OK button (or any other function in the dialog) do not refresh my "underlying" xpage.
I^m sure it's sth quite simple ....
the (symplified example) code of the dialog:
<xe:dialog id="diaSnippet" title="Update my xpage" extractContent="true"
preload="true">
<xe:dialogContent id="dialogContent1">
<xp:panel>
<xp:inputText value="#{test.dialog1}" id="inputText1">
<xp:this.defaultValue><![CDATA[#{javascript:test.getItemValueString("item1")}]]></xp:this.defaultValue>
</xp:inputText>
</xp:panel>
</xe:dialogContent>
<xe:dialogButtonBar id="dialogButtonBar1">
<xp:panel>
<xp:button id="button3" value="OK">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:test.replaceItemValue("item1","1234")
getComponent("diaSnippet").hide()}]]></xp:this.action>
</xp:eventHandler></xp:button>
</xp:panel>
</xe:dialogButtonBar>
</xe:dialog>
in my understanding the Ok should update the xpage, and should change the value of the item "item1", but it does nothing.
thx in advance for any help, Uwe
argh .... now I found the answer in the wiki:
http://www-10.lotus.com/ldd/ddwiki.nsf/xpDocViewer.xsp?lookupName=Domino+Designer+XPages+Extension+Library#action=openDocument&res_title=Modal_dialogs_ddxl853&content=pdcontent
The settings in the "Server Options" on the event tab seem to do nothing, but writing the ID(s) to be refreshed in the hide() method does the trick.
So instead of getComponent("diaSnippet").hide() I write getComponent("diaSnippet").hide("IDtorefresh)
Uwe

Computed display format of date control based on comboBox selection

I am trying to change the display format of a date/time control based on a combo box selection. I thought it would be simple to do.
I am using a js if statement with getComponent instead of datasource.getValue as I thought it would grab the value before it is submitted. I receive an error that the component is null.
Can anyone explain why I am getting null here but in a computedField with getcomponent the value shows?
if (getComponent('comboBox1').getValue()==0)
{'both'}
else
{'date'}
The type of the converter is computed during page load, and during this it is not possible to access a component with getComponent method. Additionally, it is not possible to recompute the type of the converter this way. Event if you use the page load/dynamically trick, the type of the converter will not recomputed.
But you can change the type of the converter in the partial refresh:
<xp:comboBox id="comboBox1">
<xp:selectItem itemLabel="One" itemValue="1"></xp:selectItem>
<xp:selectItem itemLabel="Null" itemValue="0"></xp:selectItem>
<xp:eventHandler event="onchange" submit="true" refreshMode="partial" refreshId="inputText1">
<xp:this.action><![CDATA[#{javascript:
var cmp:com.ibm.xsp.component.xp.XspInputText = getComponent("inputText1");
var converter:com.ibm.xsp.convert.DateTimeConverter = cmp.getConverter();
var value = getComponent("comboBox1").getValue();
if( value == 0) {
converter.setType("both");
}else{
converter.setType("date");
}
}]]>
</xp:this.action>
</xp:eventHandler>
</xp:comboBox>
In this example, the datefield is inputText1 and looks like this:
<xp:inputText id="inputText1">
<xp:this.converter>
<xp:convertDateTime type="time" />
</xp:this.converter>
<xp:dateTimeHelper />
</xp:inputText>

Partial refresh on dynamic field binding removes values

Really looking for an idea why my XPage is doing this.
I have field with a dynamic databinding:
<xp:inputText id="CORE_Input" value="#{Document[compositeData.PARA_DataBinding]}"</xp:inputText>
That works quit well until I start to hide it based on a notes formula.
Let me tell what it does: I click a checkbox in my XPage. That checkbox is running SSJS which is calling: Document.getDocument(true) to push the data from my XPage back into the notesdocument without saving it. Once that is done I can use session.evaluate("checkbox!="something"") to hide the inputText field.
It works quit well but the problem is that once I untick the checkbox the value is gone from the inputfield.
If you know a better way to use notes formulas for hiding or the reason why the inputfield is empty once it comes back would be highly appreciated. Here is an example:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xe="http://www.ibm.com/xsp/coreex">
<xp:checkBox id="checkBox1" value="#{Document.Check}" text="hide" checkedValue="hide">
<xp:eventHandler event="onchange" submit="false">
<xp:this.script><![CDATA[document.getElementById("#{id:hide}").click()]]></xp:this.script>
</xp:eventHandler>
</xp:checkBox>
<xp:panel id="test">
<xp:inputText id="CORE_Input" type="#{compositeData.NODE}"
value="#{Document[compositeData.PARA_DataBinding]}"
defaultValue="#{javascript:compositeData.PARA_DefaultValue}" style="margin-left:24px">
<xp:this.styleClass><![CDATA[#{javascript:DOMElement.getAttribute("stylesize");}]]></xp:this.styleClass> <xp:this.rendered><![CDATA[#{javascript:var doc:NotesXspDocument=Document;
var erg=session.evaluate('Check="hide"',doc.getDocument());
if(#Text(erg)=="1")
{return false}
else
{return true}}]]></xp:this.rendered>
</xp:inputText>
<xp:button value="hide" id="hide">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="test">
<xp:this.action>
<![CDATA[#{javascript:var doc:NotesXspDocument=Document;doc.getDocument(true)}]]></xp:this.action>
</xp:eventHandler></xp:button>
<xp:button value="unhide" id="unhide">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="test">
<xp:this.action><![CDATA[#{javascript:sessionScope.hide=""}]]></xp:this.action>
</xp:eventHandler></xp:button>
</xp:panel></xp:view>
The problem you have is your default value: As soon the component is unhidden, the value is recalculated. You have to check if the component is partially refreshed. If so, stop the recalculation:
<xp:this.defaultValue>
<![CDATA[#{javascript:
importPackage( com.ibm.xsp.ajax );
if( AjaxUtil.isAjaxPartialRefresh(facesContext) == true )
return;
compositeData.PARA_DefaultValue
}]]>
</xp:this.defaultValue>
This should solve your problem

Resources