XPages: Repeat Control with Sections - xpages

i'm using a repeat control in my XPage which contains some repeated sections.
The titles/header of this sections are computed from a JSON String which is stored in a sessionScope variable. So far evrything works fine.
Now i have to expand/collapse one or more sections with a button outside the repeat control.
The button "knows" the title and the header of the section which have to be collapsed/expanded.
How can i get the right ID to use something like:
getComponent("XXXXXXX").setClosed(true);
Any Ideas?

You can achieve this in client side JavaScript. First you need to find the ID of section which contains your header text. For that you can use a simple dojo.query with selectors.
var sectionID = dojo.query(".xspSection:contains('<YOUR HEADER TEXT>')")[0].id;
This would search for all the sections on your page with your specified header text in it and return all the nodes. Assuming that your header is unique get the first node (that's why the [0]) and from it get the ID of section. Once you have the ID use the XSP object to show/hide section.
XSP.showSection(sectionID, [true|false]);

Related

What is the "for identifier" in a formRow good/used for?

The extension library offers means to structure your forms by Form Tables, where you can put Form Layout Columns and Form Layout Rows.
The Form Layout Rows have a property called "for" (the "For Indentifier") - here is the OnHover-text:
"Holds the ID of the control used to edit the data. That control should be contained within this Form Layout Row control."
So, I could enter the id of e.g. an Edit Box control I put into this form row (which translates to the code ' for="inputText1" '). But what exactly is this needed for? Where or for what can this information be used?
I found no different behaviour or limited functionality when sparing this information - at least, not how we use it atm. I found nothing in the web regarding this question; hope anyone can shed some light.
It's useful if your form row contains multiple controls, preventing the form row's code from determining its "for" target automatically. In that situation, you can provide the server-side ID of the "real" target control in the row to keep the label behavior working properly.
It's also mandatory to set this attribute if you want to use the built-in OneUI or Bootstrap themes to have the label formatted correctly. For example the text will be bold only if you set the for attribute (Bootstrap acts like this)

How do I access a repeat control from the outside e.g. via CSJS

How can/should I access a repeat control from outside? In my case I want to calculate some additional value(s) for the items in the repeat control and update each item with jquery.
In SSJS you always access a component with getComponent("id"). If your contents of the repeat are just a view than define the view data source at the XPage level, not the repeat and you can use the id of the datasource to get the view object, ie, view1.
From SSJS you can access the repeat control itself via getComponent(). However, if you want to access components within the repeat, it gets more challenging.
The default behaviour is to create a single "row" of components for the repeat and then, in the Render Response phase, iterate over them to generate the relevant HTML for the appropriate number of rows (rows property of the repeat control) from the relevant start point (first property of the repeat control, which may have been incremented by a pager), picking the data from the relevant data (value property of the repeat).
If the repeat has repeatControls="true" set, at page load the runtime creates a set of controls for the appropriate number of rows (rows property of the repeat control). However, accessing them may still be a challenge. This will also remove the ability to use a pager.
If you want to manipulate e.g. the appropriate view entries within the repeat, one option might be to load into viewScope the UNID / Note ID via a computed property within each row. E.g.
rendered="#{javascript:if (view.isRenderingPhase()) {
if (idex == 1) viewScope.put("myVar", new java.util.ArrayList());
viewScope.get("myVar").add(entry.getNoteID());
return true;
} else {
return true;
}"
This initialises (or re-initialises) the viewScope variable if it's the first row (please double-check first row has idex as 1, idex being the variable name you define for the indexVar property of the repeat control), and adds the NoteID to the list. So element 0 is the NoteID of the first row, element 1 the Note ID of the second row etc.
If you wish to manipulate values, you may be able to take a similar approach by using dynamic binding. There are various questions on StackOverflow about dynamic binding for repeat controls as well as blog posts, probably by either Tim Tripcony or Jesse Gallagher.
Beyond this, CSJS may be the easiest way to manipulate the contents of the repeat. Just be aware that if you do a partial refresh whose refreshId is the repeat, it may replace whatever you've done client-side.

Conditional Client Side Validation?

I have a radio button group that gets it's values using an #Dblookup. In addition to the name to appear in the radio button group, the document also has a field to determine if another field on the xPage should be displayed or not.
If the field is displayed then it should be required.
I can do the conditional validation just fine in SSJS using an #DbLookup to lookup the document selected in the radio button group.
But I would like to be able to do it CS so it is faster and so it looks like my other validations. Is there anyway to do this?
If a field is not rendered then the node will not exist in the DOM. Your CS javascript would need to examine the DOM and look for the node, normally by looking for a specific ID. As Xpages changes the ID's sent to the browser your validation function would either need to be computed so it would know what ID to look for or you would need to look for it in some other unique way ( like add a css class name to just that field and then do a DOM search for nodes with that class name )
Once you can determine if the field has been rendered then you can run your usual CS validation routine against the other field.
If you're using client-side validation throughout your app, setting the required property on the field should achieve what you need.
If not, it may be worth looking at the Extension Library Dojo Validation Text Box. All the Extension Library Dojo control run client-side validation, even if validation is set as server-side at application level. Bear in mind that for the Dojo Validation Text Box, just setting the required property is not enough. You need to add more specific validation.
After that, the key is to ensure the partial refresh event on your radio group is set to skip validation. I haven't tried, but I believe that should achieve what you need.

The buttons in a repeat don't hide/show after refreshing the panel the repeat is in?

I have a repeat that has buttons embedded in it. The repeat is in a panel. When the user clicks a button the button should hide/show (I partial refresh the panel). The repeat is tied to a Domino view and I see the other values that I from that view get updated in the repeat, so, it does not seem like a view index issue (I refresh the view index in my code.)
If I use context.reloadPage() in my button onclick code then the buttons will hide/show like they should, but, that seems like I am using a sledge hammer! Any suggestions on how to get the buttons to recompute the visible property when the panel that holds the repeat is rendered? Another strange thing is that the visible property gets computed three times whenever I refresh the panel that holds the repeat.
thanks, Howard
I think your looking for
getComponent("<id>").setRendered(true / false);
Hi For Repeat control's entry is used to make our head hard. Because handling the entry by SSJS, we can get the value and set the value. But rendering part, id of the repeating component are same for all. So if we try to give reder as false. It hides all of our repeating component.
Try to use the following., [Put this in button onclick, and see the value of below]
var entryValue= getComponent("repeat1").getChildren().get(0).getValue()
getComponent("inputText1").setValue(entryValue)
But in client side we can easily handle. Because the id of the DOM object is unique for all repeating component.
var id1="view:_id1:repeat2:"+'2'+":button1"
document.getElementById(id1).style.display="none"
This will hide the third entry of your repeat control component.
Please see the post, You may get better idea
Found a solution. My original solution was getting values from the repeat rows (using the collection object, which was a viewentrycollection and using getColumnValues) to compute the rendered property for the buttons.
Instead, I created a viewScope variable (a Vector) that holds the state of the buttons (which set of buttons to show). This gets populated in the beforePageLoad event of the page.
The button onclick code updates this viewScope variable after performing its processing. All works very nice now. I guess it was something in the JSF lifecycle that kept the buttons from being properly updated. Using the viewScope variable works fine.
With addition to what Ramkumar said, you can use the index variable in the repeat control to identify each and every occurrences inside the repeat control. You will get more idea, if you inspect with element from firefox[You might need firebug]. Usually the field mentioned inside a repeat control itself can be considered as an array

Automatically open document when only one document is listed in repeat control

I have a repeat control for a domino view which displays the results from a search field.
As you type more characters into the search field the number of items in the list is reduced. If/When the the list only contains a single item I would like to open item automatically, without having to click the link.
Any ideas are appreciated.
Edit: after some very interesting responses, here are some screenshots
I have 3 elements on the page, a searchbar, a repeat control and a form:
When I start typing in the search bar, the repeat is refreshed with every keystroke:
the list is reduced, typing the next character ...
again the list is reduced, only 2 left, typing again....
Only one left, now it would be time to open the document in the form ..... without clicking the link.
I've tried several events on the page, but it seems that I could not find the one that will allow me to "select" the document and display the data in the form.
It seems that it's not as simple as I thought
Since you want to open the link automatically I don't know if I would try to base it on the getRowCount() of the repeat itself. You don't want to even get that far right? you just want to go to the single document.
I would put a function in beforePageLoad event maybe. Not totally sure which event but I'd try that first. Use SSJS and do a lookup that would basically return a collection of what the repeat would show. If the collection count = 1 then get your destination from that entry and do your redirection from there.
That what I would try at least. Interesting scenario!
Now that I see the screenshots this might be easier then you think and I have already implemented something similar on an internal application that I have built. It does rely on the fact that each entry in the list is 100% unique.
First of all you will need to bind the search field to a scoped variable and the onchange/onkeypress event will need to perform a partial refresh of a panel that contains both the list and the document portion of the page.
For the list the link on each item should set the value of the same scoped variable used in the search box and clicking the link should be set to run a partial refresh of the document area.
For the document area you will need two panels, the first panel will only display if there is no matching document and the second panel will only display if there is a matching document, you can do this in the rendered section by writing some ssjs that grabs a handle to the db/view and does a dblookup and returns either true or false if the document exists depending on panel your dealing with.
With this setup, when somebody clicks a link or fills out the searchbox the scoped variable will contain a value, the document panels will then check to see if this is a unique value in the view in the db and update themselves to either display the 'no document' panel or the 'document' panel accordingly.
You could add a evaluation script to the entry of your repeat control which checks the size of your repeat control using the method getRowCount() from the component. If this is 1 you could execute a context.redirectToPage("yourpage.xsp?id=yourid",true) this forces the current page to send a redirect request back to the browser and therefore redirects you to the correct page.
All you need to know is which xpage you need to open and which parameters you should use. But these could be retrieved from the content you are iterating over.

Resources