最新处理项目需要使用带勾选的列表,但是GXT3已经去掉了这个类,一看Sencha的官方论坛,尼玛居然要收费。于是自己DIY了一个,简单几行代码,方便好用。
STEP1.定义一个用于列表的类,由于我的选择一般是以ID为关键选择数据的,因此定义了一个LabelValue类:
import com.flipthebird.gwthashcodeequals.EqualsBuilder;
/**
* @author JIM
* 动态绑定关联ID值用的数据结构。
* label是显示的名称,value是绑定的值,一般是ID。
*/
public class LabelValue {
private String label;
private Integer value;
public LabelValue(){};
public LabelValue(String label, Integer value){
this.label = label;
this.value = value;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof LabelValue)){
return false;
}
if(this == obj){
return true;
}
LabelValue other = (LabelValue)obj;
return new EqualsBuilder()
.append(getLabel(),other.getLabel())
.append(getValue(),other.getValue())
.isEquals();
}
}
STEP2. 我们要用到的CheckBoxListView,主要原理是内部渲染为checkbox,然后将selectionChange事件和界面checkbox的勾选同步
package xxx.xxx.xxx.components;
import java.util.ArrayList;
import java.util.List;
import xxx.xxx.xxx.xxx.dto.LabelValue;
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.sencha.gxt.cell.core.client.form.CheckBoxCell.CheckBoxAppearance;
import com.sencha.gxt.cell.core.client.form.CheckBoxCell.CheckBoxCellOptions;
import com.sencha.gxt.core.client.Style.SelectionMode;
import com.sencha.gxt.core.client.ValueProvider;
import com.sencha.gxt.data.shared.ListStore;
import com.sencha.gxt.data.shared.ModelKeyProvider;
import com.sencha.gxt.widget.core.client.ListView;
import com.sencha.gxt.widget.core.client.ListViewSelectionModel;
import com.sencha.gxt.widget.core.client.container.SimpleContainer;
import com.sencha.gxt.widget.core.client.form.CheckBox;
import com.sencha.gxt.widget.core.client.selection.SelectionChangedEvent;
import com.sencha.gxt.widget.core.client.selection.SelectionChangedEvent.SelectionChangedHandler;
public class CcCheckBoxListView<M> extends SimpleContainer{
private ListStore<LabelValue> store;
private ListView<LabelValue, LabelValue> listView;
private CheckBoxAppearance checkBoxAppearance = GWT.<CheckBoxAppearance>create(CheckBoxAppearance.class);
private CheckBox selectAllCheckBox;
private static final String LIST_CHECK_BOX_NAME = "listCheckBox";
private SelectionChangedHandler<LabelValue> selectionChangedHandler;
public static interface DataProvider<M> {
String getLabel(M model);
Integer getValue(M model);
}
public CcCheckBoxListView(){
store = new ListStore<LabelValue>(new ModelKeyProvider<LabelValue>() {
@Override
public String getKey(LabelValue item) {
return item.getValue().toString();
}
});
listView = new ListView<LabelValue, LabelValue>(store, new ValueProvider<LabelValue, LabelValue>(){
@Override
public LabelValue getValue(LabelValue value) {
return value;
}
@Override
public void setValue(LabelValue object, LabelValue value) {
object.setLabel(value.getLabel());
object.setValue(value.getValue());
}
@Override
public String getPath() {
return null;
}
}, new AbstractCell<LabelValue>() {
@Override
public void render(Context context, LabelValue value, SafeHtmlBuilder sb) {
CheckBoxCellOptions checkBoxCellOptions = new CheckBoxCellOptions();
checkBoxCellOptions.setBoxLabel(value.getLabel());
checkBoxCellOptions.setName(LIST_CHECK_BOX_NAME);
checkBoxAppearance.render(sb, listView.getSelectionModel().isSelected(value), checkBoxCellOptions);
}
});
ListViewSelectionModel<LabelValue> ListViewSelectionModel = new ListViewSelectionModel<LabelValue>() {
@Override
protected boolean isInput(Element target) { //do not ignore click
if(target.getAttribute("name").equals(LIST_CHECK_BOX_NAME)) {
return false;
}
return super.isInput(target);
}
};
ListViewSelectionModel.setSelectionMode(SelectionMode.SIMPLE);
ListViewSelectionModel.addSelectionChangedHandler(new SelectionChangedHandler<LabelValue>() {
@Override
public void onSelectionChanged(SelectionChangedEvent<LabelValue> event) {
List<LabelValue> selection = event.getSelection();
List<LabelValue> allData = store.getAll();
for(int i = 0; i < allData.size(); i ++) {
boolean dataChecked = selection.contains(allData.get(i));
Element checkBoxElement = listView.getElement(i).getFirstChildElement().getFirstChildElement();
boolean viewChecked = checkBoxElement.getPropertyBoolean("checked");
if(viewChecked != dataChecked) {
checkBoxElement.setPropertyBoolean("checked", dataChecked);
}
}
if(selectAllCheckBox != null) {
if(selection.containsAll(allData)) {
selectAllCheckBox.setValue(true);
}
if(selection.isEmpty()) {
selectAllCheckBox.setValue(false);
}
}
if(selectionChangedHandler != null) {
selectionChangedHandler.onSelectionChanged(event);
}
}
});
listView.setSelectionModel(ListViewSelectionModel);
this.add(listView);
}
public void setDataList(List<M> dataList, DataProvider<M> dataProvider) {
clearDataList();
addDataList(dataList, dataProvider);
}
public void setDataList(List<LabelValue> dataList) {
clearDataList();
addDataList(dataList);
}
public void clearDataList() {
store.clear();
}
public void addDataList(List<M> dataList, DataProvider<M> dataProvider) {
List<LabelValue> labelValueList = new ArrayList<LabelValue>();
for(M model: dataList) {
labelValueList.add(new LabelValue(dataProvider.getLabel(model), dataProvider.getValue(model)));
}
store.addAll(labelValueList);
}
public void addDataList(List<LabelValue> dataList) {
store.addAll(dataList);
}
public List<LabelValue> getSelectedItems() {
return listView.getSelectionModel().getSelectedItems();
}
public List<LabelValue> getDataList() {
return store.getAll();
}
public void deleteDataList(List<LabelValue> dataList) {
for(LabelValue labelValue: dataList) {
store.remove(labelValue);
}
}
public ListViewSelectionModel<LabelValue> getSelectionModel() {
return listView.getSelectionModel();
}
public void bindSelectAllCheckBox(CheckBox selectAllCheckBox) {
this.selectAllCheckBox = selectAllCheckBox;
selectAllCheckBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
@Override
public void onValueChange(ValueChangeEvent<Boolean> event) {
if(event.getValue()) {
listView.getSelectionModel().selectAll();
}else {
listView.getSelectionModel().deselectAll();
}
}
});
}
public void setSelection(List<LabelValue> selectionList, boolean keepExisting) {
listView.getSelectionModel().select(selectionList, keepExisting);
}
public void setSelection(List<M> selectionList, DataProvider<M> dataProvider, boolean keepExisting) {
List<LabelValue> labelValueList = new ArrayList<LabelValue>();
for(M model: selectionList) {
labelValueList.add(new LabelValue(dataProvider.getLabel(model), dataProvider.getValue(model)));
}
listView.getSelectionModel().select(labelValueList, keepExisting);
}
public void addSelectionChangedHandler(SelectionChangedHandler<LabelValue> selectionChangedHandler) {
this.selectionChangedHandler = selectionChangedHandler;
}
}
使用:
在你的VIEW里需要使用泛型定义该组件.
@UiField
public CcCheckBoxListView<LabelValue> checkBoxListView;
类型也可以不是LabelValue,但是这样的话需要使用setDataList(List<M> dataList, DataProvider<M> dataProvider)的方式来设置数据,DataProvider是数据转换器,用来制定label和vale
支持使用bindSelectAllCheckBox绑定一个全选的CheckBox,当数据被全部勾选/未勾选时自动同步状态.
使用效果: