You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vaadin 24 TwinColSelect如何添加选中项单独排序按钮?

为Vaadin 24 TwinColSelect添加选中项单独排序按钮的实现方案

由于Vaadin 24的TwinColSelect没有内置选中项的单个排序按钮,我们可以通过自定义组合组件的方式,将TwinColSelect与上移、下移按钮结合,实现和原Vaadin 8 ListBuilder一致的排序功能,具体实现步骤如下:

1. 创建自定义组合组件

创建一个继承自Composite的自定义组件,将TwinColSelect和排序按钮整合到布局中,同时封装排序逻辑:

import com.vaadin.flow.component.Composite;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.twincolselect.TwinColSelect;
import java.util.ArrayList;
import java.util.List;

public class SortableTwinColSelect<T> extends Composite<VerticalLayout> {
    private final TwinColSelect<T> twinColSelect;
    private final Button moveUpBtn;
    private final Button moveDownBtn;

    public SortableTwinColSelect() {
        // 初始化双列选择器
        twinColSelect = new TwinColSelect<>();
        // 初始化排序按钮
        moveUpBtn = new Button(VaadinIcon.ARROW_UP.create());
        moveDownBtn = new Button(VaadinIcon.ARROW_DOWN.create());

        // 初始禁用按钮
        updateButtonStates();

        // 绑定按钮点击事件
        moveUpBtn.addClickListener(e -> moveSelectedItemUp());
        moveDownBtn.addClickListener(e -> moveSelectedItemDown());

        // 监听选中项变化,更新按钮可用状态
        twinColSelect.addSelectionListener(e -> updateButtonStates());

        // 布局组装:按钮垂直排列在选择器右侧
        VerticalLayout buttonLayout = new VerticalLayout(moveUpBtn, moveDownBtn);
        buttonLayout.setAlignItems(FlexComponent.Alignment.CENTER);
        buttonLayout.setSpacing(true);

        getContent().add(twinColSelect, buttonLayout);
        getContent().setAlignItems(FlexComponent.Alignment.CENTER);
        getContent().setSpacing(true);
    }

    // 上移选中项逻辑
    private void moveSelectedItemUp() {
        List<T> selectedItems = new ArrayList<>(twinColSelect.getValue());
        T selectedItem = twinColSelect.getSingleSelectedItem();
        if (selectedItem == null) return;

        int index = selectedItems.indexOf(selectedItem);
        if (index > 0) {
            // 交换当前项与前一项位置
            T temp = selectedItems.get(index - 1);
            selectedItems.set(index - 1, selectedItem);
            selectedItems.set(index, temp);
            // 更新选中列表并保持当前项选中状态
            twinColSelect.setValue(selectedItems);
            twinColSelect.select(selectedItem);
        }
    }

    // 下移选中项逻辑
    private void moveSelectedItemDown() {
        List<T> selectedItems = new ArrayList<>(twinColSelect.getValue());
        T selectedItem = twinColSelect.getSingleSelectedItem();
        if (selectedItem == null) return;

        int index = selectedItems.indexOf(selectedItem);
        if (index < selectedItems.size() - 1) {
            // 交换当前项与后一项位置
            T temp = selectedItems.get(index + 1);
            selectedItems.set(index + 1, selectedItem);
            selectedItems.set(index, temp);
            // 更新选中列表并保持当前项选中状态
            twinColSelect.setValue(selectedItems);
            twinColSelect.select(selectedItem);
        }
    }

    // 更新按钮可用状态
    private void updateButtonStates() {
        List<T> selectedItems = twinColSelect.getValue();
        T selectedItem = twinColSelect.getSingleSelectedItem();

        if (selectedItem == null || selectedItems == null || selectedItems.isEmpty()) {
            moveUpBtn.setEnabled(false);
            moveDownBtn.setEnabled(false);
            return;
        }

        int index = selectedItems.indexOf(selectedItem);
        moveUpBtn.setEnabled(index > 0);
        moveDownBtn.setEnabled(index < selectedItems.size() - 1);
    }

    // 暴露TwinColSelect的公共方法,方便外部配置
    public TwinColSelect<T> getTwinColSelect() {
        return twinColSelect;
    }
}

2. 在视图中使用自定义组件

像使用普通TwinColSelect一样配置和使用自定义组件:

// 创建可排序的双列选择器实例
SortableTwinColSelect<String> sortableSelect = new SortableTwinColSelect<>();
TwinColSelect<String> twinCol = sortableSelect.getTwinColSelect();

// 配置选择器属性
twinCol.setItems("选项1", "选项2", "选项3", "选项4", "选项5");
twinCol.setLabel("可排序的双列选择器");
twinCol.setPlaceholder("请选择选项");
twinCol.setAllItemsVisible(true);

// 添加到视图
add(sortableSelect);

3. 样式优化(可选)

如果需要让按钮和选择器布局更贴合原ListBuilder的样式,可以通过CSS调整按钮尺寸、间距:

.sortable-twin-col-select button {
    width: 32px;
    height: 32px;
}

然后给自定义组件添加样式类:

getContent().addClassName("sortable-twin-col-select");

内容的提问来源于stack exchange,提问作者potabattula mohan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 21:59:55