Use edit box value for dynamic view panel parameter - xpages

What I am trying to do is have an edit box, a button and a dynamic view panel on an Xpage and a View in the Notes database. Then input a document Id in the edit box which, when the button is clicked will use the edit box value as a parameter for filtering in the dynamic view panel. There seems to be very little on the Internet. I have tried setting the dynamic view panel's "Keys" property to the value
getComponent("inputDocumentID").getValue()
And have the button do a full refresh but this does not work. How can I use the edit box as the dynamic views parameter? The Notes View selection formula is;
SELECT ((Form = "Contract")) & (conContractStatus = "Cancelled") &
(initialstagecomplete = "1")

I usually do this using scoped variables. The idea is to use a mechanism similar to LotusScript's NotesViewEntryCollection.getEntriesByKey("keyFilter", False):
Let's assume you have a Notes view where the first column is sorted by UNID (column formula = #Text(#DocumentUniqueID)).
Inside your xpage you create your view panel as always. The vp's key property is set to listen to a requestScope variable like this:
<xp:viewPanel id="viewPanel1">
<xp:this.data>
<xp:dominoView var="view1" viewName="myView"
keys="#{javascript:requestScope.keyFilter;}">
</xp:dominoView>
</xp:this.data>
...
</xp:viewPanel>
Somewhere else on the Xpage you create an editbox and bind it to your requestScope var like this:
<xp:inputText id="inputText1" value="#{requestScope.keyFilter}">
<xp:eventHandler event="onkeyup" submit="true"
refreshMode="partial" refreshId="viewPanel1">
</xp:eventHandler>
</xp:inputText>
As you see every input is immediately stored in my scope variable, and every keyup event performs a partial refresh on the view panel thus refining the key filter as I type.
Remark:
There's a caveat in case your view panel comes with a pager: if you start filtering while your vp isn't showing page #5 applying a key filter could render an empty view. Reason is that the view still is showing page #5 but there just isn't enough data left to show on 5 pages.
Solution again is quite simple: add a few lines of server side script to your edit box's onkeyup event thus resetting the view to show page #1:
getComponent("viewPanel1").gotoFirstPage();

Related

Passing Repeat Index Parameter into a Validations Phase Listener

I have a repeat control with links to various XPages. I have validations set at the individual field level. I'm trying to find a way to disable all validations if a user navigates to a previous link (page). One idea I came across was using a phase listener. I tried passing a repeatIndex parameter to the phase listener to determine whether or not to disable validations (if repeatIndex < currentPageIndex then disable validations). However, it does not appear that the repeatIndex is being passed when the link is clicked:
<xp:repeat
id="Repeat"
indexVar="repeatIndex"
rows="30"
var="repeatData">
<xp:this.value><![CDATA[#{javascript:["Link 1", "Link 2"];}]]></xp:this.value>
<xp:link
escape="true"
text="#{javascript:repeatData}"
id="Link">
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="complete">
</xp:eventHandler>
<xp:this.parameters>
<xp:parameter
name="repeatIndex">
<xp:this.value><![CDATA[#{javascript:repeatIndex;}]]></xp:this.value>
</xp:parameter>
</xp:this.parameters>
</xp:link>
</xp:repeat>
Is it possible to pass the repeatIndex to the phase listener somehow? Is there a better way to go about this? Thanks for any tips.
As far as the server-side is concerned, standard repeat controls only contain a single set of components. There is no index available outside the repeat, a row is set up and destroyed as it is iterated.
If your check for whether or not validation should be enabled depends on something available for the row, you can compute the disableValidators or immediate properties on the link's eventHandler. But bear in mind the calculation needs to happen server-side and pass the result to the browser when the page is rendered, so you won't be able to take into account any changes made since that part of the page was last passed to the browser.
If you want to access the repeat from outside, you can set repeatControls="true", which basically reproduces a set of components for each element of the repeat when the page's component tree (server-side map of the page) is loaded. You can then set the id property as "Link#{repeatData}", so you get Link0, Link1 etc. But because the sets of components are hard-coded, you won't be able to use pagers to change what data each row is bound to.

Can I filter an Xpages search bar

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

Partial update dynamic view on CustomControl | XPages

I have an application with one XPage. It has these custom controls(cc):
ccHeader
ccMenu
ccContent
ccFooter
Custom control ccContent has a combobox, with list of Views in sessionScope and dynamic view panel from extension library for XPages. This combobox has an event OnChange defined to partial update dynamic view.
What do I need?: Combobox with view list will be deleted and after that I need to assign this partial update function to five links, which are located on ccMenu custom control. So, i click on link in ccMenu, it returns some view name, assigns it to dynamic view and makes partial update.
How to get id of this dynamic view in ccMenu to call partial update?
Assuming what you mean is that you want to have a clean way to let the buttons know which area to partial-refresh when changed:
You could add a property to the ccMenu control along the lines of "viewRefreshId" and pass in the ID of the area to refresh, so you'd end up with a button like this:
<xp:button id="viewChanger1" value="View 1">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="${compositeData.viewRefreshId}">
<xp:this.action><![CDATA[#{javascript: viewScope.selectedView = 'View 1' }]]></xp:this.action>
</xp:eventHandler>
</xp:button>
Now, there's a question of whether you should try to pass in an ID from something contained within another CC from the main XPage, and I try to avoid that - it would PROBABLY work, but it's a bit messy. I tend to architect similar things so that the part to be refreshed is directly on the XPage (which is to say, I don't use "content" custom controls), so I end up with something like this:
<xc:viewSelector viewRefreshId="dynamicViewContainer"/>
<xp:div id="dynamicViewContainer">
<xe:dynamicView>
<xe:this.data>
<xp:dominoView var="view1" viewName="#{viewScope.selectedView}"/>
</xe:this.data>
</xe:dynamicView>
</xp:div>
The extra container div comes from experience that I had a while ago where refreshing the dynamic view directly caused rendering problems, but I don't know if that's still the case (or if I had run into some other problem).

Set readonly property inside a nested panel

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.

Dynamic Table from Lotus Notes to XPages within a form

I am taking an existing Lotus Notes database and converting to Xpages. There is one of those tables containing 3 multi-value fields, with New Line as the seperator and the "Add New", "Modify" and "Delete" buttons controlling how the data is entered and removed. The customer would like the XPage to look as similar to the Notes GUI as possible, and I was thinking I would use the dijit dialog box to do the add new line and figure out the delete and modify. But from what I can tell, the dialog box can only be used on client-side and the data input into the dialog box can't be brought down onto the Xpage. Is this true? I was thinking I would use an editable field within a repeat, but I also couldn't that working properly.
Basically, it the solution has to show the multi-value fields for past documents and also be able to allow users to edit those older document...plus work similar/exactly the way as in the past when creating new docs.
Thanks in advance for any help I can get on this as it seems a ton easier than I am probably making it out to be.
I just wanted to update after the solution below, which appears to be an excellent way to solve this problem. However, as an admitted XPages novice, I am really struggling with the application of this concept. This is what I have, and it obviously isn't working.
Logically, this sounds like a great solution. However, I am no xpages expert and I simply can't get this working properly even to get started. Anything at all that would make this easier for me to even get started would be a big help. I'm not one to usually look for "the answer"...I'm just having difficulty getting a handle on this Multi-value field table issue. Thanks again in advance...here's what I wrote that is coming up with a 500 error. "A" is the multi-value field name.
<xp:table>
<xp:tr>
<xp:td>
<xp:repeat id="repeat1" rows="30" var="rowdata">
<xp:this.value><![CDATA[#{javascript:document1.getItemValue("A")}]]></xp:this.value>
<xp:tr id="valueRow">
<xp:td>
<xp:text
value="#{javascript: return rowdata[i]}" />
</xp:td>
<xp:eventHandler event="onclick" submit="false"
refreshMode="partial" execMode="partial" execId="valueRow"
immediate="true">
<xp:this.action>
<![CDATA[#{javascript:document1.getItemValue("A")}]]>
</xp:this.action>
</xp:eventHandler>
</xp:tr>
</xp:repeat>
</xp:td>
</xp:tr>
</xp:table>
I would say do the following
Create a repeat control which will extract the data from the multi value fields and print them read only. The repeat control will generate a tr structure with a event handler bound to it on the onclick event. something like this:
2 In the onclick event change the style of the tr clientside (using dojo) so people know they selected that row and set the id / identifier of that row in a scoped var
3 Above the repeat control add controls like add, remove, update. The add and update will open a dialog box and will read the data from the selected row ( or none if its a add action). The delete control will remove the data from the multiline value fields, save the document and refres the repeat control.
This should work.

Resources