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

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.

Related

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>

JSF Updating values in a bean from a list

So, I have a session scoped bean that has a 2 lists of string values. This bean is called AgreementBean.java. I'm showing these lists in a page called agreementDetail.xhtml like this
<h:dataTable id="servers" value="#{agreement.licenseServerNames}" var="licenseServerName">
<h:column>
<h:inputText value="#{licenseServerName}"/>
</h:column>
</h:dataTable>
Computer IDs<br/>
<h:dataTable id="idNames" value="#{agreement.computerIdNames}" var="computerIdName">
<h:column>
<h:inputText value="#{computerIdName}"/>
</h:column>
</h:dataTable>
As you can see, I expect user input on these values. I need to make an Ajax call to update those values when the customer clicks on a "Save button". Here's the button's jsf code.
<script type="text/javascript">
function showAlert(data){
alert("SAVED!");
}
</script>
<h:commandButton value="Save" immediate="true" type="submit" action="#{agreement.save}">
<f:ajax onevent="showAlert"/>
</h:commandButton><br/><br/>
The "Save" bean method does nothing right now, except for logging the values stored in both lists.
When clicking on the button, 2 things are happening right now. If the customer changed the values on the inputFields, the bean's list's value is set to null. If the customer didn't change anything, then the bean's original value is kept.
How can I fix this? Thanks!
There are 2 problems with your command button:
<h:commandButton value="Save" immediate="true" type="submit" action="#{agreement.save}">
<f:ajax onevent="showAlert"/>
</h:commandButton>
immediate="true" causes that only input elements which also have immediate="true" set will be processed. However, your inputs don't have this attribute set.
<f:ajax execute> defaults to #this, causing that only the command button itself is processed during form submit. Your inputs are therefore skipped in processing.
Get rid of the misplaced attribute and tell <f:ajax> to execute the entire form.
<h:commandButton value="Save" type="submit" action="#{agreement.save}">
<f:ajax execute="#form" onevent="showAlert"/>
</h:commandButton>
See also:
Why was "immediate" attribute added to the EditableValueHolders?
Then there's a potential problem with your data model. You seem to be supplying a List<String> to the data table instead of a List<SomeBean>. The String is immutable and doesn't have a setter for the value. A <h:inputText value="#{string}"> is never going to work. For the first table, you really need to have a LicenseServer bean with a private String name property. You can then use it as follows:
<h:dataTable value="#{agreement.licenseServers}" var="licenseServer">
<h:column>
<h:inputText value="#{licenseServer.name}"/>
See also:
Why input (for example h:inputText) nested in h:dataTable do not update Bean model?
Unrelated to the concrete problem, are you aware that onevent is invoked 3 times? For the purpose you'd probably like to check if ajax event status equals to "success".
See also:
Proccess onclick function after ajax call <f:ajax>

Set f:param in external h:commandButton (JSF2)

I really love actionListener and the possibility to pass whole objects as as parameter, instead needing to pass values as String or creating (hidden) form fields. I'm using JSF 2.1 (Mojarra) and RichFaces (for popupPanel).
Currently I'm stuck with the following problem:
I create a table with a button that opens a popup. In that popup, the user can edit the data of the current user/object in the table.
When I click the button in the popup to save the edits, how can I submit the values from the popup AND tell the bean action which userObject I'm edited?
Currently, my workaround is using a hidden inputText field in the popup, but I don't like it this way. Is there an alternative?
This is what I try to achieve (minimized):
<h:datatable value="#{bean.users}" var="user">
<h:column>
Username #{user.name}
</h:column>
<h:column>
<input onclick="showPopup()"/>
</h:column>
</h:datatable>
<rich:popupPanel>
<h:inputText value="#{bean.text}" />
<h:commandButton value="Action" actionListener="#{bean.doSomething}">
<f:attribute name="selected" value="#{userObjectFromDatatable}" /> <-- HOW? -->
</h:commandButton>
</rich:popupPanel>
Looks pretty straightforward for you to preserve the selected the userObject in a conversation-like scope as in #ViewScoped. See this article for details on the #ViewScope. As an example, Declare a variable of the desired type as an instance variable in your backing bean
UserObject userObject;
//getters and setters
In your table you'll now have something like the following to set the selected object in your backing bean
<h:commandButton value="Action" actionListener="#{bean.doSomething}">
<f:setPropertyActionListener value="#{user}" target="#{bean.userObject}"/>
</h:commandButton>
By setting the variable in your backing bean from within the table, the viewscope will ensure that any other operation you perform on that object will be with the same instance, provided you stay on the same JSF view and you do not navigate away from it.

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

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>

Resources