Update single row in JSF / Primefaces datatable using AJAX

后端 未结 4 447
孤城傲影
孤城傲影 2020-12-17 21:17

How could I update a single row in a p:datatable when using AJAX?

I don\'t want to update the whole datatable because it has a lot of rows and it\'s going to take so

相关标签:
4条回答
  • 2020-12-17 21:35

    Not sure if I'm late for the party but let me give my 5 cents on this subject on how to update content of a row using just plain ajax features from PrimeFaces.

    1) Partial update: My first approach to update something in a specific row using PF is not exactly update the whole row, but update the regions of interest inside the row. This can be achieved by just defining the holding panels and updating them. For example:

    <h:form id="testForm">
        <p:dataTable id="myEntityTable" var="myEntity" value="#{myController.allEntities}">
    
            <p:column headerText="id">
                <h:outputText value="#{myEntity.id}"/>
            </p:column>
    
            <p:column headerText="last update">
                <p:outputPanel id="lastUpdatePanel">
                    <h:outputText value="#{myEntity.lastUpdate}">
                        <f:convertDateTime pattern="HH:mm:ss" type="date" />
                    </h:outputText>
                </p:outputPanel>
            </p:column>
    
            <p:column headerText="counter">
                <p:outputPanel id="counterPanel">
                    <h:outputText value="#{myEntity.counter}"/>
                </p:outputPanel>
            </p:column>
    
            <p:column headerText="increment">
                <p:commandButton value="+"
                    actionListener="#{myController.increment(myEntity)}"
                    update="counterPanel, lastUpdatePanel"/>
            </p:column>
        </p:dataTable>
    </h:form>
    

    The trick is to update the target panels (in this example the fragment update="counterPanel, lastUpdatePanel"). This results in something like the following image:

    2) Actually updating the row: Very often the previous approach works fine enough. However, if it is really needed to update the row one can follow the advice given in one of the previous answers and use the @row keyword:

    <h:form id="testForm">
        <p:dataTable id="myEntityTable" var="myEntity" value="#{myController.allEntities}" rowIndexVar="rowIndex">
    
            <p:column headerText="id">
                <h:outputText value="#{myEntity.id}"/>
            </p:column>
    
            <p:column headerText="last update 1">
                <p:outputPanel>
                    <h:outputText value="#{myEntity.lastUpdate}">
                        <f:convertDateTime pattern="HH:mm:ss" type="date" />
                    </h:outputText>
                </p:outputPanel>
            </p:column>
    
            <p:column headerText="last update 2">
                <h:outputText value="#{myEntity.lastUpdate}">
                    <f:convertDateTime pattern="HH:mm:ss" type="date" />
                </h:outputText>
            </p:column>
    
            <p:column headerText="counter">
                <p:outputPanel>
                    <h:outputText value="#{myEntity.counter}"/>
                </p:outputPanel>
            </p:column>
    
            <p:column headerText="increment">
                <p:commandButton value="+"
                    actionListener="#{myController.increment(myEntity)}"
                    update="@form:myEntityTable:@row(#{rowIndex})"/>
            </p:column>
        </p:dataTable>
    </h:form>
    

    The trick is to hold each content from the columns inside a p:outputPanel and let update="@form:myEntityTable:@row(#{rowIndex})" make the job. I consciously leave the "last update 2" column without an outputPanel in order to illustrate this point:

    Hence, whereas the columns "last update 1" and "counter" actually update after a click in "+" the "last update 2" column keeps unchanged. So, if you need to update a content, wrap up it with an outputPanel. It is noteworthy as well that the outputPanels holding each column content don't need an explicit id (you can add one if you want). In the sake of completeness, in these examples I have used PF 6.2. The backbean is pretty straightforward:

    package myprefferedpackage;
    
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    
    import javax.annotation.PostConstruct;
    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.ViewScoped;
    
    @ManagedBean
    @ViewScoped
    public class MyController {
    
        private List<MyEntity> entities;
    
        @PostConstruct
        public void init() {
            this.entities = new ArrayList<MyEntity>(10);
            for(int i = 0; i < 10; ++i) {
                this.entities.add(new MyEntity(i));
            }
        }
    
        public List<MyEntity> getAllEntities() {
            return entities;
        }
    
        public void increment(MyEntity myEntity) {
            myEntity.increment();
        }
    
        public class MyEntity {
            private int id;
            private int counter;
            private Date lastUpdate;
    
            public MyEntity(int id) {
                this.id = id;
                this.counter = 0;
                this.lastUpdate = new Date();
            }
    
            public void increment() {
                this.counter++;
                this.lastUpdate = new Date();
            }
    
            public int getId() {
                return id;
            }
    
            public int getCounter() {
                return counter;
            }
    
            public Date getLastUpdate() {
                return lastUpdate;
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-17 21:45

    Either use the 'ajax' functionality of a utility library like OmniFaces or be creative with the PrimeFaces Selectors.

    In both cases you need to get access to the e.g. the 'current' row or rowId. But since that you have the buttons IN the row, that should not be a problem. I unfortunately don't have the time to create examples for you

    0 讨论(0)
  • 2020-12-17 21:57

    You can use @row(n) search expression which does just that - it updates the nth row in a table. In order to update the current row, you need to pass row index as an argument. Set rowIndexVar="rowIdx" attribute on <p:dataTable> and then:

    <p:commandButton ... update="@form:visitTable:@row(#{rowIdx})" />
    
    0 讨论(0)
  • 2020-12-17 21:59

    I try with uptate = "@parent:componentAnotherColumn" and works. Only update the same row

     <p:column>    
           <p:selectBooleanCheckbox value="#{atributoVar.booleanValue}">
                <p:ajax process="@this" update="@parent:componentAnotherColumn"/>
           </p:selectBooleanCheckbox>
     </p:column>
     <p:column>                            
         <p:selectBooleanCheckbox id="componentAnotherColumn" value="#{!atributoVar.booleanValue}"/>
     </p:column>                    
    
    0 讨论(0)
提交回复
热议问题