1

I have a <h:dataTable> that is populated from an Entity class and displays different products. I want to be able to click a <h:commandLink> and edit row that the link belongs to. I have structured it mostly the same way as this nice example and article at mkyong.

The table (with some columns excluded):

<h:form>
    <h:dataTable id="gnomeTable" value="#{gnome.productList}" 
                 var="item" 
                 styleClass="gnomeTable"
                 headerClass="gnomeTableHeader"
                 rowClasses="gnomeTableOddRow,gnomeTableEvenRow"
                 bgcolor="#F1F1F1" border="10"  cellspacing="2"
                 rules="all" >           

        <f:facet name="header">
            <h:outputText value="List of available gnomes for sale" />
        </f:facet> 

        <h:column>
            <f:facet name="header">
                <h:outputText value="GnomeID" />
            </f:facet> 
            <h:outputText value="#{item.id}"></h:outputText>
        </h:column>

        <h:column>
            <f:facet name="header">
                <h:outputText value="Name"/>
            </f:facet> 
            <h:outputText value="#{item.name}" rendered="#{not item.editable}"></h:outputText>
            <h:inputText value="#{item.name}" rendered="#{item.editable}"></h:inputText>
        </h:column>

        <h:column>
            <f:facet name="header">
                <h:outputText value="Available"/>
            </f:facet>
            <h:outputText value="#{item.available}" rendered="#{not item.editable}"></h:outputText>
            <h:inputText value="#{item.available}" rendered="#{item.editable}"></h:inputText>
        </h:column>
        <h:column>
            <f:facet name="header">
                <h:outputText value="Edit"/>
            </f:facet>
            <h:commandLink value="Edit" action="#{gnome.editAction(item)}" rendered="#{not item.editable}" />
        </h:column>
    </h:dataTable>
    <h:commandButton value="Save Changes" action="#{gnome.saveAction}" />
</h:form>

The Bean methods:

public String saveAction() {
    for (Gnome g : productList) {
        g.setEditable(false);
    }
    return null;
}

public String editAction(Gnome gnome) {
    gnome.setEditable(true);
    return null;
}

The property boolean editable in the entity class is annotated as @Transient since it's not a part of the persistant data and I don't want the entity manager to touch it:

@Transient
private boolean editable;

I thought this would result in the boolean variable being set to true when the Edit-button is clicked, the row re-renders with the fields now as <h:inputText>, but nothing happens. I have debugged it and made sure that the variable is set to true, which it is.

I also found this SO question that I thought perhaps could be something similar to the problem I am experiencing. The difference though is that a refresh of the page doesn't change anything.

What am I missing?

Edit 1: In the first version of this question I had by mistake pasted the wrong code. The one that is included now is my current code, that in theory should work but does not.

Edit 2: Initialization of productList, where Gnome is the entity class.

private List<Gnome> productList = new ArrayList<>();

public List<Gnome> getProductList() {
    productList = gnomeFacade.findAll();
    return productList;
}

public void setProductList(List<Gnome> productList) {
    this.productList = productList;
}
Community
  • 1
  • 1
Daniel B
  • 8,770
  • 5
  • 43
  • 76
  • Where is your h:inputText tags specified ? I dont see any in the columns. You will need to specify both outputText and inputText with one rendered evaluating to true and one to false according to editable is true or false. – prajeesh kumar Jan 03 '14 at 16:38
  • @prajeeshkumar you are correct! By mistake I pasted an old version of the code. I have edited it to the correct version! – Daniel B Jan 03 '14 at 16:46
  • @DanielB You should probably remove this question, this make no more sense on SO since the problem can't help other people. Glad it works! – Alexandre Lavoie Jan 03 '14 at 20:47
  • @AlexandreLavoie I still have the same problem. The error that prajeesh pointed out was just a paste error here on SO. The problem remains, and the code in my original question is the code that in theory should work, but does not. – Daniel B Jan 03 '14 at 20:51
  • @DanielB Ok, in that case my comment is invalid now! :) – Alexandre Lavoie Jan 03 '14 at 21:11
  • @DanielB What is the scope of your bean? – Alexandre Lavoie Jan 03 '14 at 21:23

1 Answers1

2

After testing your example, the only possible error is that you are using a RequestScoped bean. In order to make it work, you need at least ViewScoped or SessionScoped. Ortherwise, the productList changed content is lost at every requests (button action).

According to the edit, the second mistake is how data is took. You need to load your data somewhere else than getter like this :

@PostConstruct
public void init()
{
    productList = gnomeFacade.findAll();
}

public List<Gnome> getProductList()
{
    return productList;
}

Ortherwise, at every actions your list is reset.

Alexandre Lavoie
  • 8,711
  • 3
  • 31
  • 72
  • The thought that the error could be due to something like this struck my mind, though I couldn't figure out why it happened. I have now changed it to `@ViewScoped` instead of `@RequestScoped`, since I want the bean to persist until I navigate to another page. Though, the problem still remains; the boolean variable is set to true but the form is not rendered differently than before. – Daniel B Jan 03 '14 at 21:57
  • @DanielB Can you show how you are initializing `productList` ? – Alexandre Lavoie Jan 03 '14 at 22:01
  • Added the initialization of the list in original post, see edit 2! – Daniel B Jan 03 '14 at 22:06
  • And where `setProductList` is called ? – Alexandre Lavoie Jan 03 '14 at 22:10
  • It isn't, and should be removed. The `dataTable` populates successfully via the `productList` property, aswell as the `editable` variable is set to `true` when the Edit-`commandLink` is pressed. As far as I understand from reading up on the scopes, the only problem should have been the issue with the wrong scope, but as it seems, it's not. Do I have to specifically call the form to rerender it? – Daniel B Jan 03 '14 at 22:17
  • Thank you, Alexandre! I have two pages where the same issue occurred, and your solution to load the data first and only once did the trick in the page where I manage the customers. The problem still remains on the page where I want to manage the products, but since it is working as planned on the other page, the problem must be related to something else. Nice solution! – Daniel B Jan 03 '14 at 22:38