How to dynamically add input rows to JSF h:dataTable and keep focus where it was - jsf

Problem is simple. Page has some textfields and user must be able to write into as many of them as he needs. When user starts to fill last textfield then new empty textfield must be added.
Currently i am able to add rows with ajax but focus gets lost. Bean keeps track of total number of rows and if currently focused row is last then new item is added to list and datatable rerendered. How to keep the focus in input textfield where it was before rendering. I can also use openfaces features.
<h:form id="myform">
<h:dataTable id="table" value="#{ajaxTestBean.rows}" var="rows">
<h:column>
<h:inputHidden id="inputtext" binding="#{ajaxTestBean.input}" value ="#{rows.rownum}"></h:inputHidden>
<h:inputText value="#{rows.text}">
<f:ajax event="focus" listener="#{ajaxTestBean.action}" render=":myform"></f:ajax>
</h:inputText>
</h:column>
</h:dataTable>
</h:form>

Related

JSF validation error prevents updating another valid rows of an h:dataTable placed in an h:form

I have an h:dataTable inside of an h:form, where each row has it's own h:commandButton type="submit" action="#{bean.saveChanges(item)}".
f:inputs are declared as required and they also need to match a pattern.
If every input is in the right format, then it works fine.
Otherwise it needs only one input to be wrong and an updating function on a commandButton corresponding to a completely different item in another row seems not to be called, therefore not updated in the database.
Also only the wrong row's validation message is displayed and the changes are maintained in the view by a (backing Spring view scoped) bean, so the user might actually think, that the initial row was indeed updated in the database too.
Is there a way, how to separate individual rows of the h:dataTable, so that the validation messages of another row does not stop other items from being updated by the method of a (Spring/backing) bean?
Use ajax to process/execute only the current row. You can achieve that by explicitly specifying the client IDs of the input components in <f:ajax execute>.
<h:form>
<h:dataTable ...>
<h:column>
<h:inputText id="foo" ... />
</h:column>
<h:column>
<h:inputText id="bar" ... />
</h:column>
<h:column>
<h:inputText id="baz" ... />
</h:column>
<h:column>
<h:commandButton ...>
<f:ajax execute="foo bar baz #this" ... />
</h:commandButton>
</h:column>
</h:dataTable>
</h:form>
This won't process the inputs in other rows. Use if necessary <f:ajax render> to update the <h:message(s)> associated with the inputs.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
The required on the input cause the Process validation to fail and the render response to be invoked.
A simple solution could be You could remove the required from the input and handle the case in you managed bean. Since the action would move on till Phase 5: Invoke application the valid data can be saved. For all invalid rows highlight the row by having a boolean in you data model.

unselect the selected rows in a datatable

I'm working on a datatable with a single selection mode.My problem is that when I refesh the page , the same selected rows before refreshing stay refreshed.
Any idea on how unselecting all datatable rows in this case.
I appreciate helping me with this issue.
This is my datatable code:
<p:dataTable id="cars1" var="car" widgetVar="carsTable" value="#{typePrimeManager.tprimes}" editable="false" style="margin-bottom:20px" paginator="false" selectionMode="single" selection="#{typePrimeManager.selectedtype}" rowKey="#{car.idPrime}">
<p:ajax event="rowSelect" update=":form:cars2" />
<p:ajax event="rowUnselect" listener="#{typePrimeManager.setSelectedtype(null)}" update=":form:cars2"/>
<p:ajax event="rowUnselect" listener="#{typePrimeManager.setSelectedtype(null)}" update=":form:cars2"/>
<p:column headerText="intitule des types">
<h:outputText value="#{car.intitulePrime}" />
</p:column>
</p:dataTable>
You use a managed bean with SessionScoped ? This keep the value unchange. I Recommand to you to read this : How to choose the right bean scope?
If you want to keep using SessionScope and reset the selected rows you have to clean the selectedtype inside your bean
If you have to have a session scoped bean, you need to clear the value that DataTable holds to reference the selected item which in your case is typePrimeManager.selectedtype.
So if you set this value to null or any object of the same type that is not in the DataTable dataSource than your problem will resolved, but you have to do this before page is reloaded. To get that event you can use pre-defined JSF events ,like PreRenderView, to execute a method in which you should clear the selected value, or you can define a remoteCommand that will call the appropriate bean method and execute that remoteCommand with javascript when the page is loaded.

Saving data from multiple inputtext boxes created by a loop in jsf

Basically, I have an input text box that I want to submit for each item in the array. The code below is cut down to the relevant portions
<c:forEach items="${mybean.mats}" var="mat">
<p:dataTable var="datarow" value="#{mybean.getDatarows(mat.itemId)}" rowIndexVar="row">
<p:column>
<p:inputText value="#{bean.amt}" />
</p:column>
</p:dataTable>
</p:panel>
<p:commandButton value="Confirm" action="#{mybean.runSubmit}" process="#this" />
</c:forEach>
From what I know, each individual item needs to have its own variable name to save the data in each input text box. I know the method I'm currently using is wrong, so is there another way to save all the data? Perhaps in an array or something?
First, mixing the JSTL c:foreach with a datatable is not recommended. Use ui:repeat instead.
Second, your p:dataTable value has to reference a collection that exists during the lifetime of the backing bean. It looks to me like the call to #{mybean.getDatarows(mat.itemId)} generates a list of items dynamically. That's going to be a problem since your backing bean will need to call the getDatarows when the values are re-applied to the bean on your ajax call runSubmit to save the values. In this case, you will need to save the dynamically created list to the backing bean so that the same collection will match up exactly to the collection used to produce the html.
For example, suppose your backing bean contains the property List<List<Mat>> mats, where the Mat class contains a single property 'dataId'. Then, your EL could be:
<h:form id="input-form">
<ui:repeat id="mats-repeat" value="#{mats}" var="mat">
<p:dataTable id="mat-table" value="#{mat}" var="dataObj">
<p:column>
<p:inputText id="dataId" value="#{dataObj.dataId}" />
</p:column>
</p:dataTable>
</ui:repeat>
</h:form>
Since the form, repeat, and dataTable components are naming containers, they ensure that any child components are named uniquely. In this case, the first input mat element would be rendered as:
<input id="input-form:mats-repeat:0:mat-table:0:dataId" ...

Record navigator from jsf datatable

I require some advice on a query regarding record navigation.
I have a datatable that is displayed with the results of an Hibernate query. The datatable looks something like this:
<h:dataTable value="#{myBean.dataList}" var="dataItem">
<h:column>
<f:facet name="header">
<h:outputText value="ID" />
</f:facet>
<h:outputText value="#{dataItem.id}" />
</h:column>
The user then selects a row and it displays a form with the details on a JSF form.
What I would like to do is allow the user to go to the next row in the results table from the JSF form without going 'back' to the results table.
Is this possible?
You can do a ajax call on click of Next button present on the form. When the user presses Next, on default event "action", you can write code in a managed bean method which will be called through the listener property of f:ajax. in this method call, you can set the values of different fields on the form depending on the Id of the next record. These values may be used by different components on your form.
<h:commandButton value="Next">
<f:ajax event="action" execute="#this" render="#form" listener="#{myBean.populateNextRecord}"/>
</h:commandButton>

input binding in ui:repeat in jsf

i am using facelets jsf 2.0 with primefaces 3.0.M2 component library.
i am trying to achieve dynamic numbers of rows including iput fields that are filled when a datatable selection occurs.
whenever a selection is made the dynamic rows generated correctly with input fields but after the first selection for following selections dynamic row count changes correctly but the input fields does not update and keeps showing inputs from the first selection.
here is how i iterate list in facelet;
<ui:repeat value="#{goalEntranceBean.selectedCard.parameterList}" var="prmBean" >
<li><h:outputText value="#{prmBean.lookUp.value}"/></li>
<li>
<h:outputText value="Weight:"/>
<p:inputText id="wx" required="true" value="#{prmBean.weight}">
</p:inputText>
<h:outputText value="Percent:"/>
<p:inputText required="true" value="#{prmBean.percent}">
</p:inputText>
</li>
</ui:repeat>
my bean where i get the list of cards and set the selectedCard with rowSelect event in datatable.
#ManagedBean(name = "goalEntranceBean")
#ViewScoped
public class GoalEntranceAction implements Serializable {
private List<ScoreCard> personalCards = new ArrayList<ScoreCard>();
private ScoreCard selectedCard = new ScoreCard();
......
}
when i checked in debug mode i can see the true list but in screen the elements does not change.
This is a common problem (gets asked every couple of days). To make long story short, inputs inside ui:repeat do not work, period.
It is a problem with JSF, a long standing, famous one. Maybe it will be fixed. Maybe not, it seems that no one really cares (I mean - an input? in a... ui:repeat? such crazy scenario!).
A quick-fix is to use a h:dataTable, possibly ungodly abused with css to make it look like a list. A long-fix is to use some iterator from a different library. Primefaces has an element that should work that renders an unordered list.
thanks for your replies. Sorry for forget sharing the solution.
As i mentioned above i have primefaces datatable.
On row selection event i render datatable and want to update the cells of that datatable.
USING p:inputtext easily solved my problem. Now i can change the data on screen and i can see the values after update operation on screen. I don't understand the reason but it works.
<p:dataTable var="orgPrmBean"
value="#{scoreCardOperationsBean.selectedCard.orgParameterList}"
emptyMessage="#{labels.norecord}"
rowKey="#{orgPrmBean.id}"
>
<p:columnGroup type="header">
<p:row>
<p:column headerText="Parameters" colspan="3" style="text-align:left;width:480;"/>
</p:row>
</p:columnGroup>
<p:column style="text-align:left;width:200px;">
<h:outputText value="#{orgPrmBean.info}"/>
</p:column>
<p:column style="text-align:left;width:180px;">
<p:inputText value="#{orgPrmBean.weight}"
rendered="#{scoreCardOperationsBean.selectedCard.goalEdit}">
<f:convertNumber maxFractionDigits="0"/>
</p:inputText>
</p:column>
</p:dataTable>
It IS possible to make it work, but the solution is to bind the inputs to a backing bean, and update the values of the controls in the backing bean via listeners (using the new value received in the argument). Obviously this isn't a good solution if you have a complex form, as you need to add a listener/control in the backing bean for each control in the page, but it's practical if you just have one or two inputs.

Resources