On an xpage I have a combobox where the default value is set via expression language:
defaultValue="#{strings.field_mandate}"
this populates the correct value.
if I compute the Disabled property of the combobox and compute the value of the combobox in a computed text control via:
getComponent("mandate").getValue()
I get a strange behaviour.
Initially the combobox is Disabled and the computed value is correct (value from the strings.properties file). However if I switch the value of the Disabled to false the computed text value becomes literally #{strings.field_mandate}.
Why is this and how can I avoid this?
<xp:comboBox id="mandate" value="#{ds.mandate}" defaultValue="#{strings.field_mandate}">
<xp:selectItem itemLabel="#{strings.field_mandate}" itemValue="null"/>
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:getListMandates();}]]></xp:this.value>
</xp:selectItems>
<xp:eventHandler event="onchange" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:setSelectedMandateValues();}]]></xp:this.action>
</xp:eventHandler>
</xp:comboBox>
Try to avoid getComponent().getValue(). Computation should always happen to the value the component is bound to. So bind it to a scoped variable and set that one to your initial value. That should mitigate the issue
Related
On my XPages form I have a checkbox control:
<xp:checkBox
id="cbPromo"
value="#{employeeBean.employee.promoCheck}"
valueChangeListener="#{employeeBean.onPromotChange}"
checkedValue="true"
uncheckedValue="false"
disabled="#{!employeeBean.employee.editable}">
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="partial"
refreshId="pnlUpdate"
execMode="partial" />
</xp:checkBox>
</xp:panel>
The problem is when I change the edit mode for the employee object (default is editable = false) the checkbox control which was in read mode checked becomes unchecked.
When I add a computed text control to see what the value for the promoCheck field its is both in read and edit mode true:
<xp:text escape="true" id="computedField1"
value="#{employeeBean.employee.promoCheck}">
</xp:text>
Can someone explain me what I should do to keep the checkbox control checked when I switch the editable mode for my employee object?
don't use the disabled property, but the readonly property instead
I'm trying to set a value to a field ( which is not inside the repeat control ) from a field which is on the repeat control.
The field from the repeat:
<xp:inputText id="inputText2" disabled="true">
<xp:this.value><![CDATA[#{viewScope.field_2[index]}]]></xp:this.value>
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="sus">
<xp:this.action><![CDATA[#{javascript:getComponent("inputText4").setValue("1234");}]]></xp:this.action>
</xp:eventHandler>
</xp:inputText>
And the target field , as you can notice, is inside a panel, id="sus".
Also the target field is binded to a form field.
but no value is assigned. How can I achieve this?
Components are only visualizations of a data model behind. Always bind your controls and go after the model value, never the component. A disabled inputText can't fire a value and in the code snippet above you have disabled="true". The onchange event can't fire.
This would work:
<xp:inputText id="inputText2" disabled="false">
<xp:this.value><![CDATA[#{viewScope.field_2[index]}]]></xp:this.value>
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="sus">
<xp:this.action><![CDATA[#{javascript:viewScope.someValue=42;}]]></xp:this.action>
</xp:eventHandler>
</xp:inputText>
Your target control would look like this:
<xp:inputText id="inputText4" value="#{viewScope.someValue}">
</xp:inputText>
If your target control is bound to something else (e.g. #{document1.test}), they your code needs to update that one. (document1.replaceItemValue("test",42))
Again 3 important aspects:
Never go after UI elements, always update the bound model behind (a.k.a: Talk to the data, not the UI also known as: The Controller updates the MODEL, not the view)
Make sure your target is part of the refreshed fields
Disabled fields don't fire events
Let us know how it goes
I'm using a <xe:djTabContainer> with 10 <xe:djTabPane> containing numerous fields components.
There is a principal combobox whose value will determine which fields to be showed or not and in this way the document structure will be achieved.
If I will use this approach, then for all my >50 fields which I want to show/hide, I will use only the onChange event of the combobox?
Considering the fact that there are >50 fields which enter in this category < showing&hiding them >, should I use another approach / method? Thanks for your time.
<xp:comboBox value="#{Contr.txt_tipcontractcv}" id="comboBox4"> <xp:selectItems id="selectItems1">
<xp:this.value><![CDATA[#{javascript:return ""}]]></xp:this.value>
</xp:selectItems>
<xp:selectItems id="selectItems2">
<xp:this.value><![CDATA[#{javascript:#DbColumn(#DbName(),"SetupvwTipuriContracteC",1);}]]> </xp:this.value>
</xp:selectItems>
<xp:eventHandler event="onchange" submit="false"> <xp:this.script><![CDATA[XSP.partialRefreshPost("#{id:FisaP}", {
});
]]></xp:this.script> </xp:eventHandler> </xp:comboBox>
and the panel:
<xp:panel id="FisaP">
<xp:label id="label4"
style="color:rgb(128,0,0);font-family:verdana;font-size:9pt;font-weight:bold">
<xp:this.value><![CDATA[#{javascript:"Fisa contract "+ Contr.getItemValueString("txt_tipcontractcv")}]]></xp:this.value>
<xp:this.rendered><![CDATA[#{javascript:
Contr.getItemValueString("txt_tipcontractcv") != ""
}]]></xp:this.rendered>
</xp:label>
</xp:panel>
I would turn it around. Let the labels and fields ask the combobox if they should be rendered or not. Let the combobox's onchange event initiate a partial refresh of a panel which includes all fields you want to show/hide.
If your >50 fields are all on one place you can frame them with a panel and set the rendered property there.
If your combobox is bound to a viewScope variable the rendered property of fields/labels would be
rendered="#{javascript:viewScope.tipcontractcv1 == 'Vanzare-Cumparare'}"
or if it is bound to a document field then
rendered="#{javascript:document1.getItemValueString('txt_tipcontractcv1') === 'Vanzare-Cumparare'}"
Update:
Based on your code in your answer https://stackoverflow.com/a/25636661/2065611 take the following steps so get it to work with the Dojo Tab Container:
1.
Put the labels and fields in panels which do have an id but don't have a rendered attribute
<xp:panel id="panel1">
<xp:label value="Persoane spre informare" ... id="label2">
<xp:this.rendered><![CDATA[#{javascript:
Contr.getItemValueString("txt_tipcontractcv1") == "Vanzare-Cumparare"
}]]></xp:this.rendered>
</xp:label>
... other label and fields ...
</xp:panel>
You can create other panels "panel2", "panel3", ... too. They can be placed in different djTabPanes.
2.
Change the onchange event of your combobox and execute client side code to refresh the panels
<xp:eventHandler
event="onchange"
submit="false">
<xp:this.script><![CDATA[
XSP.partialRefreshPost("#{id:panel1}", {
onComplete: function() {
XSP.partialRefreshPost("#{id:panel2}");
}
});
]]></xp:this.script>
</xp:eventHandler>
3.
You can optimize your code if you put labels and fields with the same rendered attribute together into an additional panel
<xp:panel id="panel1">
<xp:panel id="panelRendered1"
<xp:this.rendered><![CDATA[#{javascript:
Contr.getItemValueString("txt_tipcontractcv1") == "Vanzare-Cumparare"
}]]></xp:this.rendered>
<xp:label value="Persoane spre informare" ... id="label2" />
... other label and fields ...
</xp:panel>
</xp:panel>
First... never do this:
if (comboVal == "Vanzare-Cumparare")
Even though it's called "SSJS".. it's really not "JavaScript"... you're pretty much working with Java. In Java everything is an object. Even a literal string. So by entering "Vanzare-Cumparare" you're pretty much creating a new Object. You can see this in the typeahead of the SSJS editor. Try typing "anything". <-- Note you NEED to type in that period.
The way to do that if statement is:
if ("Vanzare-Cumparare".equalsIgnoreCase(comboVal)
you could reverse it I think:
if (comboVal.equalsIgnoreCase("Vanzare-Cumparare")
Should give you the same result. I think sometimes you can get away with using the == but mostly likely it's going to bite you at some point no matter what. So I recommend never doing that.
I'm not sure I'm following your approach here. I guess it makes some sense but if it were me I'd do it differently. I know that personally I've NEVER tried to grab the component in SSJS like this: var combo:javax.faces.component.UIComponent - I've never seen the need.
I'd prefer to use a scoped variable and then in the label's rendering property grab that scoped variable and use that to determine your rendering value - true or false.
I see a real problem. If the component is not currently rendered, you cannot get a handle to it with getComponent. If you simply change the display value, then the component is always there, even if it's not displayed.
Something like this:
var combo:javax.faces.component.UIComponent = getComponent("txt_tipcontractcv1");
var comboVal = combo.getValue();
if (comboVal.equalsIgnoreCase("Vanzare-Cumparare")) {
document.getElementById("#{id:label2}").style.display = "block"; // or "inline"
} else {
document.getElementById("#{id:label2}").style.display = "none";
}
You need to ensure that the label2 element is always rendered, so that the style indicates whether it is visible.
I have 2 edit Boxes, 1 is editable, the other just prints the name of the sessionScope, both fields are in a in 2 cells next to each other , see code below, inputText1 is a editable text field, inputText2 is non editable text, printing #{sessionScope.Tmp1_ABC}
<xp:td>
<xp:inputText id="inputText1"
loaded="true">
<xp:this.value><![CDATA[${javascript:var fieldName = "Tmp_" + #ReplaceSubstring(varcollection," ","");
return '#{sessionScope.' + #ReplaceSubstring(fieldName,#List(" ",")","("),"") + '}';}]]></xp:this.value>
<xp:eventHandler
event="onchange" submit="true" refreshMode="partial"
refreshId="panel_1" />
</xp:inputText>
</xp:td>
<xp:td>
<xp:inputText id="inputText2"
loaded="true">
<xp:this.value><![CDATA[#{javascript:var fieldName = "Tmp1_" + #ReplaceSubstring(varcollection," ","");
return '#{sessionScope.' + #ReplaceSubstring(fieldName,#List(" ",")","("),"") + '}';}]]></xp:this.value>
<xp:eventHandler
event="onchange" submit="true" refreshMode="partial"
refreshId="panel_1" />
</xp:inputText>
</xp:td>
AFAIK you can't assemble your data binding that way. Data binding is an EL expression, not SSJS. You could try to trick using ${} to compute #{}
As per Stefan, using SSJS (javascript:) to define a value for an input control results in it only being read-only. For values to be editable they must be bound using Expression Language (EL). For something as complex as the example (looping over a list of field/variable) you will most likely have to learn a little Java to allow you to connect your input controls to the bean via EL. If the purpose of the code is to have one field editable and the other read-only you should (as Per suggested) change the control from being an inputText to just (computed) text or a label and remove the event handler. Somebody reading the code could easily be confused in thinking you intended both to be editable.
I'm going crazy: I cannot access the selected value of a combobox in the onchange event:
<xp:comboBox id="comboBox1" value="#{sessionScope.groupBy}">
<xp:selectItem itemLabel="nothing" itemValue=""></xp:selectItem>
<xp:selectItem itemLabel="State" itemValue="state"></xp:selectItem>
<xp:selectItem itemLabel="CCType" itemValue="cctype"></xp:selectItem>
<xp:eventHandler event="onchange" submit="true" refreshMode="complete">
<xp:this.action>
<xp:executeScript>
<xp:this.script>
<![CDATA[
#{javascript:sessionScope.groupBy = getComponent("comboBox1").getValue();
print( getComponent("comboBox1").getValue() )}
]]>
</xp:this.script>
</xp:executeScript>
</xp:this.action>
</xp:eventHandler>
</xp:comboBox>
I want to store the value and reload the page to access the value I just submitted. I also tried getSubmittedValue() and value only. They always return null.
What is the trick here?
I have a problem similar to that one but if I understand your quandary I may have a solution. You are trying to capture the value of a combo box field that you select correct? Here is the code for the combo box (name: POVendor). The view I'm drawing the list from is named "PLBV".
#DbColumn(#DbName(), "PLBV", 1)
Here is the code for the Computed field that captures the value of the selection in the combo box. Just do a partial refresh on the computed field from the combo box & it should work fine.
var item = document1.getValue("POVendor");
return item;
I was facing the similar issue, tried the below option and it worked for me.
Set the Server Options on the onChange event of the combobox to Full Update and check the option "Process Data without validation
This will give you the desired result.(Your sessionScope.groupBy will be set to the new selected value of the combobox.