简体   繁体   中英

How to update button inside <ui: repeat>?

This is my problem. I have two <p: commandLink> inside a <ui: repeat> . I need to update these buttons by simulating checkbox when I click them. Updating a <panelGroup> around <ui:repeat> works. However for a list with many items, after clicking the button the update, it makes the screen go back to the top of the list making it impracticable to select many items. Are there any ways to give an update specific line in <p:commandLink> ?

<tbody>
    <ui:repeat value="#{myBean.itens}" var="item" varStatus="index">
        <tr class="myCustomClass" id="item#{item.id}">
            <th>
                <p:commandLink
                    rendered="#{myConditionRendered}"
                    actionListener="#{myBean.deselect(item)}"
                    update=":panelGroupArroundId"
                    process="@this">
                    <i style="font-size: 15px;" class="fa fa-check-square-o" />
                </p:commandLink>
                <p:commandLink
                    rendered="#{!myConditionRendered}"
                    actionListener="#{myBean.select(item)}"
                    update=":panelGroupArroundId"
                    process="@this">
                    <i style="font-size: 15px;" class="fa fa-square-o" />
                </p:commandLink>
            </th>
            <td>
                <h:outputText value="#{item.field1}"/>
            </td>
            ...                                                         
        </tr>
    </ui:repeat>
</tbody>

JSF version: 2.1
Primefaces version: 3.5

The trick here is to update only the sections you need - if you update the whole container the browser will reset and refresh from the point where the most recent update happened. In JSF there are a couple of ways to accomplish what you need. More recent versions of JSF (2.3 in particular) has selectors available such as :parent to allow to easier target specific parts of the page to update. With 2.1 you are slightly more limited.

I made a quick test and came up with a working example of your particular user case. The image below is using Font Awesome and PrimeFaces 3.5;

在此处输入图像描述

I slightly tweaked your code and made a complete and working example. The controller and backing bean have been separated into separate classes in this example. First let's take a look at the backing bean:

@Data @Named @ViewScoped
public class MyBean implements Serializable {
    @Data @RequiredArgsConstructor
    public static class Item {
        @NonNull private String name;
        private boolean selected;
    }

    private List<Item> items;

    @PostConstruct
    private void init() {
        items = List.of(new Item("a"), new Item("b"), new Item("c"),
            new Item("d"), new Item("e"), new Item("f"), new Item("g"), 
            new Item("h"), new Item("i"), new Item("j")
        );
    }
}

This defines our data set and uses Lombok to minimize the amount of boilerplate code ( @Data and @RequiredArgsConstructor ). I also added a selected flag to keep track of if the checkbox is selected or not. This is then used in the controller bean when selecting and deselecting:

@Data @Named @RequestScoped
public class MyBeanController {
    @Inject
    private MyBean myBean;

    public void select(Item item) {
        item.setSelected(true);
    }

    public void deselect(Item item) {
        item.setSelected(false);
    }
}

Furthermore, here is the view (XHTML) definition:

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <title>Button update in UI repeat example</title>
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.0.0/css/font-awesome.css" />
    </h:head>
    <h:body>
        <table>
            <tbody>
                <ui:repeat value="#{myBean.items}" var="item">
                    <tr style="float: left; padding-right: 10px">
                        <th>
                            <h:form>
                                <h:panelGroup id="content">
                                    <p:commandLink rendered="#{item.selected}"
                                        actionListener="#{myBeanController.deselect(item)}"
                                        update="content" process="@this">
                                        <i class="fa fa-check-square-o" />
                                    </p:commandLink>
                                    <p:commandLink rendered="#{!item.selected}"
                                        actionListener="#{myBeanController.select(item)}"
                                        update="content" process="@this">
                                        <i class="fa fa-square-o" />
                                    </p:commandLink>
                                </h:panelGroup>
                            </h:form>
                        </th>
                        <td><h:outputText value="#{item.name}"/></td>                                                       
                    </tr>
                </ui:repeat>
            </tbody>
        </table>
    </h:body>
</html>

As you can see we wrap the buttons inside a form and define an container content that we reference in the update attributes of the p:commandLink tags. Because we are wrapped inside a form the actual id of the panelGroup actually becomes something like j_idt6:9:j_idt8:content with each content id being unique (because each form has a unique id generated).

This allows us to target and update the data of that row specifically.

Theoretically you could update the form directly without wrapping it inside a content . However, doing so interferes with the life-cycle and handling of the form when wrapped inside a ui:repeat . Adding an additional panelGroup and updating that instead, like in this example, solves the issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM