Revision history [back]

click to hide/show revision 1
initial version

asked 2020-10-01 17:31:19 +0800

suzuha gravatar image suzuha

Reload Listbox After Filter In A LoadOnDemand Model

Hello,

The szenario:

Currently I'm trying to implement a Listbox/Model to load hughe Data with paging in MVVM (this works reather well after looking at some tech talks).

The code thus far is working fine! The Listmodel works and loads Items on each page switch and puts them in a cache. The items are also in the Listbox.

The problem:

What I don't get to work is the reset of the model + Listbox. When I change the value in one of the search Textboxes the search method for the specific box is called and the correct db query is used. But the Listbox won't update the entries to the new model.

I tried two approaches in the methods searchForCode() and searchForDisplayText() in ViewModel class (see below). With both approaches the displayed elements won't change. If I also reload the totalSize of the ListModel sometimes when I write in a textbox, delete it and rewrite it the Listbox content changes.

Any ideas how I can reload the listbox content?

Here is the ZUL Code of the Listbox:

<groupbox hflex="1" vflex="1" closable="false" mold="3d">
                    <caption label="Test"/>
                    <vlayout hflex="1" vflex="1">
                        <hlayout hflex="1" height="60px">
                            <label value="Code: " />
                            <textbox value="@bind(vm.searchCode)" onChanging="@command('searchForCode')" width="200px" />
                            <label value="Diagnosetext: " />
                            <textbox value="@bind(vm.searchDisplayText)" onChanging="@command('searchForDisplayText')" width="200px" />
                        </hlayout>
                        <listbox id="lbPaging" mold="paging" model="@bind(vm.model)" emptyMessage="no entries found"
                                 pageSize="10">
                            <listhead>
                                <listheader label="Code"/>
                                <listheader label="Wert"/>
                                <listheader label="Orig."/>
                            </listhead>
                            <template name="model">
                                <listitem>
                                    <listcell>
                                        <label value="@load(each.code)"/>
                                    </listcell>
                                    <listcell>
                                        <label value="@load(each.displayText)"/>
                                    </listcell>
                                </listitem>
                            </template>
                        </listbox>
                    </vlayout>
                </groupbox>

And this is my ListModel:

public abstract class PagingListModelList<T> extends AbstractListModel {
    private final int pageSize;

    private Integer listTotalSize = null;
    private final Map<Integer, List<T>> pageCache = new HashMap<>();

    public PagingListModelList(int pageSize) {
        super();
        this.pageSize = pageSize;
    }

    @Override
    public T getElementAt(int index) {
        int pageIndex = index / pageSize;
        List<T> pageElements = pageCache.get(pageIndex);
        if (pageElements == null) {
            pageElements = loadPageFromDB(pageIndex * pageSize, pageSize);
            pageCache.put(pageIndex, pageElements);
        }

        return pageElements != null ? pageElements.get(index % pageSize) : null;
    }

    @Override
    public int getSize() {
        if (listTotalSize == null) {
            listTotalSize = loadListTotalSize();
        }
        return listTotalSize;
    }

    public void clearCaches() {
        listTotalSize = null;
        pageCache.clear();
    }

    protected abstract Integer loadListTotalSize();

    protected abstract List<T> loadPageFromDB(int startIndex, int size);
}

And finally here the ViewModel:

public class MyViewModel {
    private int pageSize = 10;

    private String searchCode;
    private String searchDisplayText;

    private PagingListModelList<CodeDisplay> model;
    @Wire("#lbPaging")
    private Listbox lbPaging;


    private boolean isSearchCode = false;
    private boolean isSearchDisplayText = false;

    @Init
    public void init() {
        model = new PagingListModelList<CodeDisplay>(pageSize) {
            @Override
            protected Integer loadListTotalSize() {
                int count = 0;
                try (Session hb_session = HibernateUtil.getSessionFactory().openSession()) {
                    Long counter = 0L;
                    if (isSearchCode) {
                        counter = hb_session.createQuery("Select count(cv) From CodeValue cv where cv.code = 'codesystem' and cv.shortCode like :code ", Long.class).setParameter("code", "%"+searchCode+"%").uniqueResult();
                    } else if (isSearchDisplayText) {
                        counter = hb_session.createQuery("Select count(cv) From CodeValue cv where cv.code = 'codesystem' and cv.displayText like :display ", Long.class).setParameter("display", "%"+searchDisplayText+"%").uniqueResult();
                    } else {
                        counter = hb_session.createQuery("Select count(cv) From CodeValue cv where cv.code = 'codesystem' ", Long.class).uniqueResult();
                    }
                    count = counter.intValue();
                }
                return count;
            }

            @Override
            protected List<CodeDisplay> loadPageFromDB(int startIndex, int size) {
                List<CodeDisplay> currentPageData = new LinkedList<>();
                try (Session hb_session = HibernateUtil.getSessionFactory().openSession()) {
                    if (isSearchCode) {
                        currentPageData = hb_session.createQuery("Select new org.test.model.CodeDisplay(cv.shortCode, cv.displayText)  From DomainValue cv where cv.code = 'codesystem' and cv.shortCode like :code order by cv.shortCode asc", CodeDisplay.class).setParameter("code", "%"+searchCode+"%").setFirstResult(startIndex).setMaxResults(size).list();
                    } else if (isSearchDisplayText) {
                        currentPageData = hb_session.createQuery("Select new org.test.model.CodeDisplay(cv.shortCode, cv.displayText)  From DomainValue cv where cv.code = 'codesystem' and cv.displayText like :display order by cv.shortCode asc", CodeDisplay.class).setParameter("display", "%"+searchDisplayText+"%").setFirstResult(startIndex).setMaxResults(size).list();
                    } else {
                        currentPageData = hb_session.createQuery("Select new org.test.model.CodeDisplay(cv.shortCode, cv.displayText)  From DomainValue cv where cv.code = 'codesystem' order by cv.shortCode asc", CodeDisplay.class).setFirstResult(startIndex).setMaxResults(size).list();
                    }
                }
                return currentPageData;
            }
        };
    }

    @AfterCompose
    public void afterCompose(@ContextParam(ContextType.VIEW) Component view) {
        Selectors.wireComponents(view, this, false);
    }

    @Command
    @NotifyChange("searchForCode")
    public void searchForCode() {
        if(searchDisplayText != null) {
            searchDisplayText = null;
            isSearchDisplayText = false;
        }

        isSearchCode = searchCode != null && !searchCode.isEmpty();
        model.clearCaches();
        model.loadPageFromDB(0,pageSize);
        lbPaging.setModel(new ListModelList<CodeDisplay>());
        lbPaging.setModel(model);
    }

    @Command
    @NotifyChange("searchForDisplayText")
    public void searchForDisplayText() {
        if(searchCode != null) {
            searchCode = null;
            isSearchCode = false;
        }

        isSearchDisplayText = searchDisplayText != null && !searchDisplayText.isEmpty();

        model.clearCaches();
        model.loadPageFromDB(0,pageSize);
        lbPaging.invalidate();
    }

    public PagingListModelList<CodeDisplay> getModel() {
        return model;
    }

    public String getSearchCode() {
        return searchCode;
    }

    public void setSearchCode(String searchCode) {
        this.searchCode = searchCode;
    }

    public String getSearchDisplayText() {
        return searchDisplayText;
    }

    public void setSearchDisplayText(String searchDisplayText) {
        this.searchDisplayText = searchDisplayText;
    }
}

Reload Listbox After Filter In A LoadOnDemand Model

Hello,

The szenario:

Currently I'm trying to implement a Listbox/Model to load hughe Data with paging in MVVM (this works reather well after looking at some tech talks).

The code thus far is working fine! The Listmodel works and loads Items on each page switch and puts them in a cache. The items are also in the Listbox.

The problem:

What I don't get to work is the reset of the model + Listbox. When I change the value in one of the search Textboxes the search method for the specific box is called and the correct db query is used. But the Listbox won't update the entries to the new model.

I tried two approaches in the methods searchForCode() and searchForDisplayText() in ViewModel class (see below). With both approaches the displayed elements won't change. If I also reload the totalSize of the ListModel sometimes when I write in a textbox, delete it and rewrite it the Listbox content changes.

Any ideas how I can reload the listbox content?

Here is the ZUL Code of the Listbox:

<groupbox hflex="1" vflex="1" closable="false" mold="3d">
                    <caption label="Test"/>
                    <vlayout hflex="1" vflex="1">
                        <hlayout hflex="1" height="60px">
                            <label value="Code: " />
                            <textbox value="@bind(vm.searchCode)" onChanging="@command('searchForCode')" width="200px" />
                            <label value="Diagnosetext: " />
                            <textbox value="@bind(vm.searchDisplayText)" onChanging="@command('searchForDisplayText')" width="200px" />
                        </hlayout>
                        <listbox id="lbPaging" mold="paging" model="@bind(vm.model)" emptyMessage="no entries found"
                                 pageSize="10">
                            <listhead>
                                <listheader label="Code"/>
                                <listheader label="Wert"/>
                                <listheader label="Orig."/>
                            </listhead>
                            <template name="model">
                                <listitem>
                                    <listcell>
                                        <label value="@load(each.code)"/>
                                    </listcell>
                                    <listcell>
                                        <label value="@load(each.displayText)"/>
                                    </listcell>
                                </listitem>
                            </template>
                        </listbox>
                    </vlayout>
                </groupbox>

And this is my ListModel:

public abstract class PagingListModelList<T> extends AbstractListModel {
    private final int pageSize;

    private Integer listTotalSize = null;
    private final Map<Integer, List<T>> pageCache = new HashMap<>();

    public PagingListModelList(int pageSize) {
        super();
        this.pageSize = pageSize;
    }

    @Override
    public T getElementAt(int index) {
        int pageIndex = index / pageSize;
        List<T> pageElements = pageCache.get(pageIndex);
        if (pageElements == null) {
            pageElements = loadPageFromDB(pageIndex * pageSize, pageSize);
            pageCache.put(pageIndex, pageElements);
        }

        return pageElements != null ? pageElements.get(index % pageSize) : null;
    }

    @Override
    public int getSize() {
        if (listTotalSize == null) {
            listTotalSize = loadListTotalSize();
        }
        return listTotalSize;
    }

    public void clearCaches() {
        listTotalSize = null;
        pageCache.clear();
    }

    protected abstract Integer loadListTotalSize();

    protected abstract List<T> loadPageFromDB(int startIndex, int size);
}

And finally here the ViewModel:

public class MyViewModel {
    private int pageSize = 10;

    private String searchCode;
    private String searchDisplayText;

    private PagingListModelList<CodeDisplay> model;
    @Wire("#lbPaging")
    private Listbox lbPaging;


    private boolean isSearchCode = false;
    private boolean isSearchDisplayText = false;

    @Init
    public void init() {
        model = new PagingListModelList<CodeDisplay>(pageSize) {
            @Override
            protected Integer loadListTotalSize() {
                int count = 0;
                try (Session hb_session = HibernateUtil.getSessionFactory().openSession()) {
                    Long counter = 0L;
                    if (isSearchCode) {
                        counter = hb_session.createQuery("Select count(cv) From CodeValue cv where cv.code = 'codesystem' and cv.shortCode like :code ", Long.class).setParameter("code", "%"+searchCode+"%").uniqueResult();
                    } else if (isSearchDisplayText) {
                        counter = hb_session.createQuery("Select count(cv) From CodeValue cv where cv.code = 'codesystem' and cv.displayText like :display ", Long.class).setParameter("display", "%"+searchDisplayText+"%").uniqueResult();
                    } else {
                        counter = hb_session.createQuery("Select count(cv) From CodeValue cv where cv.code = 'codesystem' ", Long.class).uniqueResult();
                    }
                    count = counter.intValue();
                }
                return count;
            }

            @Override
            protected List<CodeDisplay> loadPageFromDB(int startIndex, int size) {
                List<CodeDisplay> currentPageData = new LinkedList<>();
                try (Session hb_session = HibernateUtil.getSessionFactory().openSession()) {
                    if (isSearchCode) {
                        currentPageData = hb_session.createQuery("Select new org.test.model.CodeDisplay(cv.shortCode, cv.displayText)  From DomainValue CodeValue cv where cv.code = 'codesystem' and cv.shortCode like :code order by cv.shortCode asc", CodeDisplay.class).setParameter("code", "%"+searchCode+"%").setFirstResult(startIndex).setMaxResults(size).list();
                    } else if (isSearchDisplayText) {
                        currentPageData = hb_session.createQuery("Select new org.test.model.CodeDisplay(cv.shortCode, cv.displayText)  From DomainValue CodeValue cv where cv.code = 'codesystem' and cv.displayText like :display order by cv.shortCode asc", CodeDisplay.class).setParameter("display", "%"+searchDisplayText+"%").setFirstResult(startIndex).setMaxResults(size).list();
                    } else {
                        currentPageData = hb_session.createQuery("Select new org.test.model.CodeDisplay(cv.shortCode, cv.displayText)  From DomainValue CodeValue cv where cv.code = 'codesystem' order by cv.shortCode asc", CodeDisplay.class).setFirstResult(startIndex).setMaxResults(size).list();
                    }
                }
                return currentPageData;
            }
        };
    }

    @AfterCompose
    public void afterCompose(@ContextParam(ContextType.VIEW) Component view) {
        Selectors.wireComponents(view, this, false);
    }

    @Command
    @NotifyChange("searchForCode")
    public void searchForCode() {
        if(searchDisplayText != null) {
            searchDisplayText = null;
            isSearchDisplayText = false;
        }

        isSearchCode = searchCode != null && !searchCode.isEmpty();
        model.clearCaches();
        model.loadPageFromDB(0,pageSize);
        lbPaging.setModel(new ListModelList<CodeDisplay>());
        lbPaging.setModel(model);
    }

    @Command
    @NotifyChange("searchForDisplayText")
    public void searchForDisplayText() {
        if(searchCode != null) {
            searchCode = null;
            isSearchCode = false;
        }

        isSearchDisplayText = searchDisplayText != null && !searchDisplayText.isEmpty();

        model.clearCaches();
        model.loadPageFromDB(0,pageSize);
        lbPaging.invalidate();
model.loadListTotalSize();
    model.loadPageFromDB(0,pageSize);
    lbPaging.setActivePage(0);
    lbPaging.setModel(new ListModelList<CodeDisplay>());
    lbPaging.setModel(model);
    }

    public PagingListModelList<CodeDisplay> getModel() {
        return model;
    }

    public String getSearchCode() {
        return searchCode;
    }

    public void setSearchCode(String searchCode) {
        this.searchCode = searchCode;
    }

    public String getSearchDisplayText() {
        return searchDisplayText;
    }

    public void setSearchDisplayText(String searchDisplayText) {
        this.searchDisplayText = searchDisplayText;
    }
}

Reload Listbox After Filter In A LoadOnDemand Model

Hello,

The szenario:

Currently I'm trying to implement a Listbox/Model to load hughe Data with paging in MVVM (this works reather well after looking at some tech talks).

The code thus far is working fine! The Listmodel works and loads Items on each page switch and puts them in a cache. The items are also in the Listbox.

The problem:

What I don't get to work is the reset of the model + Listbox. When I change the value in one of the search Textboxes the search method for the specific box is called and the correct db query is used. But the Listbox won't update the entries to the new model.

I tried two approaches in the methods searchForCode() and searchForDisplayText() in ViewModel class (see below). With both approaches the displayed elements won't change. If I also reload the totalSize of the ListModel sometimes when I write in a textbox, delete it and rewrite it the Listbox content changes.

Any ideas how I can reload the listbox content?

Here is the ZUL Code of the Listbox:

<groupbox hflex="1" vflex="1" closable="false" mold="3d">
                    <caption label="Test"/>
                    <vlayout hflex="1" vflex="1">
                        <hlayout hflex="1" height="60px">
                            <label value="Code: " />
                            <textbox value="@bind(vm.searchCode)" onChanging="@command('searchForCode')" width="200px" />
                            <label value="Diagnosetext: " />
                            <textbox value="@bind(vm.searchDisplayText)" onChanging="@command('searchForDisplayText')" width="200px" />
                        </hlayout>
                        <listbox id="lbPaging" mold="paging" model="@bind(vm.model)" emptyMessage="no entries found"
                                 pageSize="10">
                            <listhead>
                                <listheader label="Code"/>
                                <listheader label="Wert"/>
                                <listheader label="Orig."/>
                            </listhead>
                            <template name="model">
                                <listitem>
                                    <listcell>
                                        <label value="@load(each.code)"/>
                                    </listcell>
                                    <listcell>
                                        <label value="@load(each.displayText)"/>
                                    </listcell>
                                </listitem>
                            </template>
                        </listbox>
                    </vlayout>
                </groupbox>

And this is my ListModel:

public abstract class PagingListModelList<T> extends AbstractListModel {
    private final int pageSize;

    private Integer listTotalSize = null;
    private final Map<Integer, List<T>> pageCache = new HashMap<>();

    public PagingListModelList(int pageSize) {
        super();
        this.pageSize = pageSize;
    }

    @Override
    public T getElementAt(int index) {
        int pageIndex = index / pageSize;
        List<T> pageElements = pageCache.get(pageIndex);
        if (pageElements == null) {
            pageElements = loadPageFromDB(pageIndex * pageSize, pageSize);
            pageCache.put(pageIndex, pageElements);
        }

        return pageElements != null ? pageElements.get(index % pageSize) : null;
    }

    @Override
    public int getSize() {
        if (listTotalSize == null) {
            listTotalSize = loadListTotalSize();
        }
        return listTotalSize;
    }

    public void clearCaches() {
        listTotalSize = null;
        pageCache.clear();
        loadListTotalSize();
        loadPageFromDB(0,pageSize);
        fireEvent(ListDataEvent.CONTENTS_CHANGED, -1, -1);
    }

    protected abstract Integer loadListTotalSize();

    protected abstract List<T> loadPageFromDB(int startIndex, int size);
}

And finally here the ViewModel:

public class MyViewModel {
    private int pageSize = 10;

    private String searchCode;
    private String searchDisplayText;

    private PagingListModelList<CodeDisplay> model;
    @Wire("#lbPaging")
    private Listbox lbPaging;


    private boolean isSearchCode = false;
    private boolean isSearchDisplayText = false;

    @Init
    public void init() {
        model = new PagingListModelList<CodeDisplay>(pageSize) {
            @Override
            protected Integer loadListTotalSize() {
                int count = 0;
                try (Session hb_session = HibernateUtil.getSessionFactory().openSession()) {
                    Long counter = 0L;
                    if (isSearchCode) {
                        counter = hb_session.createQuery("Select count(cv) From CodeValue cv where cv.code = 'codesystem' and cv.shortCode like :code ", Long.class).setParameter("code", "%"+searchCode+"%").uniqueResult();
                    } else if (isSearchDisplayText) {
                        counter = hb_session.createQuery("Select count(cv) From CodeValue cv where cv.code = 'codesystem' and cv.displayText like :display ", Long.class).setParameter("display", "%"+searchDisplayText+"%").uniqueResult();
                    } else {
                        counter = hb_session.createQuery("Select count(cv) From CodeValue cv where cv.code = 'codesystem' ", Long.class).uniqueResult();
                    }
                    count = counter.intValue();
                }
                return count;
            }

            @Override
            protected List<CodeDisplay> loadPageFromDB(int startIndex, int size) {
                List<CodeDisplay> currentPageData = new LinkedList<>();
                try (Session hb_session = HibernateUtil.getSessionFactory().openSession()) {
                    if (isSearchCode) {
                        currentPageData = hb_session.createQuery("Select new org.test.model.CodeDisplay(cv.shortCode, cv.displayText)  From CodeValue cv where cv.code = 'codesystem' and cv.shortCode like :code order by cv.shortCode asc", CodeDisplay.class).setParameter("code", "%"+searchCode+"%").setFirstResult(startIndex).setMaxResults(size).list();
                    } else if (isSearchDisplayText) {
                        currentPageData = hb_session.createQuery("Select new org.test.model.CodeDisplay(cv.shortCode, cv.displayText)  From CodeValue cv where cv.code = 'codesystem' and cv.displayText like :display order by cv.shortCode asc", CodeDisplay.class).setParameter("display", "%"+searchDisplayText+"%").setFirstResult(startIndex).setMaxResults(size).list();
                    } else {
                        currentPageData = hb_session.createQuery("Select new org.test.model.CodeDisplay(cv.shortCode, cv.displayText)  From CodeValue cv where cv.code = 'codesystem' order by cv.shortCode asc", CodeDisplay.class).setFirstResult(startIndex).setMaxResults(size).list();
                    }
                }
                return currentPageData;
            }
        };
    }

    @AfterCompose
    public void afterCompose(@ContextParam(ContextType.VIEW) Component view) {
        Selectors.wireComponents(view, this, false);
    }

    @Command
    @NotifyChange("searchForCode")
    public void searchForCode() {
        if(searchDisplayText != null) {
            searchDisplayText = null;
         isSearchDisplayText = false;
        }

        isSearchCode = true;
        searchCode != null && !searchCode.isEmpty();
= event.getValue();
        model.clearCaches();
        model.loadPageFromDB(0,pageSize);
        lbPaging.setModel(new ListModelList<CodeDisplay>());
        lbPaging.setModel(model);
    }

    @Command
    @NotifyChange("searchForDisplayText")
    public void searchForDisplayText() {
        if(searchCode != null) {
            searchCode = null;
         isSearchCode = false;
        }

        isSearchDisplayText = true;
        searchDisplayText != null && !searchDisplayText.isEmpty();

= event.getValue();
        model.clearCaches();
        model.loadPageFromDB(0,pageSize);
    model.loadListTotalSize();
    model.loadPageFromDB(0,pageSize);
    lbPaging.setActivePage(0);
    lbPaging.setModel(new ListModelList<CodeDisplay>());
    lbPaging.setModel(model);
    }

    public PagingListModelList<CodeDisplay> getModel() {
        return model;
    }

    public String getSearchCode() {
        return searchCode;
    }

    public void setSearchCode(String searchCode) {
        this.searchCode = searchCode;
    }

    public String getSearchDisplayText() {
        return searchDisplayText;
    }

    public void setSearchDisplayText(String searchDisplayText) {
        this.searchDisplayText = searchDisplayText;
    }
}

Reload Listbox After Filter In A LoadOnDemand Model

Hello,

The szenario:

Currently I'm trying to implement a Listbox/Model to load hughe Data with paging in MVVM (this works reather well after looking at some tech talks).

The code thus far is working fine! The Listmodel works and loads Items on each page switch and puts them in a cache. The items are also in the Listbox.

The problem:

What I don't get to work is the reset of the model + Listbox. When I change the value in one of the search Textboxes the search method for the specific box is called and the correct db query is used. But the Listbox won't update the entries to the new model.

I tried two approaches in the methods searchForCode() and searchForDisplayText() in ViewModel class (see below). With both approaches the displayed elements won't change. If I also reload the totalSize of the ListModel sometimes when I write in a textbox, delete it and rewrite it the Listbox content changes.

Any ideas how I can reload the listbox content?

Here is the ZUL Code of the Listbox:

<groupbox hflex="1" vflex="1" closable="false" mold="3d">
                    <caption label="Test"/>
                    <vlayout hflex="1" vflex="1">
                        <hlayout hflex="1" height="60px">
                            <label value="Code: " />
                            <textbox onChanging="@command('searchForCode')" width="200px" />
                            <label value="Diagnosetext: value="Display text: " />
                            <textbox onChanging="@command('searchForDisplayText')" width="200px" />
                        </hlayout>
                        <listbox id="lbPaging" mold="paging" model="@bind(vm.model)" emptyMessage="no entries found"
                                 pageSize="10">
                            <listhead>
                                <listheader label="Code"/>
                                <listheader label="Wert"/>
                                <listheader label="Orig."/>
                            </listhead>
                            <template name="model">
                                <listitem>
                                    <listcell>
                                        <label value="@load(each.code)"/>
                                    </listcell>
                                    <listcell>
                                        <label value="@load(each.displayText)"/>
                                    </listcell>
                                </listitem>
                            </template>
                        </listbox>
                    </vlayout>
                </groupbox>

And this is my ListModel:

public abstract class PagingListModelList<T> extends AbstractListModel {
    private final int pageSize;

    private Integer listTotalSize = null;
    private final Map<Integer, List<T>> pageCache = new HashMap<>();

    public PagingListModelList(int pageSize) {
        super();
        this.pageSize = pageSize;
    }

    @Override
    public T getElementAt(int index) {
        int pageIndex = index / pageSize;
        List<T> pageElements = pageCache.get(pageIndex);
        if (pageElements == null) {
            pageElements = loadPageFromDB(pageIndex * pageSize, pageSize);
            pageCache.put(pageIndex, pageElements);
        }

        return pageElements != null ? pageElements.get(index % pageSize) : null;
    }

    @Override
    public int getSize() {
        if (listTotalSize == null) {
            listTotalSize = loadListTotalSize();
        }
        return listTotalSize;
    }

    public void clearCaches() {
        listTotalSize = null;
        pageCache.clear();
        loadListTotalSize();
        loadPageFromDB(0,pageSize);
        fireEvent(ListDataEvent.CONTENTS_CHANGED, -1, -1);
    }

    protected abstract Integer loadListTotalSize();

    protected abstract List<T> loadPageFromDB(int startIndex, int size);
}

And finally here the ViewModel:

public class MyViewModel {
    private int pageSize = 10;

    private String searchCode;
    private String searchDisplayText;

    private PagingListModelList<CodeDisplay> model;
    @Wire("#lbPaging")
    private Listbox lbPaging;


    private boolean isSearchCode = false;
    private boolean isSearchDisplayText = false;

    @Init
    public void init() {
        model = new PagingListModelList<CodeDisplay>(pageSize) {
            @Override
            protected Integer loadListTotalSize() {
                int count = 0;
                try (Session hb_session = HibernateUtil.getSessionFactory().openSession()) {
                    Long counter = 0L;
                    if (isSearchCode) {
                        counter = hb_session.createQuery("Select count(cv) From CodeValue cv where cv.code = 'codesystem' and cv.shortCode like :code ", Long.class).setParameter("code", "%"+searchCode+"%").uniqueResult();
                    } else if (isSearchDisplayText) {
                        counter = hb_session.createQuery("Select count(cv) From CodeValue cv where cv.code = 'codesystem' and cv.displayText like :display ", Long.class).setParameter("display", "%"+searchDisplayText+"%").uniqueResult();
                    } else {
                        counter = hb_session.createQuery("Select count(cv) From CodeValue cv where cv.code = 'codesystem' ", Long.class).uniqueResult();
                    }
                    count = counter.intValue();
                }
                return count;
            }

            @Override
            protected List<CodeDisplay> loadPageFromDB(int startIndex, int size) {
                List<CodeDisplay> currentPageData = new LinkedList<>();
                try (Session hb_session = HibernateUtil.getSessionFactory().openSession()) {
                    if (isSearchCode) {
                        currentPageData = hb_session.createQuery("Select new org.test.model.CodeDisplay(cv.shortCode, cv.displayText)  From CodeValue cv where cv.code = 'codesystem' and cv.shortCode like :code order by cv.shortCode asc", CodeDisplay.class).setParameter("code", "%"+searchCode+"%").setFirstResult(startIndex).setMaxResults(size).list();
                    } else if (isSearchDisplayText) {
                        currentPageData = hb_session.createQuery("Select new org.test.model.CodeDisplay(cv.shortCode, cv.displayText)  From CodeValue cv where cv.code = 'codesystem' and cv.displayText like :display order by cv.shortCode asc", CodeDisplay.class).setParameter("display", "%"+searchDisplayText+"%").setFirstResult(startIndex).setMaxResults(size).list();
                    } else {
                        currentPageData = hb_session.createQuery("Select new org.test.model.CodeDisplay(cv.shortCode, cv.displayText)  From CodeValue cv where cv.code = 'codesystem' order by cv.shortCode asc", CodeDisplay.class).setFirstResult(startIndex).setMaxResults(size).list();
                    }
                }
                return currentPageData;
            }
        };
    }

    @AfterCompose
    public void afterCompose(@ContextParam(ContextType.VIEW) Component view) {
        Selectors.wireComponents(view, this, false);
    }

    @Command
    @NotifyChange("searchForCode")
    public void searchForCode() searchForCode(@ContextParam(ContextType.TRIGGER_EVENT) InputEvent event) {
        searchDisplayText = null;
        isSearchDisplayText = false;
        isSearchCode = true;
        searchCode = event.getValue();
        model.clearCaches();
    }

    @Command
    @NotifyChange("searchForDisplayText")
    public void searchForDisplayText() searchForDisplayText(@ContextParam(ContextType.TRIGGER_EVENT) InputEvent event) {
        searchCode = null;
        isSearchCode = false;
        isSearchDisplayText = true;
        searchDisplayText = event.getValue();
        model.clearCaches();
    }

    public PagingListModelList<CodeDisplay> getModel() {
        return model;
    }

    public String getSearchCode() {
        return searchCode;
    }

    public void setSearchCode(String searchCode) {
        this.searchCode = searchCode;
    }

    public String getSearchDisplayText() {
        return searchDisplayText;
    }

    public void setSearchDisplayText(String searchDisplayText) {
        this.searchDisplayText = searchDisplayText;
    }
}

Reload Listbox After Filter In A LoadOnDemand Model

Hello,

The szenario:

Currently I'm trying to implement a Listbox/Model to load hughe Data with paging in MVVM (this works reather well after looking at some tech talks).

The code thus far is working fine! The Listmodel works and loads Items on each page switch and puts them in a cache. The items are also in the Listbox.

The problem:

What I don't get to work is the reset of the model + Listbox. When I change the value in one of the search Textboxes the search method for the specific box is called and the correct db query is used. But the Listbox won't update the entries to the new model.

I tried two approaches in the methods searchForCode() and searchForDisplayText() in ViewModel class (see below). With both approaches the displayed elements won't change. If I also reload the totalSize of the ListModel sometimes when I write in a textbox, delete it and rewrite it the Listbox content changes.

Any ideas how I can reload the listbox content?

Here is the ZUL Code of the Listbox:

<groupbox hflex="1" vflex="1" closable="false" mold="3d">
                    <caption label="Test"/>
                    <vlayout hflex="1" vflex="1">
                        <hlayout hflex="1" height="60px">
                            <label value="Code: " />
                            <textbox onChanging="@command('searchForCode')" width="200px" />
                            <label value="Display text: " />
                            <textbox onChanging="@command('searchForDisplayText')" width="200px" />
                        </hlayout>
                        <listbox id="lbPaging" mold="paging" model="@bind(vm.model)" emptyMessage="no entries found"
                                 pageSize="10">
                            <listhead>
                                <listheader label="Code"/>
                                <listheader label="Wert"/>
                                <listheader label="Orig."/>
                            </listhead>
                            <template name="model">
                                <listitem>
                                    <listcell>
                                        <label value="@load(each.code)"/>
                                    </listcell>
                                    <listcell>
                                        <label value="@load(each.displayText)"/>
                                    </listcell>
                                </listitem>
                            </template>
                        </listbox>
                    </vlayout>
                </groupbox>

And this is my ListModel:

public abstract class PagingListModelList<T> extends AbstractListModel {
    private final int pageSize;

    private Integer listTotalSize = null;
    private final Map<Integer, List<T>> pageCache = new HashMap<>();

    public PagingListModelList(int pageSize) {
        super();
        this.pageSize = pageSize;
    }

    @Override
    public T getElementAt(int index) {
        int pageIndex = index / pageSize;
        List<T> pageElements = pageCache.get(pageIndex);
        if (pageElements == null) {
            pageElements = loadPageFromDB(pageIndex * pageSize, pageSize);
            pageCache.put(pageIndex, pageElements);
        }

        return pageElements != null ? pageElements.get(index % pageSize) : null;
    }

    @Override
    public int getSize() {
        if (listTotalSize == null) {
            listTotalSize = loadListTotalSize();
        }
        return listTotalSize;
    }

    public void clearCaches() {
        listTotalSize = null;
        pageCache.clear();
        loadListTotalSize();
        loadPageFromDB(0,pageSize);
pageCache.put(0, loadPageFromDB(0, pageSize));
        fireEvent(ListDataEvent.CONTENTS_CHANGED, -1, -1);
    }

    protected abstract Integer loadListTotalSize();

    protected abstract List<T> loadPageFromDB(int startIndex, int size);
}

And finally here the ViewModel:

public class MyViewModel {
    private int pageSize = 10;

    private String searchCode;
    private String searchDisplayText;

    private PagingListModelList<CodeDisplay> model;
    @Wire("#lbPaging")
    private Listbox lbPaging;


    private boolean isSearchCode = false;
    private boolean isSearchDisplayText = false;

    @Init
    public void init() {
        model = new PagingListModelList<CodeDisplay>(pageSize) {
            @Override
            protected Integer loadListTotalSize() {
                int count = 0;
                try (Session hb_session = HibernateUtil.getSessionFactory().openSession()) {
                    Long counter = 0L;
                    if (isSearchCode) {
                        counter = hb_session.createQuery("Select count(cv) From CodeValue cv where cv.code = 'codesystem' and cv.shortCode like :code ", Long.class).setParameter("code", "%"+searchCode+"%").uniqueResult();
                    } else if (isSearchDisplayText) {
                        counter = hb_session.createQuery("Select count(cv) From CodeValue cv where cv.code = 'codesystem' and cv.displayText like :display ", Long.class).setParameter("display", "%"+searchDisplayText+"%").uniqueResult();
                    } else {
                        counter = hb_session.createQuery("Select count(cv) From CodeValue cv where cv.code = 'codesystem' ", Long.class).uniqueResult();
                    }
                    count = counter.intValue();
                }
                return count;
            }

            @Override
            protected List<CodeDisplay> loadPageFromDB(int startIndex, int size) {
                List<CodeDisplay> currentPageData = new LinkedList<>();
                try (Session hb_session = HibernateUtil.getSessionFactory().openSession()) {
                    if (isSearchCode) {
                        currentPageData = hb_session.createQuery("Select new org.test.model.CodeDisplay(cv.shortCode, cv.displayText)  From CodeValue cv where cv.code = 'codesystem' and cv.shortCode like :code order by cv.shortCode asc", CodeDisplay.class).setParameter("code", "%"+searchCode+"%").setFirstResult(startIndex).setMaxResults(size).list();
                    } else if (isSearchDisplayText) {
                        currentPageData = hb_session.createQuery("Select new org.test.model.CodeDisplay(cv.shortCode, cv.displayText)  From CodeValue cv where cv.code = 'codesystem' and cv.displayText like :display order by cv.shortCode asc", CodeDisplay.class).setParameter("display", "%"+searchDisplayText+"%").setFirstResult(startIndex).setMaxResults(size).list();
                    } else {
                        currentPageData = hb_session.createQuery("Select new org.test.model.CodeDisplay(cv.shortCode, cv.displayText)  From CodeValue cv where cv.code = 'codesystem' order by cv.shortCode asc", CodeDisplay.class).setFirstResult(startIndex).setMaxResults(size).list();
                    }
                }
                return currentPageData;
            }
        };
    }

    @AfterCompose
    public void afterCompose(@ContextParam(ContextType.VIEW) Component view) {
        Selectors.wireComponents(view, this, false);
    }

    @Command
    @NotifyChange("searchForCode")
    public void searchForCode(@ContextParam(ContextType.TRIGGER_EVENT) InputEvent event) {
        searchDisplayText = null;
        isSearchDisplayText = false;
        isSearchCode = true;
        searchCode = event.getValue();
        model.clearCaches();

        //using this instead of fireing the event in model.clearCaches() works:
        //lbPaging.setModel(new ListModelList<CodeValue>());
        //lbPaging.setActivePage(0);
        //lbPaging.setModel(model);    
    }

    @Command
    @NotifyChange("searchForDisplayText")
    public void searchForDisplayText(@ContextParam(ContextType.TRIGGER_EVENT) InputEvent event) {
        searchCode = null;
        isSearchCode = false;
        isSearchDisplayText = true;
        searchDisplayText = event.getValue();
        model.clearCaches();
    }

    public PagingListModelList<CodeDisplay> getModel() {
        return model;
    }

    public String getSearchCode() {
        return searchCode;
    }

    public void setSearchCode(String searchCode) {
        this.searchCode = searchCode;
    }

    public String getSearchDisplayText() {
        return searchDisplayText;
    }

    public void setSearchDisplayText(String searchDisplayText) {
        this.searchDisplayText = searchDisplayText;
    }
}
Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More