I have a selectOneMenu and a dataTable. When I change the selected value, dataTable will repopulate.
A one of column of the dataTable is an inputText. The problem is that the inputText field doesn't call the getter, but caches the previous value.
I want to either call the getter by force or set inputText to not be cached.
How do I get rid of this problem?
<h:body>
<f:view>
<h:form id="headForm">
<ice:selectOneMenu id="item"
value="#{outerBean.selectedItem}"
valueChangeListener="#{outerBean.itemListValueChanged}"
style="width: 158px;" required="true"
label="Supplier Id" partialSubmit="true">
<f:selectItems value="#{outerBean.itemList}" />
</ice:selectOneMenu>
<ice:dataTable id="pdet" value="#{outerBean.nestedClassList}" var="nestedObject" rendered="true">
<ice:column>
<f:facet name="header">Order Number</f:facet>
<ice:outputText value="#{nestedObject.orderNumber}" />
</ice:column>
<ice:column>
<f:facet name="header">Qty</f:facet>
<ice:inputText value="#{nestedObject.qty}" id="qty" label="'Qty' FOR 'Order Number':#{nestedObject.orderNumber} "
partialSubmit="true"
valueChangeListener="#{nestedObject.qtyChanged}"
validator="#{nestedObject.validateQty}">
</ice:inputText>
</ice:column>
</ice:dataTable>
</h:form>
</h:view>
public class OuterBean{
private List<String> itemList = new ArrayList<String>();
private String selectedItem;
private List<NestedClass> nestedClassList = new ArrayList<NestedClass>();
public OuterBean(){
//init values
}
public void itemListValueChanged(ValueChangeEvent e){
selectedItem = (String)e.getNewValue();
//reset the dataTable record list
nestedClassList = getRandomRecords();
}
//---getters-setters-----//
private class NestedClass{
private int orderNumber;
private int qty;
NestedClass(){
orderNumber = generateOrderNumber();
qty = getRandomQty();
}
//-----qtyChangedListener----//
//-----qtyValidator----------//
//-----getters-setters-------//
}
}
I don't see where you are chainging nestedObject.qty in itemListValueChanged
The component will not rerender unless it is changed .
Partial Submit in Icefaces will only update the components whose value have changed.
You can make Partial Submit false on selectonemenu or you can reinitialize the value of the inputText in itemListValueChanged.
Related
How can I dynamicaly disable an inputTextarea based on the value of a specific checkbox from within a ui:repeat list?
<ui:repeat var="eligibilityReason"
value="#{itemDetails.itemSelected.listEligibilityReasons}">
<h:selectBooleanCheckbox id="eligibilityReasonOptId"
value="#{eligibilityReason.selected}"/>
<h:outputText value="#{eligibilityReason.eligiReasonDescr}"/>
</ui:repeat>
<h:inputTextarea id="ineligiReasonOtherId"
value="#{itemDetails.itemSelected.ineligiReasonOther}"
disabled="???" />
Backing bean:
private String eligiReason;
private String eligiReasonDescr;
private boolean selected;
listEligibilityReasons gets a List<EligibilityReason>. So how can I dynamically enable/disable the inputTextarea based only on the selected/checkbox value for eligiReason='99'?
Something like this should do. The ajax event is ONLY fired for item 99 and calls a Java method to set a Boolean flag for the Text Area. This is untested but gives you the idea of what you need to do.
<ui:repeat var="eligibilityReason" value="#{itemDetails.itemSelected.listEligibilityReasons}">
<p:selectBooleanCheckbox id="eligibilityReasonOptId" value="#{eligibilityReason.selected}" itemLabel="#{eligibilityReason.eligiReasonDescr}">
<p:ajax listener="#{view.reason99}" disabled="#{eligibilityReason.eligiReason eq '99'}" update="ineligiReasonOtherId" />
</p:selectBooleanCheckbox>
</ui:repeat>
<h:inputTextarea id="ineligiReasonOtherId"
value="#{itemDetails.itemSelected.ineligiReasonOther}"
disabled="#{view.textAreaDisabled}" />
Java:
boolean textAreaEnabled = false;
public void reason99(AjaxBehaviorEvent event) {
textAreaEnabled = event.getSource().getValue();
}
I have prime faces form that have set of input elements and finally button let's call it i_BTN which is not the submit button and datatable let's call it f_DT.
My logic is to fill set of elements let's is call these elements :
inpt_1 and inpt_2 not all elements and when click on i_BTN it is add new record in f_DT.
I am using partial submit in i_BTN to to that logic cause i don't to submit all fields.
Button do its task fine and new record is added in f_DT
My big deal is :
when i am add ajax in f_DT to catch rowSelect the SelectEvent object pass with null value.
with full submit SelectEvent is passed with value.
<h:form id="generalForm">
<p:inputText label="full_submit_input_one" id="inpt1"/>
<p:inputText label="full_submit_input_two" id="inpt2"/>
<h:panelGrid columns="4" id="partial_submit_Panel">
<p:inputText label="partial_submit_input_one" id="inpt3"/>
<p:inputText label="partial_submit_input_two" id="inpt4"/>
</h:panelGrid>
<p:dataTable id="itemDT" var="item" value="#{itemView.items}" selectionMode="multiple"
selection="#{itemView.selectedItems}"
rowKey="#{fee.Id}">
<p:ajax event="rowSelect"
listener="#{dtFeesView.onRowSelect}" />
<p:column headerText="Input three">
<h:outputText value="#{fee.inpt3}" />
</p:column>
<p:column headerText="Input four">
<h:outputText value="#{fee.inpt4}" />
</p:column>
</p:dataTable>
<p:commandButton value="Full Submit" actionListener="#{itemView.add}"/>
<p:commandButton value="Partial Submit" actionListener="#{itemView.insertRecord}" process=":generalForm:partial_submit_Panel"/>
#ManagedBean(name="itemView")
#ViewScoped
public class ItemView{
private ItemModel selectedItems[];
// getters and setters for selectedItems
private List<ItemModel> items;
// getters and setters for items
public void add(){
// add item to i.e database
}
public void insertRecord(){
// add itemModels to items list
}
public void onRowSelect(SelectEvent event) {
ItemModel model =(ItemModel)event.getObject();
// model is null in case of process with value :generalForm:partial_submit_Panel
//model is not null in case of process with value generalForm "submit full form"
}
}
please help.
regards.
I have a h:inputText with valueChangeListener, when the user type some code another h:inputText display data from MySQL about that code, the valueChangeListener works but the second h:inputText not displayed the value and only do it when I set the readonly attribute or I change the component to h:outputText
my facelets page is:
<h:form id="idFacturacion">
<rich:panel>
<f:facet name="header">
<h:outputText value="FACTURACION AL CLIENTE" />
</f:facet>
<h:panelGrid columns="4">
<h:outputText value="Cedula: " />
<h:inputText value="#{facturaBean.encFactura.cedula}" onchange="submit();" valueChangeListener="#{facturaBean.processValueChange}" />
<h:outputText value="Nombre: " />
<h:inputText value="#{facturaBean.encFactura.nombre_cli}" />
</h:panelGrid>
</rich:panel>
</h:form>
facturaBean is:
#ManagedBean
#SessionScoped
public class FacturaBean {
private EncFactura encFactura = new EncFactura();
//getter and setter
public void processValueChange(ValueChangeEvent event){
String ced = event.getNewValue().toString();
try{
//do the database thing
if(resultSet.next()){
encFactura.setNombre_cli(resultSet.getString("nombre_cli"));
}else{
encFactura.setNombre_cli("");
}
}catch(SQLException error){
facesContext.addMessage(null, new FacesMessage("Hubo un error SQL."));
}
}
}
Please see
Change inputText value from listener method… and
Possible to execute `valueChangeListener` for `p:inputText` without hitting `enter` key?
May I suggest using ajax?
Here is a primefaces example but you could apply to richfaces..
<h:inputText value="#{facturaBean.stringOne}" >
<p:ajax event="change" listener="#{facturaBean.processValueChange}" update="strTwo"/> </h:inputText> <h:outputText value="Nombre: " />
<h:inputText id="strTwo" value="#{facturaBean.stringTwo}" />
</h:panelGrid>
private String stringOne= "";
private String stringTwo= "";
public void processValueChange(){
stringTwo = stringOne;
}
With getters etc.. basically on change, fires off to ajax, you do your database call etc, then it returns the response and updates your other input field, it's a much cleaner way than trying to submit forms etc..
Also are you sure you want session scope?
I have a code:
<h:panelGroup>
<p:panel>
<p:commandButton value="Go" style="background:#25A6E1;color:#fff;font-family:'Helvetica Neue',sans-serif;font-size:10px;border-radius:4px;"
actionListener="#{customCalender.searchUserofList}" update="picklist">
<f:attribute name="trigram" value="#{customCalender.listTrig}"/>
<f:attribute name="firstName" value="#{customCalender.listFname}"/>
<f:attribute name="lastName" value="#{customCalender.listLname}"/>
<f:attribute name="teamName" value="#{customCalender.selectedTeam}"/>
</p:commandButton>
</p:panel>
</h:panelGroup>
<h:panelGroup id="picklist" rendered="#{not empty customCalender.searchList}">
<p:pickList value="#{customCalender.searchList}" var="user" itemLabel="#{user}" itemValue="#{user}"/>
</h:panelGroup>
and the searchList generates on button click in the method searchUserofList().
I declared searchList as:
private DualListModel searchList;
public DualListModel<String> getSearchList() {
return searchList;
}
public void setSearchList(DualListModel<String> searchList) {
this.searchList = searchList;
}
and its being defined in method searchUserofList method like:
List<EmpBean> list = new ArrayList<EmpBean>();
list = getSearchResult("people",trigram,firstName,lastName,teamName);
Iterator<EmpBean> iterator = list.iterator();
List<String> userList = new ArrayList<String>();
List<String> userTarget = new ArrayList<String>();
while(iterator.hasNext()){
String userName = iterator.next().getStrUserid();
System.out.println("Name :: "+userName);
userList.add(userName);
}
searchList = new DualListModel<String>(userList, userTarget);
But when button clicked it gets the list but the picklist with the values are not shown.
How can I make that correct to show the picklist?Please suggest.
You can't update dynamically a component that is not rendered, you should move your rendered attribute so your component always exists.
<h:panelGroup id="picklist">
<p:pickList rendered="#{not empty customCalender.searchList}" value="#{customCalender.searchList}" var="user" itemLabel="#{user}" itemValue="#{user}"/>
</h:panelGroup>
I have a h:datatable showing a list of rows, and the fields of each row are input fields.
I render an "Add Row" button before the table, and a "Remove Row" button on each row of the table.
The baking bean is viewScoped, and the buttons add/remove elements from the java list in the backing bean, and then return to the same view.
I set the immediate attribute to "true" in the buttons in order to not validate the input fields when I add or remove a row.
Everything works ok but one thing: the values of the input fileds are cleared. I thought that the view kept the values beacuse the bean is viewScoped.
How can I achieve adding/removing rows without triggering validations and keeping the values that were already typed by the user in the form?
My view:
<h:form>
<h:commandButton value="Añadir Fila" immediate="true" action="#{tablaController.addRowAction}" />
<h:dataTable value="#{tablaController.lista}" var="fila" cellpadding="0" cellspacing="0" border="1">
<f:facet name="header">TABLA</f:facet>
<h:column>
<f:facet name="header"><h:outputLabel value="NOMBRE" /></f:facet>
<h:inputText id="nom" value="#{fila.nombre}" />
<h:message for="nom" class="msjError" />
</h:column>
<h:column>
<f:facet name="header"></f:facet>
<h:commandButton value="Quitar Fila" immediate="true" action="#{tablaController.removeRowAction(fila)}" />
</h:column>
</h:dataTable>
</h:form>
My backing bean:
#ManagedBean(name="tablaController")
#ViewScoped
public class TablaController {
private List<Fila> lista;
...
public TablaController() { }
...
#PostConstruct
public void init() {
this.lista = new ArrayList<Fila>();
for (int i=0; i<5; i++) {
Fila fila = new Fila();
fila.setNombre("");
this.lista.add(i,fila);
}
}
...
public String addRowAction () {
Fila fila = new Fila();
fila.setNombre("");
this.lista.add(fila);
return "";
}
public String removeRowAction (Fila f) {
boolean exito = this.lista.remove(f);
return "";
}
...
}
UPDATE --> MY SOLUTION:
I write here my solution if someone is interested.
The problem is that I use immediate="true" to skip validations, but this makes to skip the update_model_values too, so that the values entered by the user in the form are lost after clicking the add/remove buttons and re-redenring the page.
As I use "JSR-303 bean validation", my solution was to skip validations using the f:validateBean to enable/disable them. Depending on the button I click, if I want the validations to execute, I enable the bean validation (for example in a "submit" button), and if I want to skip them, I disable bean validation (like in the add/remove row buttons). But anyway the update_model_values always executes, so the values are not lost.
Here's the view:
<h:form>
<f:validateBean disabled="#{!empty param['disableValidation']}">
<h:commandButton value="Añadir Fila" action="#{tablaController.addRowAction}">
<f:param name="disableValidation" value="true" />
</h:commandButton>
<h:dataTable value="#{tablaController.lista}" var="fila" cellpadding="0" cellspacing="0" border="1">
<f:facet name="header">TABLA</f:facet>
<h:column>
<f:facet name="header"><h:outputLabel value="NOMBRE" /></f:facet>
<h:inputText id="nom" value="#{fila.nombre}" />
<h:message for="nom" class="msjError" />
</h:column>
<h:column>
<f:facet name="header"></f:facet>
<h:commandButton value="Quitar Fila" action="#{tablaController.removeRowAction(fila)}">
<f:param name="disableValidation" value="true" />
</h:commandButton>
</h:column>
</h:dataTable>
<h:commandButton value="Submit" action="#{tablaController.saveData}" />
</f:validateBean>
</h:form>
The backing bean:
#ManagedBean(name="tablaController")
#ViewScoped
public class TablaController {
private List<Fila> lista;
...
public TablaController() { }
...
#PostConstruct
public void init() {
this.lista = new ArrayList<Fila>();
for (int i=0; i<5; i++) {
Fila fila = new Fila();
fila.setNombre("fila "+i);
this.lista.add(i,fila);
}
}
...
public String addRowAction () {
Fila fila = new Fila();
fila.setNombre("");
this.lista.add(fila);
return "";
}
public String removeRowAction (Fila f) {
this.lista.remove(f);
return "";
}
...
public String saveData () {
...
//processes the valid data
//for example, calls to a service method to store them in a database
...
return "";
}
...
}
I set the immediate attribute to "true" in the buttons in order to not validate the input fields when I add or remove a row.
immediate="true" is the wrong tool for the job. It should be used to prioritize validation, not to enable/disable validation. The difference is rather huge as you encountered yourself.
You want to trigger validation conditionally. In case of e.g. required="true" that'd be as easy as
<h:inputText ... required="#{saveButtonPressed}" />
where #{saveButtonPressed} evaluates true when the save button is pressed. E.g. when its client ID is present in request parameter map.
In case of JSR 303 bean validation, that'd be a matter of
<f:validateBean disabled="#{not saveButtonPressed}">
<h:inputText ... />
</f:validateBean>
or with OmniFaces <o:validateBean> which allows controlling that on a per-command basis.
<h:commandButton id="add" ...>
<o:validateBean disabled="true" />
</h:commandButton>
I had exactly the same problem. In short, you can NOT use immediate for action that update data table(UIData) or facelet repeat. Short explanation:submitted values are not kept for re-display if inputs in UIData do not go through validation. Long explanation can be found here: long explanation and a related bug in Mojarra