Using domino-ui datatable search action with remote data store.

huangapple go评论57阅读模式
英文:

Using domino-ui datatable search action with remote data store

问题

连接SearchTableAction头部与服务器端搜索的正确方式是什么?(现在的示例使用LocalListDataStore并通过SearchFilter在客户端进行筛选,而传统的GWT会使用CellTables和AsyncDataProvider)

目前的最佳选项(似乎并不理想)是在构造函数中复制SearchTableAction的UI设置,并创建一个新的类,该类在服务器端调用完成后会调用LocalDataStore的setData方法。

英文:

what is the proper way to connect the SearchTableAction header with a server-side search? (Right now the example uses the LocalListDataStore and filters it client-side via a SearchFilter, Regular GWT would use CellTables and AsyncDataProvider)

The winning option right now (which does not seem ideal) would be to copy SearchTableAction UI setup in the constructor and create a new class that would call setData on the LocalDataStore after the server-side call finishes.

答案1

得分: 2

以下是翻译好的部分:

不需要复制UI,搜索操作以及标题筛选将在更改时触发表事件,任何数据存储都可以侦听这些事件并从事件中读取搜索筛选条件,然后使用它来加载/筛选数据。LocalDataStore执行此操作并在本地筛选数据,远程数据存储将读取这些筛选条件并将它们发送到服务器,服务器将筛选数据并将结果返回给客户端。

这是一个示例的远程数据存储:

package org.dominokit.domino.ui.sample.store;

import org.dominokit.domino.ui.sample.client.Formats;
import org.dominokit.domino.ui.sample.shared.store.CanLoadItems;
import org.dominokit.domino.ui.sample.shared.store.LoadContext;
import org.dominokit.domino.ui.datatable.events.SearchEvent;
import org.dominokit.domino.ui.datatable.events.SortEvent;
import org.dominokit.domino.ui.datatable.events.TableEvent;
import org.dominokit.domino.ui.datatable.events.TablePageChangeEvent;
import org.dominokit.domino.ui.datatable.model.Filter;
import org.dominokit.domino.ui.datatable.model.FilterTypes;
import org.dominokit.domino.ui.datatable.store.DataChangedEvent;
import org.dominokit.domino.ui.datatable.store.DataStore;
import org.dominokit.domino.ui.datatable.store.StoreDataChangeListener;
import org.dominokit.domino.ui.pagination.HasPagination;
import org.gwtproject.i18n.client.DateTimeFormat;

import java.util.*;

import static java.util.Objects.nonNull;
import static org.dominokit.domino.ui.datatable.events.SearchEvent.SEARCH_EVENT;
import static org.dominokit.domino.ui.datatable.events.SortEvent.SORT_EVENT;

public class RemoteDataStore<T> implements DataStore<T> {
    // ... (其余部分请参考上述代码)
}

这里我们侦听事件并委托实际数据加载调用给uiHandlers。

请注意,实施远程数据存储取决于服务器实现,因此没有一个适用于所有人的远程数据存储,因此可以将其用作实现适合您的服务器的示例。

英文:

You dont actually need to copy the UI, the search action as well the header filters will fire a table event when they are changed, any data store can listen to those events and read the search filters from the event and use it to load/filter the data, the LocalDatStore does this and filter the data locally, a remote data store will read these filters and sends them to the server and the server will filter the data and return the result to the client.

Here is a sample remote data store

package org.dominokit.domino.ui.sample.store;

import org.dominokit.domino.ui.sample.client.Formats;
import org.dominokit.domino.ui.sample.shared.store.CanLoadItems;
import org.dominokit.domino.ui.sample.shared.store.LoadContext;
import org.dominokit.domino.ui.datatable.events.SearchEvent;
import org.dominokit.domino.ui.datatable.events.SortEvent;
import org.dominokit.domino.ui.datatable.events.TableEvent;
import org.dominokit.domino.ui.datatable.events.TablePageChangeEvent;
import org.dominokit.domino.ui.datatable.model.Filter;
import org.dominokit.domino.ui.datatable.model.FilterTypes;
import org.dominokit.domino.ui.datatable.store.DataChangedEvent;
import org.dominokit.domino.ui.datatable.store.DataStore;
import org.dominokit.domino.ui.datatable.store.StoreDataChangeListener;
import org.dominokit.domino.ui.pagination.HasPagination;
import org.gwtproject.i18n.client.DateTimeFormat;

import java.util.*;

import static java.util.Objects.nonNull;
import static org.dominokit.domino.ui.datatable.events.SearchEvent.SEARCH_EVENT;
import static org.dominokit.domino.ui.datatable.events.SortEvent.SORT_EVENT;

public class RemoteDataStore&lt;T&gt; implements DataStore&lt;T&gt; {
    private List&lt;StoreDataChangeListener&lt;T&gt;&gt; listeners = new ArrayList&lt;&gt;();
    private HasPagination pagination;
    private CanLoadItems&lt;T&gt; uiHandlers;
    private String propertyName;
    private String sortDirection;
    private int activePage = 0;

    private Map&lt;String, String&gt; searchProperties = new HashMap&lt;&gt;();
    private List&lt;T&gt; items;

    public RemoteDataStore(CanLoadItems&lt;T&gt; uiHandlers) {
        this.uiHandlers = uiHandlers;
    }

    @Override
    public void onDataChanged(StoreDataChangeListener&lt;T&gt; dataChangeListener) {
        listeners.add(dataChangeListener);
    }

    @Override
    public void removeDataChangeListener(StoreDataChangeListener&lt;T&gt; dataChangeListener) {
        listeners.remove(dataChangeListener);
    }

    @Override
    public void load() {
        uiHandlers.load(getLoadContext(), loadResult -&gt; {
            this.items = loadResult.getResourceList();
            if (nonNull(loadResult.getPage())) {
                pagination.updatePagesByTotalCount(loadResult.getPage().getTotalElements(), loadResult.getPage().getSize());
                pagination.gotoPage(loadResult.getPage().getNumber() + 1, true);
            }
            fireUpdate();
        });
    }

    private LoadContext getLoadContext() {
        return new LoadContext(propertyName, sortDirection, activePage, searchProperties);
    }

    @Override
    public void handleEvent(TableEvent event) {
        switch (event.getType()) {
            case TablePageChangeEvent.PAGINATION_EVENT:
                activePage = pagination.activePage() - 1;
                load();
                break;
            case SORT_EVENT:
                propertyName = ((SortEvent&lt;?&gt;) event).getColumnConfig().getName();
                sortDirection = ((SortEvent&lt;?&gt;) event).getSortDirection().toString();
                load();
                break;
            case SEARCH_EVENT:
                searchProperties = new HashMap&lt;&gt;();
                List&lt;Filter&gt; filters = ((SearchEvent) event).getFilters();
                this.activePage = 0;
                for (Filter filter : filters) {
                    if (!filter.getValues().isEmpty()) {
                        if (filter.getType().equals(FilterTypes.DATE)) {
                            String longDate = filter.getValues().get(0);
                            String formattedDate = DateTimeFormat.getFormat(Formats.DEFAULT_DATE_PATTERN)
                                    .format(new Date(Long.parseLong(longDate)));
                            searchProperties.put(filter.getFieldName(), formattedDate);
                        } else {
                            searchProperties.put(filter.getFieldName(), filter.getValues().get(0));
                        }
                    }
                }
                load();
                break;
        }
    }

    private void fireUpdate() {
        listeners.forEach(dataChangeListener -&gt; dataChangeListener.onDataChanged(new DataChangedEvent&lt;&gt;(items, items.size())));
    }

    public HasPagination getPagination() {
        return pagination;
    }

    public void setPagination(HasPagination pagination) {
        this.pagination = pagination;
    }

    public int getActivePage() {
        return activePage;
    }

    public void load(int pageNumber) {
        this.activePage = pageNumber;
        load();
    }
}

Here we listen to the events and delegate the actual data load call to the uiHandlers.

Notice that implementing a remote data store depends on the server implementation, so there is no one remote data store that works for everyone, so use this as an example to implement one that works for your server.

答案2

得分: 0

以下是代码部分的翻译:

感谢您。 (我尚没有足够的积分来在第一个回答上添加评论 - 因此添加了一个新的回答)这是很棒的信息!以下是使用 GWT 异步进行服务器通信的实现,但它很容易可以在重写的加载方法中替换。

将表格添加到您的页面并告诉 RemoteDataService 如何从服务器加载信息。

SimplePaginationPlugin<Person> simplePaginationPlugin = new SimplePaginationPlugin<>(10);

TableConfig<Person> tableConfig = new TableConfig<>();
tableConfig
    .addColumn(ColumnConfig.<Person>create("id", "#").textAlign("right").asHeader()
        .setCellRenderer(cell -> TextNode.of(cell.getTableRow().getRecord().getId() + ""))
    .addColumn(ColumnConfig.<Person>create("status", "Status").textAlign("center").setCellRenderer(cell -> {
        if (cell.getTableRow().getRecord().isActive()) {
            return Style.of(Icons.ALL.check_circle()).setColor(Color.GREEN_DARKEN_3.getHex()).element();
        } else {
            return Style.of(Icons.ALL.highlight_off()).setColor(Color.RED_DARKEN_3.getHex()).element();
        }
    }))
    .addColumn(ColumnConfig.<Person>create("firstName", "Name")
        .setCellRenderer(cell -> TextNode.of(cell.getTableRow().getRecord().getName())));

tableConfig
    .setFixed(true)
    .addPlugin(new SortPlugin<>())
    .addPlugin(new HeaderBarPlugin<Person>("Demo table", "this a sample table with all features")
        .addActionElement(new HeaderBarPlugin.SearchTableAction<>()))
    .addPlugin(simplePaginationPlugin);
    ;

RemoteDataStore<Person> remoteDataStore = new RemoteDataStore<Person>() {

    @Override
    public void load() {
        greetingService.getPeople(getSearchProperties(), getSortPropertyName(), getSortPropertyDirection(),
            new AsyncCallback<ArrayList<Person>>() {

                @Override
                public void onSuccess(ArrayList<Person> result) {
                    loadNewItems(result);
                }

                @Override
                public void onFailure(Throwable caught) {
                    Window.alert("Failure");
                }
            });
    }
};

remoteDataStore.setPagination(simplePaginationPlugin.getSimplePagination());

DataTable<Person> table = new DataTable<>(tableConfig, remoteDataStore);
layout.getContentPanel()
    .appendChild(Card
        .create("BASIC TABLE", "By default a table will auto fit columns and allow custom cell content")
        .setCollapsible().appendChild(table).element());

// 在页面加载时加载表格数据
remoteDataStore.load();
import static java.util.Objects.nonNull;
import static org.dominokit.domino.ui.datatable.events.SearchEvent.SEARCH_EVENT;
import static org.dominokit.domino.ui.datatable.events.SortEvent.SORT_EVENT;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;

import org.dominokit.domino.ui.datatable.events.SearchEvent;
import org.dominokit.domino.ui.datatable.events.SortEvent;
import org.dominokit.domino.ui.datatable.events.TableEvent;
import org.dominokit.domino.ui.datatable.events.TablePageChangeEvent;
import org.dominokit.domino.ui.datatable.model.Filter;
import org.dominokit.domino.ui.datatable.model.FilterTypes;
import org.dominokit.domino.ui.datatable.store.DataChangedEvent;
import org.dominokit.domino.ui.datatable.store.DataStore;
import org.dominokit.domino.ui.datatable.store.StoreDataChangeListener;
import org.dominokit.domino.ui.pagination.HasPagination;
import org.gwtproject.i18n.client.DateTimeFormat;

public abstract class RemoteDataStore<T> implements DataStore<T> {
    private List<StoreDataChangeListener<T>> listeners = new ArrayList<>();
    private HasPagination pagination;
    private String sortPropertyName;
    private String sortPropertyDirection;

    private Entry<String, String> sortProperties;

    private int activePage = 0;

    private Map<String, String> searchProperties = new HashMap<>();
    private List<T> items;

    public RemoteDataStore() {
        super();
    }

    @Override
    public void onDataChanged(StoreDataChangeListener<T> dataChangeListener) {
        listeners.add(dataChangeListener);
    }

    @Override
    public void removeDataChangeListener(StoreDataChangeListener<T> dataChangeListener) {
        listeners.remove(dataChangeListener);
    }

    public void loadNewItems(List<T> newItems) {
        if (Objects.isNull(getItems())) {
            setItems(new ArrayList<T>());
        }

        getItems().clear();
        getItems().addAll(newItems);

        if (Objects.nonNull(pagination)) {
            pagination.updatePagesByTotalCount(getItems().size());
            pagination.gotoPage(1, true);
        }

        fireUpdate();
    }

    @Override
    public void handleEvent(TableEvent event) {
        switch (event.getType()) {
            case TablePageChangeEvent.PAGINATION_EVENT:
                setActivePage(pagination.activePage() - 1);
                fireUpdate();
                break;
            case SORT_EVENT:
                setSortPropertyName(((SortEvent<?>) event).getColumnConfig().getName());
                setSortPropertyDirection(((SortEvent<?>) event).getSortDirection().toString());
                load();
                break;
            case SEARCH_EVENT:
                setSearchProperties(new HashMap<>());
                List<Filter> filters = ((SearchEvent) event).getFilters();
                this.setActivePage(0);
                for (Filter filter : filters) {
                    if (!filter.getValues().isEmpty()) {
                        if (filter.getType().equals(FilterTypes.DATE)) {
                            String longDate = filter.getValues().get(0);
                            String formattedDate = DateTimeFormat.getFormat("dd-MM-yyyy HH:mm:ss")
                                    .format(new Date(Long.parseLong(longDate)));
                            getSearchProperties().put(filter.getFieldName(), formattedDate);
                        } else {
                            getSearchProperties().put(filter.getFieldName(), filter.getValues().get(0));
                        }
                    }
                }
                load();
                break;
        }
    }

    private void fireUpdate() {
        List<T> updateRecords = getRecordsForPage();
        listeners.forEach(dataChangeListener -> dataChangeListener.onDataChanged(new DataChangedEvent<>(updateRecords, updateRecords.size())));
    }

    private List<T> getRecordsForPage() {
        if (nonNull(getPagination())) {
            int fromIndex = getPagination().getPageSize() * (getPagination().activePage() - 1);
            int toIndex = Math.min(fromIndex + getPagination().getPageSize(), getItems().size());
            return new ArrayList<>(getItems().subList(fromIndex, toIndex));
        } else {
            return new ArrayList<>(getItems());
        }
    }

    public HasPagination getPagination() {
        return pagination;
    }

    public void setPagination(HasPagination pagination) {
        this.pagination = pagination;
    }

    public int getActivePage() {
        return activePage;
    }

    public void load(int pageNumber) {
        this.setActivePage(pageNumber);
        load();
    }

    public Map<String, String> getSearchProperties() {
        return searchProperties;
    }

    public void setSearchProperties(Map<String, String> searchProperties) {
        this

<details>
<summary>英文:</summary>



Thank you. (I don&#39;t have enough points yet to add a comment on the first answer - so adding a new answer) This is great information!  Below is the implementation with GWT Async for server communications - but it could easily be replaced in the overridden load method.  

Add the table to your page and tell the RemoteDataService how to load information from the server.
SimplePaginationPlugin&lt;Person&gt; simplePaginationPlugin = new SimplePaginationPlugin&lt;&gt;(10);
TableConfig&lt;Person&gt; tableConfig = new TableConfig&lt;&gt;();
tableConfig
.addColumn(ColumnConfig.&lt;Person&gt;create(&quot;id&quot;, &quot;#&quot;).textAlign(&quot;right&quot;).asHeader()
.setCellRenderer(cell -&gt; TextNode.of(cell.getTableRow().getRecord().getId() + &quot;&quot;)))
.addColumn(ColumnConfig.&lt;Person&gt;create(&quot;status&quot;, &quot;Status&quot;).textAlign(&quot;center&quot;).setCellRenderer(cell -&gt; {
if (cell.getTableRow().getRecord().isActive()) {
return Style.of(Icons.ALL.check_circle()).setColor(Color.GREEN_DARKEN_3.getHex()).element();
} else {
return Style.of(Icons.ALL.highlight_off()).setColor(Color.RED_DARKEN_3.getHex()).element();
}
}))
.addColumn(ColumnConfig.&lt;Person&gt;create(&quot;firstName&quot;, &quot;Name&quot;)
.setCellRenderer(cell -&gt; TextNode.of(cell.getTableRow().getRecord().getName())));
tableConfig
.setFixed(true)
.addPlugin(new SortPlugin&lt;&gt;())
.addPlugin(new HeaderBarPlugin&lt;Person&gt;(&quot;Demo table&quot;, &quot;this a sample table with all features&quot;)
.addActionElement(new HeaderBarPlugin.SearchTableAction&lt;&gt;()))
.addPlugin(simplePaginationPlugin);
;
RemoteDataStore&lt;Person&gt; remoteDataStore = new RemoteDataStore&lt;Person&gt;() {
@Override
public void load() {
greetingService.getPeople(getSearchProperties(), getSortPropertyName(), getSortPropertyDirection(),
new AsyncCallback&lt;ArrayList&lt;Person&gt;&gt;() {
@Override
public void onSuccess(ArrayList&lt;Person&gt; result) {
loadNewItems(result);
}
@Override
public void onFailure(Throwable caught) {
Window.alert(&quot;Failure&quot;);
}
});
}
};
remoteDataStore.setPagination(simplePaginationPlugin.getSimplePagination());
DataTable&lt;Person&gt; table = new DataTable&lt;&gt;(tableConfig, remoteDataStore);
layout.getContentPanel()
.appendChild(Card
.create(&quot;BASIC TABLE&quot;, &quot;By default a table will auto fit columns and allow custom cell content&quot;)
.setCollapsible().appendChild(table).element());
//Load the table data on page load
remoteDataStore.load();

import static java.util.Objects.nonNull;
import static org.dominokit.domino.ui.datatable.events.SearchEvent.SEARCH_EVENT;
import static org.dominokit.domino.ui.datatable.events.SortEvent.SORT_EVENT;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;

//import org.dominokit.domino.ui.sample.client.Formats;
import org.dominokit.domino.ui.datatable.events.SearchEvent;
import org.dominokit.domino.ui.datatable.events.SortEvent;
import org.dominokit.domino.ui.datatable.events.TableEvent;
import org.dominokit.domino.ui.datatable.events.TablePageChangeEvent;
import org.dominokit.domino.ui.datatable.model.Filter;
import org.dominokit.domino.ui.datatable.model.FilterTypes;
import org.dominokit.domino.ui.datatable.store.DataChangedEvent;
import org.dominokit.domino.ui.datatable.store.DataStore;
import org.dominokit.domino.ui.datatable.store.StoreDataChangeListener;
import org.dominokit.domino.ui.pagination.HasPagination;
import org.gwtproject.i18n.client.DateTimeFormat;

public abstract class RemoteDataStore<T> implements DataStore<T> {
private List<StoreDataChangeListener<T>> listeners = new ArrayList<>();
private HasPagination pagination;
private String sortPropertyName;
private String sortPropertyDirection;

private Entry&lt;String,String&gt; sortProperties;
private int activePage = 0;
private Map&lt;String, String&gt; searchProperties = new HashMap&lt;&gt;();
private List&lt;T&gt; items;
public RemoteDataStore() {
super();
}
@Override
public void onDataChanged(StoreDataChangeListener&lt;T&gt; dataChangeListener) {
listeners.add(dataChangeListener);
}
@Override
public void removeDataChangeListener(StoreDataChangeListener&lt;T&gt; dataChangeListener) {
listeners.remove(dataChangeListener);
}
public void loadNewItems(List&lt;T&gt; newItems)
{
if(Objects.isNull(getItems()))
{
setItems(new ArrayList&lt;T&gt;());
}
getItems().clear();
getItems().addAll(newItems);
if(Objects.nonNull(pagination))
{
pagination.updatePagesByTotalCount(getItems().size());
pagination.gotoPage(1, true);
}
fireUpdate();
}
@Override
public void handleEvent(TableEvent event) {
switch (event.getType()) {
case TablePageChangeEvent.PAGINATION_EVENT:
setActivePage(pagination.activePage() - 1);
fireUpdate();
break;
case SORT_EVENT:
setSortPropertyName(((SortEvent&lt;?&gt;) event).getColumnConfig().getName());
setSortPropertyDirection(((SortEvent&lt;?&gt;) event).getSortDirection().toString());
load();
break;
case SEARCH_EVENT:
setSearchProperties(new HashMap&lt;&gt;());
List&lt;Filter&gt; filters = ((SearchEvent) event).getFilters();
this.setActivePage(0);
for (Filter filter : filters) {
if (!filter.getValues().isEmpty()) {
if (filter.getType().equals(FilterTypes.DATE)) {
String longDate = filter.getValues().get(0);
String formattedDate = DateTimeFormat.getFormat(&quot;dd-MM-yyyy HH:mm:ss&quot;)
.format(new Date(Long.parseLong(longDate)));
getSearchProperties().put(filter.getFieldName(), formattedDate);
} else {
getSearchProperties().put(filter.getFieldName(), filter.getValues().get(0));
}
}
}
load();
break;
}
}
private void fireUpdate() {
List&lt;T&gt; updateRecords = getRecordsForPage();
listeners.forEach(dataChangeListener -&gt; dataChangeListener.onDataChanged(new DataChangedEvent&lt;&gt;(updateRecords, updateRecords.size())));
}
private List&lt;T&gt; getRecordsForPage() {
if (nonNull(getPagination())) {
int fromIndex = getPagination().getPageSize() * (getPagination().activePage() - 1);
int toIndex = Math.min(fromIndex + getPagination().getPageSize(), getItems().size());
return new ArrayList&lt;&gt;(getItems().subList(fromIndex, toIndex));
} else {
return new ArrayList&lt;&gt;(getItems());
}
}
public HasPagination getPagination() {
return pagination;
}
public void setPagination(HasPagination pagination) {
this.pagination = pagination;
}
public int getActivePage() {
return activePage;
}
public void load(int pageNumber) {
this.setActivePage(pageNumber);
load();
}
public Map&lt;String, String&gt; getSearchProperties() {
return searchProperties;
}
public void setSearchProperties(Map&lt;String, String&gt; searchProperties) {
this.searchProperties = searchProperties;
}
public void setActivePage(int activePage) {
this.activePage = activePage;
}
public Entry&lt;String,String&gt; getSortProperties() {
return sortProperties;
}
public void setSortProperties(Entry&lt;String,String&gt; sortProperties) {
this.sortProperties = sortProperties;
}
public String getSortPropertyName() {
return sortPropertyName;
}
public void setSortPropertyName(String sortPropertyName) {
this.sortPropertyName = sortPropertyName;
}
public String getSortPropertyDirection() {
return sortPropertyDirection;
}
public void setSortPropertyDirection(String sortPropertyDirection) {
this.sortPropertyDirection = sortPropertyDirection;
}
public List&lt;T&gt; getItems() {
return items;
}
public void setItems(List&lt;T&gt; items) {
this.items = items;
}

}


@SuppressWarnings("serial")
public class Person implements Serializable {

private int id;
private String name;
private boolean active;
public Person() {
}
public Person(int id, String name, boolean active) {
this.id = id;
this.name = name;
this.active = active;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}

}


</details>

huangapple
  • 本文由 发表于 2023年4月4日 07:36:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/75924457.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定