I have a combo box on my XPage with showReadonlyAsDisabled marked true:
<xp:comboBox
id="ComboTest"
defaultValue="One"
showReadonlyAsDisabled="true"
readonly="true">
<xp:selectItem
itemLabel="One"
itemValue="One">
</xp:selectItem>
</xp:comboBox>
However, the combo box still displays as read-only (text) and not as the disabled control. Is this a bug? The showReadonlyAsDisabled property appears to work on other controls (input, radio, etc.). I'm using Designer 9.0.1FP4 and the Domino server is on 9.0.1FP5.
EDIT (showing combo box with data binding):
Comobo box in custom control
<xp:comboBox
id="Address"
value="#{Location.AddressType}"
defaultValue="Street Address"
showReadonlyAsDisabled="true"
readonly="true">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:keywords.getSelectItem("Address Type", true);}]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
Data binding on parent XPage
<xp:dominoDocument
var="Location"
formName="Location"
action="editDocument"
documentId="#{javascript:param.location}">
</xp:dominoDocument>
Seems to be a problem with all kinds of selection controls that are rendered as html tables in read mode (which in my opinion is even more annoying than just this "show disabled in read mode" bug as it makes styling unnecessarily complicated). This however is only happening if the control is bound to a document datasource.
So what you can try is create a second combo box on you page and bind it to a viewScope variable, then make sure the correct value is copied over from the Notes field upon page load, then make sure only one insstance of tyour control is visible in read / edit mode:
For a datasource named Location, and a Notes field AddressType this would be in beforePageLoad:
if(!doc1.isNewNote()){
viewScope.comboField=Location.getItemValueString("AddressType");
}
This would be the markup for your original / editable comboBox control:
<xp:comboBox id="comboBox1" value="#{Location.AddressType}" rendered="#{javascript:doc1.isEditable()}" defaultValue="Street Address">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:keywords.getSelectItem("Address Type", true);}]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
This would be the markup for your additional / disabled comboBox control:
<xp:comboBox id="comboBox2" value="#{viewScope.AddressType}" disabled="true" rendered="#{javascript:!doc1.isEditable()}">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:keywords.getSelectItem("Address Type", true);}]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
You can add the following XML part to the faces-config.xml of your application.
With this, the renderer for the ComboBox will be set to the default, not read-only renderer. Then, your ComboBox should appear as you want.
<renderer>
<component-family>javax.faces.SelectOne</component-family>
<renderer-type>javax.faces.Menu.ReadOnly</renderer-type>
<renderer-class>com.ibm.xsp.renderkit.html_basic.MenuRenderer</renderer-class>
</renderer>
Related
is it possible to call a Dialog component in typeAhead functionality?
What i want to do is If the user enter a word which does not come up with typeAhead function then a dialog should appear on the screen.
Please find my code below (my dialog is in custom control)
Regards
Cumhur Ata
<?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">
<xe:dialog id="dialogConfirmation">
<div class="modal-body">
<p>You have entered a word which is not in the list</p>
<p class="text-warning">Please add/or cancel<small> </small></p>
</div>
<xe:dialogButtonBar id="dialogButtonBar1">
<xp:button value="Hayır" id="btnConfirmYes">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script><![CDATA[XSP.closeDialog('#{id:dialogConfirmation}')]]></xp:this.script>
</xp:eventHandler></xp:button>
<xp:button value="Evet" id="btnConfirmNo" styleClass="btn-primary">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:openNewFrm(sessionScope.extDbPath,sessionScope.expDbPage)}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
</xe:dialogButtonBar>
<xe:this.title><![CDATA[#{javascript:var c = "Warning";return c;}]]></xe:this.title></xe:dialog></xp:view>
You can hijack the result of the typeahead and call your dialog if it's empty by using this snippet:
https://openntf.org/XSnippets.nsf/snippet.xsp?id=typeahead-onstartoncomplete-event
I don't have Domino Designer at hand right now so I can't try this out. So this is just guessing:
I don't think that you can use the standard Edit Box control's type ahead feature for something like that; instead you could program this yourself using the control's "onkeyup" event, mimicking the standard type ahead. the idea is that a classic type-ahead operates as a filter to a list of possible entries, just like a "getElementsByKey" method that is fired upon each key stroke. So with every event you check what's in the Edit Box so far, compare it to your list, then display the filtered result to the user in a pop-up (you may want to use a dojo tooltip here).
If the result is null you can bring up your dialog instead.
I have been given an XPages project which I did not develop. The project has a OneUILayout that includes a Search Bar "facet". Is it possible to code a filter into the search bar facet so that retrieved records are omitted that have a field with a certain value. I have very little experience with XPages. The search results are output to a OneUI_searchpage.xsp where an edit box displays the search string then a dynamic View Panel shown the retrieved records. I have attached the source code for these two items below. Thank you
<xp:label value="Search String:" id="label1"></xp:label>
<xp:inputText id="inputText1" value="#{param.search}"></xp:inputText>
<xp:panel id="maincontentpanel">
<xe:dynamicViewPanel rows="30" id="dynamicViewPanel1"
width="100%">
<xe:this.data>
<xp:dominoView viewName="ContractsFlatByYear"
var="view">
<xp:this.search><![CDATA[#{javascript:return
param.search;}]]></xp:this.search>
</xp:dominoView>
</xe:this.data>
</xe:dynamicViewPanel>
After some consultation with stwissel below, I amended the application to have a check box on the search results xpage with it checked by default and created an additional view for the same output. One view to show cancelled contracts and one to omit cancelled contracts. The relevant Xpage section now looks like as follows;
<xp:checkBox text="Omit Cancelled Contracts"
id="OmitCancelled" defaultChecked="true" checkedValue="True"
uncheckedValue="False" style="padding-left:5.0em" value="#
{viewScope.viewSel}">
<xp:eventHandler event="onchange" submit="true" refreshMode="partial"
refreshId="dynamicViewPanel1"></xp:eventHandler>
</xp:checkBox>
<xp:panel id="maincontentpanel">
<xe:dynamicViewPanel rows="30" id="dynamicViewPanel1"
width="100%" partialRefresh="true">
<xe:this.data>
<xp:dominoView var="view">
<xp:this.viewName>
<![CDATA[#{javascript:var cancelledYesNo = viewScope.viewSel
= getComponent("OmitCancelled").getValue();
if(cancelledYesNo == "True"){
viewName = "ContractsFlatByYear"}
else {
viewName = "ContractsFlatByYearandCancelled"}}]]>
</xp:this.viewName>
<xp:this.search><![CDATA[#{javascript:return param.search;}]]
></xp:this.search>
</xp:dominoView>
</xe:this.data>
</xe:dynamicViewPanel>
This appears to work but I have the check box onChange event to apply a partial refresh on the dynamicviewpanel but only refreshes when I click on the dynamicviewpanel itself
The search bar facet only captures what you want to search and sends it to the specified XPages for processing.
You have 2 options:
Alter the facet to send the additional condition to the search page
Alter the search function in the search page (the one the query gets posted to) to filter that (if it is static).
Be aware: filtering in code is not a security feature (in case you were intending that). There's reader and author fields for that.
XPages in its core is JSF with some specialities around Domino. You might want to check out my article series on them.
Update
Based on the code snippet, your can get the desired result quite fast. Edit the view selection formula and add & conContractStatus <> "cancelled". You need to check first if that view is used elsewhere to show canceled contracts too. If that is the case, copy the view (eg add Active behind the name) and make the changes there.
Update 2
Your code doesn't return a value and you don't need to get to the component
<xp:this.viewName>
<![CDATA[#{javascript:return (viewScope.viewSel=="True") ? "ContractsFlatByYear" : "ContractsFlatByYearandCancelled";}]]>
</xp:this.viewName>
Let us know how it goes
If I have an outer panel in which the readonly property is true, is there any way to created inner panels in which the content can be editable?
The use case is a mobile page with a number of fields plus multiple RoundedRectLists. I would like to add a search control to each RoundedRectList to filter the content of those lists. I do not want the fields to always be editable. I need the search control to be editable so I can enter a search value without toggling the entire form. At the moment I have readonly=false set for the inner panel but the search control only becomes editable when the readonly for the outer panel is also set to false.
I know I can created separate panel that are not nested, but this design pattern of nested panels is quite common and I am sure there is n XPages guru out there that has solved this...
I am not the XPage guru you are searching for but i have a workaround, =)
As far as i know if you set the outer panel to readonly="true" all your inner inputText boxes will output no <inputField> in your html just a <span>. Thats also very anoying if you want to have a field that looks like a input but is just disabled for input. That is achieved if you set the to disabled="true" and showReadonlyAsDisabled="true".
I would recomend setting all readonly="false" and use dojo.query to set the disabled propertie on page load like:
<xp:scriptBlock>
<xp:this.value><![CDATA[dojo.ready(function(){
dojo.query(".input").forEach(function(node, index, array){
node.disabled = true;
}
)
});]]></xp:this.value>
</xp:scriptBlock>
<xp:panel>
<xp:inputText id="inputText1" value="#{viewScope.in1}" styleClass="input"
defaultValue="Txt0" >
</xp:inputText>
<xp:inputText id="inputText2" value="#{viewScope.in2}" styleClass="input"
defaultValue="Txt1">
</xp:inputText>
<xp:inputText id="inputText3" value="#{viewScope.in3}" styleClass="input"
defaultValue="Txt2">
</xp:inputText>
</xp:panel>
Another benefit of this solution you can set them editable on clientSide without any Server calls.
Hope it helps.
I'm using the Extension Library and XPages to build a web based workflow application. One feature is to prompt a dialog and select the next approver before submitting it forward.
For new documents, the dialog appears, and it also appears when in read mode. It never opens for a saved document. I need it to work in SSJS, though the dialog does open in CSJS. Here is some of the code:
xpMain.xsp contains two custom controls: ccButtons and ccWFloDialogs.
ccButtons "Submit" button:
getComponent('dlgNextOwner').show();
ccWFloDialogs "dlgNextOwner" dialog:
<xe:dialog id="dlgNextOwner" title="Select Supervisor">
<xe:formTable id="ftDlgNextOwner" formTitle="Select Supervisor"
formDescription="You may select a different supervisor."
disableErrorSummary="true">
<xp:this.facets>
<xe:formRow id="formRow1" xp:key="footer" for="txtWFloNextOwner"
labelWidth="125px">
<xp:inputText id="txtWFloNextOwner" style="width:200px"
value="#{viewScope.nextOwner}">
</xp:inputText>
<xe:namePicker id="npNextOwner" dialogTitle="Select Supervisor"
for="txtWFloNextOwner">
<xe:this.dataProvider>
<xe:dominoNABNamePicker addressBookSel="all-public"></xe:dominoNABNamePicker>
</xe:this.dataProvider>
</xe:namePicker>
</xe:formRow>
</xp:this.facets>
</xe:formTable>
</xe:dialog>
In CSJS, I can use the following code and it successfully opens the dialog:
XSP.openDialog("#{id:dlgNextOwner}");
I'm also using Mark Hughes' picklist from the extension library, and if I remove the panel which contains the control and data source, the dialog shows up in SSJS! The code is in a custom control, although, if it's directly in the XPage, the problem is the same. Here is the code for the panel:
<xp:panel
id="vendorDiv">
<xp:this.data>
<xp:dominoView
var="nvVend"
viewName="V_Vend"
ignoreRequestParams="true"
databaseName="other/lookupdb.nsf"
startKeys="#{javascript:viewScope.srchVend}">
</xp:dominoView>
</xp:this.data>
<xe:formTable
id="ftGetVendor"
disableErrorSummary="true"
labelPosition="above">
<xe:formRow
id="frVendor"
for="cfVendorName"
label="Name of the Vendor:">
<xp:text
escape="true"
id="cfVendorName"
value="#{currentDocument.VendorName}"
style="width:200px">
</xp:text>
<xc:viewpicklist
rowsPerPage="15"
buttonImage="./add.png"
tableClass="tablecellgreen"
headerClass="headerclass"
rowClass="odd, even"
searchBar="false"
searchButtonText="Search"
searchButtonClass="button2"
searchBarClass="headerclass"
pagerStyleFirst="navbutton1"
pagerStylePrevious="navbutton2"
pagerStyleCurrent="navbutton4"
pagerStyleNext="navbutton2"
pagerStyleLast="navbutton3"
typeAheadBar="true"
select="Column"
onReturn="Set Scope Value"
bottomBarClass="bottomround headerclass"
cancelButtonText="Cancel"
cancelButtonClass="button2 floatthisright"
type="Single Value"
finishButtonText="Finish"
finishButtonClass="button2 floatthisright"
multiSelectButtonAddImg="./add.png"
multiSelectButtonRemoveImg="./delete.png"
picklistButtonClass="button"
openDialogWith="Link"
picklistLinkImg="./add.png"
multiSelectLinkAddImg="./add.png"
multiSelectLinkRemoveImg="./delete.png"
selectWith="Link"
clearSearchImg="./cross.png"
SelectCellWidth="30px"
dialogID="dlgVend"
dialogTitle="Select a Vendor"
dialogWidth="80%"
refreshID="vendorDiv"
ssjsSelectFunction="getVendorInfo"
varName="viewScope.vendorInfo"
datasrc="nvVend"
selectColumn="4"
linkImg="./add.png"
typeAheadVar="viewScope.srchVend">
<xc:this.viewColumn>
<xp:value>0</xp:value>
<xp:value>1</xp:value>
<xp:value>2</xp:value>
<xp:value>3</xp:value>
</xc:this.viewColumn>
</xc:viewpicklist>
</xe:formRow>
<xe:formRow
id="frVendorStatus"
for="cfVendorStatus"
label="Vendor Registration Status:">
<xp:text
escape="true"
id="cfVendorStatus"
value="#{currentDocument.VendorStatus}">
</xp:text>
</xe:formRow>
<xe:formRow
id="frVendorCountry"
for="cfVendorCountry"
label="Country Name:">
<xp:text
escape="true"
id="cfVendorCountry"
value="#{currentDocument.VendorCountry}">
</xp:text>
</xe:formRow>
</xe:formTable>
</xp:panel>
The requested vendor information populates the fields, without any problem or errors. However, something here seems to prevent dialogs from opening up using SSJS.
Can anyone see anything obvious I'm missing? The data source is in the panel, ignoreRequestParams is true (otherwise it doesn't work).
The main data source is in the entire XPage context. I tried to add the ccWFloDialog custom control outside the main panel, and change the data source to the panel, but that didn't work.
Any ideas?
Forget the dialog for now. This is probably data source related. Suggest you get it working just on the xpage first. With visible fields. then maybe use the rendered property to get it working on the xpage similar to how the dialog would appear. Once you have that working then you should be good to apply to dialog. This idea is to just take the dialog out of the equation first to make sure it works normally.
Instead, I decided to open the dialogs using CSJS, instead of SSJS. I've changed some of logic, and will have a bit more to do to finish this part of the project. Thanks to all!
I have two custom controls, CustomControlBody and CustomControlTitle.
CustomControlBody has a radio button. CustomControlTitle has a computed field based off of the value of the radio button in CustomControlBody.
If CustomControlTitle is placed within CustomControlBody then the computed field in CustomControlTitle can see the value of the radio button on CustomControlBody just fine.
But for flexibility of design, I want to be able to place CustomControlTitle and CustomControlBody separately on the xPage. But when I do this, CustomControlTitle does not seem to be able to see the radio button in CustomControlBody.
How can I pass the value of the radio button in CustomControlBody to the computed filed in CustomControlTitle?
You can use the viewscope to set the parameter and on refresh you can read this var. another way would be to create a custom control title and body with a facet (editable area. The you create a third control where you place these controls into and fill the facets with the radiobutton and the text field. Something like
(this is not production ready ofcourse it is just to illustrate the above..)
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xc="http://www.ibm.com/xsp/custom"
xmlns:xe="http://www.ibm.com/xsp/coreex">
<xp:this.data>
<xp:dominoDocument var="yourdocument" action="editDocument"
documentId="#{javascript:return compositeData.DocumentUniqueID;}"
computeWithForm="save" formName="yourdocument">
</xp:dominoDocument>
</xp:this.data>
<xp:panel>
<xc:Title>
<xp:textxp:key="field" value="#{javascript: rb = getComponent("radiobutton"); return cb.getValue();}"/>
</xc:Title>
<xc:Body>
<xp:radioGroup id="radioGroup1" xp:key="fields">
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="titleControl">
<xp:this.action><![CDATA[#{javascript:viewScope.value = this.getValue();}]]></xp:this.action>
</xp:eventHandler></xp:radioGroup>
</xc:Body>
</xp:panel>
</xp:view>