I would like to start with x no. of fields (in my app I have a pair of textual data field and numeric data field) on a xpage application (say 10 pairs) and then when the user clicks on "more field", I want more pairs to appear dynamically without a full refresh on the page, but would like unlimited no. of fields (as long as the page doesn't crash) and then I would like to submit the form and the data for all those fields. What's the best way to implement this?
Usually, fields are bound to a document data source using dot notation:
<inputText value="#{contact.firstName}" />
However, array notation is also supported:
<inputText value="#{contact['firstName']}" />
Because the field name in this latter syntax is being treated as a string, not as an implicit property of the bean, it can be dynamically computed. What I've found to be the easiest way to define these dynamic fields is to create a custom control for each of the basic types of fields, and define each as accepting the data source and the field name. So the field itself then ends up with a syntax similar to the following:
<inputText value="#{compositeData.dataSource[compositeData.fieldName]}" />
By using that syntax, a calculation of any complexity can be used to determine what field name to pass to the custom control. In the scenario you're attempting to accomplish, specifying an indexVar on the repeat control that surrounds the field pair would allow you to designate a field suffix for each... perhaps something like the following:
<xp:repeat indexVar="fieldSuffix" value="#{viewScope.rowCount}">
<xp:div>
<xc:dynamicInputText dataSource="#{contact}" fieldName="fullName_#{fieldSuffix}" />
<xc:dynamicInputNumber dataSource="#{contact}" fieldName="phoneNumber_#{fieldSuffix}" />
</xp:div>
</xp:repeat>
With this approach, you would end up with fields named "fullName_0", "fullName_1", etc., up to the limit specified in the viewScope. Typically, the only complication is ensuring that when an existing document is opened, the viewScope variable is set back to the correct limit. Another approach to that, of course, is actually saving the limit as another item on the document and binding the repeat value to it instead.
You also can have a look at the exercise 23 "Tablewalker". It doesn't do multiple fields but does Multi-value fields which might be better in terms of processing and storage (you can do an #Elements to find out how many are there in a document). The exercise is here:
http://www-10.lotus.com/ldd/ddwiki.nsf/dx/Tutorial-Introduction-to-XPages-Exercise-23
While the button only adds one row at a time, it is easy to adjust.
What you could do is have a Bean with 2 String values Label and Data and a managed bean that has a ArrayList of that object so inside of your repeat control you bind the repeat to the ArrayList and then bind your xp:inputText to rowData.Data and your xp:label to rowData.Label then when you want to add another 5 rows you just add However many more objects into the ArrayList then refresh your page, your data will still live in your arraylist and you will have 5 new Empty objects where you can add data.
public class Data {
private String label;
private String data;
public Data() {
}
//getters and setters
}
public class ManagedBean {
private ArrayList<Data> datalist; // add a managed property for this one so It will create a new one when needed.
// getters and setters
public addFiveMoreObjects() {
Data newItem;
for (int i=0; i<5; i++) {
newItem = new Data();
datalist.add(newItem);
}
}
}
<xp:repeat value="#{managedBean.datalist}" var="rowData">
<xp:text value="#{rowData.label}" />
<xp:inputText value="#{rowData.data} />
</xp:repeat>
<xp:button value="Add 5 More"> // call #{managedBean.addFiveMoreObjects}
Related
This question already has answers here:
Why JSF calls getters multiple times
(9 answers)
Closed 6 years ago.
In my ADF project , I have a table component on JSF page whose value attribute is bound to method in Managed bean which returns List type object . I am able to show the data on the table but i can see the method being executed as many as 22 times ! Why the method is being called this many times and does the same thing happens with business components as well when we expose them through Data control? TIA
Edit : JSPX code :
<af:table var="row" rowBandingInterval="1"
autoHeightRows="10"
binding="#{backingBeanScope.backing_ForEachExample.t2}"
id="t1" partialTriggers=":::cb1"
styleClass="AFStretchWidth"
value="#{backingBeanScope.backing_ForEachExample.test2}">
<af:column sortable="false" headerText="col1" id="c3">
<af:outputText value="#{row}" id="ot2"/>
</af:column>
</af:table>
Bean Method is :
public List<String> gettest2(){
/* Unique values are derived */
List<String> tab=new ArrayList<String>();
for(String s:uniqueValues){
System.err.println("? Unique Value is : "+s);
tab.add(s);
}
return tab;
}
when you are using ADF BC, data is displayed from you VO which is exposed in AM through a data control, you can specify VO tuning properties, which determine how many records are fetched from database in one round trip. this is named in batches of. you can specify iterator's range size in sync with how many records you are fetching from database in one go and how many you need to dispay in table at UI. af:table has an attribute called fetchSize, if you set this attribute to some value equal to iterator range size say 20, and VO > Tuning > in batches of = 20, it would query only once. by default, VO in batches of is equal to 1, in that case, if you display a table with autoheightrows = 20, in this case table will query data multiple times from database.
for manage a cart i have create an HashMap and i convert this in a list for display into a PrimeFaces Datatable with this method:
public List<Map.Entry<Livre, Integer>> getPanier() {
Set<Map.Entry<Livre, Integer>> panierSet = panier.entrySet();
return new ArrayList<Map.Entry<Livre, Integer>>(panierSet);
}
Once the list shown i wish to update the quantity directly inside the datatable with inputText.
But i have no idea if this is possible ? or if i need to convert HashMap in ArrayList for do this traitement.
You can use something like this in your table
<h:inputText value="#{myMap[someVarUsedInDatatable.keyOfThatRow]}"/>
That will allow you to read and modify the relevant value in the relevant key...
I'm trying to put an autocomplete that fetches suggestions as a list of Entry<String, Integer>
<p:autoComplete completeMethod="#{suggester.suggestTopics}"
var="x1" itemLabel="#{x1.key}" itemValue="#{x1.value.toString()}"
value="#{topicController.selected}" />
Manged bean code is as follows:
private int selected;
public int getSelected() {
return selected;
}
public void setSelected(int selected) {
this.selected= selected;
}
But this fails saying the Integer class doesn't have method/property named key. If I remove the value attribute from autocomplete then it starts working properly. But when I put value attribute it starts expecting that the object inside var should be of the same type as that inside value attribute. I believe/expect it should be that the object inside itemValue should be of the same type as that inside value attribute.
I want to use POJOs for suggestions but pass just the entity Id to the value
Using :
Primefaces 3.1
JSF 2.1.6
I believe/expect it should be that the object inside itemValue should
be of the same type as that inside value attribute.
Yes this makes sense, and it is the same in the primefaces showcase:
<p:autoComplete value="#{autoCompleteBean.selectedPlayer1}"
id="basicPojo"
completeMethod="#{autoCompleteBean.completePlayer}"
var="p" itemLabel="#{p.name}" itemValue="#{p}"
converter="player" forceSelection="true"/>
As you see is var="p" and itemValue="#{p} where p is an instance of Player. And selectedPlayer1 is also an instance of Player.
I don't know if it works with a Map since the Primefaces example is called "Pojo support" and the suggestions should be a List of elements of the same type as in the value attribute.
I think you want to use the Simple auto complete , but instead you looked at the wrong example on the showcase of the Pojo Support
x1 refers to the int selected - while it expect to be referred to a POJO (with key and value properties.) , that's why you get the message
Integer class doesn't have method/property named key
Or simple use the Simple auto complete
As commented to Matt you dont need to rebuild Player(Pojo) from Db. You can set simply id property of Player(Pojo) and in action method may be utilize this id to fetch it from DB.
In your case in convertor you might do
Entry<String, Integer> e = new Entry<String, Integer>();
e.setId(value) // where value is passed in to convertor in method getAsObject.....
This value will be set to private Entry<String, Integer> selected
I have used Pojo autocomplete but not tried with generic classes.
Hope this helps.
I know the question is outdated but I've had the same problem.
The point is that you have to assign var to p (var="p"). I think it's terribly unobvious (documentation doesnot mention it has to be that way) 'cause I thought I can assign any var name I want.
I am using the Primefaces wizard component. On one tab I am dynamically creating input boxes based on previous tabs input(user type). The inputbox text labels are derived from a list. In my backing bean, I have a map that contains input labels as keys and inputbox inputs as values.
Clicking on next, I would like the map(values) to be updated with the user input (corresponding to the key)
<c:forEach items="#{gdsiGeodataBean.actionCommand.fields}" var="reqs">
<h:outputLabel for="#{reqs.name}" value="#{reqs.name}:* " />
<pou:inputText value="#{gdsiGeodataBean.actionCommand.values['reqs.name']}" required="true" requiredMessage="Input is required."/>
</c:forEach>
My backing bean :
private List<RequiredParam> fields; // +getter (no setter required)
private Map<String, String> values; // +getter (no setter required)
public CommandAction(String actionName, String actionParams, String context) {
this.actionName = actionName;
this.actionParams = actionParams;
this.contextName = context;
//Set up parameters
getRequiredParams();
getOptionalParams();
fields = getFields();
values = new HashMap<String, String>();
}
Essentially what I would like is for the map values to be updated with user inputs from the textinput boxes.
Your approach to bind the input value to a map is not entirely correct.
<pou:inputText value="#{gdsiGeodataBean.actionCommand.values['reqs.name']}" required="true" requiredMessage="Input is required."/>
You're specifying a fixed map key instead of a dynamic map key based on the currently iterated #{reqs}. This way all submitted values will end up in one and same fixed map key "reqs.name", whereby each one overrides each other so that you only get the value of the last field in the map.
You need to remove those singlequotes to make it a really dynamic key.
<pou:inputText value="#{gdsiGeodataBean.actionCommand.values[reqs.name]}" required="true" requiredMessage="Input is required."/>
Unrelated to the concrete question, even though this approach will work when used as-is in your question, the <c:forEach> will fail in certain circumstances. E.g. when used inside a composite component or an iterating JSF component. Rather use <ui:repeat> instead. See also JSTL in JSF2 Facelets... makes sense?
I am having some trouble with using h:selectOneRadio. I have a list of objects which is being returned which needs to be displayed. I am trying something like this:
<h:selectOneRadio id="selectPlan" layout="pageDirection">
<f:selectItems value="#{detailsHandler.planList}" />
</h:selectOneRadio>
and planList is a List of Plans. Plan is defined as:
public class Plan {
protected String id;
protected String partNumber;
protected String shortName;
protected String price;
protected boolean isService;
protected boolean isOption;
//With all getters/setters
}
The text that must appear for each radio button is actually in a properties file, and I need to insert params in the text to fill out some value in the bean. For example the text in my properties file is:
plan_price=The price of this plan is {0}.
I was hoping to do something like this:
<f:selectItems value="<h:outputFormat value="#{i18n.plan_price}">
<f:param value="#{planHandler.price}">
</h:outputFormat>" />
Usually if it's not a h:selectOneRadio component, if it's just text I use the h:outputFormat along with f:param tags to display the messages in my .property file called i18n above, and insert a param which is in the backing bean. here this does not work. Does anyone have any ideas how I can deal with this?
I am being returned a list of Plans each with their own prices and the text to be displayed is held in property file. Any help much appreciated.
Thanks!
I am now able to resolve the above issue following the recommendation below. But now I have another question.
Each radio button item must display like this:
Click **here** to see what is included. The cost is XX.
Now the above is what is displayed for each radio button. The "here" needs to be a hyperlink which the user can click and should bring up a dialog box with more info.I can display the sentence above but how do I make the "here" clickable?
Since the above is what is displayed it is the label for SelectItem(Object value, String label) which is returned.
Any ideas much appreciated.
The value passed to <f:selectItems /> must be a list or array of type javax.faces.model.SelectItem.
You can set the output label in the constructor of the SelectItem. I imagine you can access your properties file from the backing bean. The method to get the SelectItems would look something like this:
public List<SelectItem> getPlanItems() {
List<SelectItem> list = new ArrayList<SelectItem>();
for (Plan plan : planList) {
String label = buildPlanPriceLabel(plan.getPrice());
list.add(new SelectItem(plan, label));
}
return list;
}
Leaving buildPlanPriceLabel as an exercise for the reader.