我如何将动态过滤的xpage视图/重复控件放入hashmap?

时间:2014-04-28 08:56:08

标签: java xpages

我可以轻松地将filtered view的条目值放入hashmap吗?

我有一个重复控件,绑定到视图,带有动态过滤器。 用户可以将过滤器更改为与视图列对应的多个djFilteringSelect controls

根据第一个djFilteringSelect中的选择,下一个djFilteringSelects中的选择应限于可能的条目(“类似于excel中的数据过滤器”)。目前,我使用@dbcolumn/@dblookup的单独djFilteringSelects方法执行此操作,但我认为将视图条目值填充到hashmap并显示{{}会更好更容易1 {} hashmap中的值。

我在这里找到了一些带有重复控件和djFilteringSelect的线程,但是这些示例还分别构建了doc集合,我希望避免这种情况。

感谢您的帮助, 乌韦

1 个答案:

答案 0 :(得分:1)

所有这些示例分别构建文档集的原因。而不是"视图在UI"中,所以我必须使用它,您可能更容易构建一个bean作为重复控制的源。 Bean数据源或托管bean。这将允许一个用例,在一个显示中显示2个过滤结果(例如英格兰/伦敦和法国/里昂),过滤视图无法做到。

<强>更新

如果你有很多读者/作者字段,你想要一个由他们分类的视图,填充你的&#34;支持bean&#34; - 有很多performance to gain。在记忆中容纳几百件物品并不是一件大事。

虽然有两列火车:使它成为通用的,因此视图中的每一行最终都是一个收集项(数组,列表,地图等)或构建具有清晰名称的专用订单项。这列火车经常碰撞,让我带你去专用火车一会儿。 :-)所以你的课程(你需要2)看起来像这样:

    package test;

    import java.io.Serializable;
    import java.util.Vector;

    import lotus.domino.Database;
    import lotus.domino.Document;
    import lotus.domino.NotesException;
    import lotus.domino.ViewEntry;

    public class Fruit implements Serializable {

        private static final long   serialVersionUID    = 1L;

        private String              name;
        private String              color;
        private String              shape;
        private String              taste;
        private String              unid                = null;

        public Fruit() {
            // default constructor, might not be needed
        }

        // To make it easy from a view
        public Fruit(final ViewEntry ve) {
            try {
                @SuppressWarnings("rawtypes")
                Vector v = ve.getColumnValues();
                // 0 would be the user/group/role
                this.setName(v.get(1).toString());
                this.setColor(v.get(2).toString());
                this.setShape(v.get(3).toString());
                this.setTaste(v.get(4).toString());
                this.unid = ve.getUniversalID();
            } catch (NotesException e) {
                e.printStackTrace();
            }

        }

        public void save(Database db) throws NotesException {
            Document doc;
            if (this.unid == null) {
                doc = db.createDocument();
            } else {
                doc = db.getDocumentByUNID(this.unid);
            }
            doc.replaceItemValue("Color", this.getColor());
            // more here
            doc.save();
        }

        public final String getName() {
            return this.name;
        }

        public final void setName(String name) {
            this.name = name;
        }

        public final String getColor() {
            return this.color;
        }

        public final void setColor(String color) {
            this.color = color;
        }

        public final String getShape() {
            return this.shape;
        }

        public final void setShape(String shape) {
            this.shape = shape;
        }

        public final String getTaste() {
            return this.taste;
        }

        public final void setTaste(String taste) {
            this.taste = taste;
        }
    }

持有订单项(使用我最喜欢的水果示例)。在你的代码中,重复控制变量(或数据表变量) - 而不是视图控件,将保存一个来自fruitController.getSelectedFruits()的Fruit实例(你可以在EL中使用fruitController.selectedFruits),所以你可以使用varName.color,varname.shape

绑定列

它周围的类看起来大致如下:

    package test;

    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Set;
    import java.util.TreeSet;

    import lotus.domino.Database;
    import lotus.domino.NotesException;
    import lotus.domino.Session;
    import lotus.domino.View;
    import lotus.domino.ViewEntry;
    import lotus.domino.ViewEntryCollection;

    public class FruitController implements Serializable {

        private static final long       serialVersionUID    = 1L;
        private static final String     FRUIT_VIEW          = "(FruitsByUser)";

        private final Collection<Fruit> allFruits           = new ArrayList<Fruit>();
        private final Set<String>       colors              = new TreeSet<String>();
        private final Set<String>       shape               = new TreeSet<String>();
        private final Set<String>       taste               = new TreeSet<String>();

        private String                  colorFilter         = null;
        private String                  tasteFilter         = null;
        private String                  shapeFilter         = null;

        // if you use this controller, you only can use an object data source!
        // for a bean you would need an empty controller
        public FruitController(final Session s, final Database db) {
            this.populateData(s, db);
        }

        public final String getColorFilter() {
            return this.colorFilter;
        }

        public final String[] getColors() {
            return (String[]) this.colors.toArray();
        }

        public Collection<Fruit> getSelectedFruits() {
            Collection<Fruit> result = new ArrayList<Fruit>();

            for (Fruit f : this.allFruits) {
                if (this.matchesFilter(f)) {
                    result.add(f);
                }
            }

            return result;
        }

        public final String[] getShape() {
            return (String[]) this.shape.toArray();
        }

        public final String getShapeFilter() {
            return this.shapeFilter;
        }

        public final String[] getTaste() {
            return (String[]) this.taste.toArray();
        }

        public final String getTasteFilter() {
            return this.tasteFilter;
        }

        public void resetFilters() {
            this.setColorFilter(null);
            this.setShapeFilter(null);
            this.setTasteFilter(null);
        }

        public final void setColorFilter(String colorFilter) {
            this.colorFilter = colorFilter;
        }

        public final void setShapeFilter(String shapeFilter) {
            this.shapeFilter = shapeFilter;
        }

        public final void setTasteFilter(String tasteFilter) {
            this.tasteFilter = tasteFilter;
        }

        private boolean matchesFilter(Fruit f) {
            boolean result = true;

            result = ((result == false) ? false : ((this.colorFilter == null || "".equals(this.colorFilter.trim())) ? true
                    : (this.colorFilter.equals(f.getColor()))));
            result = ((result == false) ? false : ((this.tasteFilter == null || "".equals(this.tasteFilter.trim())) ? true
                    : (this.tasteFilter.equals(f.getTaste()))));
            result = ((result == false) ? false : ((this.shapeFilter == null || "".equals(this.shapeFilter.trim())) ? true
                    : (this.shapeFilter.equals(f.getShape()))));

            return result;
        }

        private void populateData(final Session s, final Database db) {
            try {
                final View v = db.getView(FRUIT_VIEW);
                // You might need to loop a little here to get all the values
                final ViewEntryCollection vec = v.getAllEntriesByKey(s.getUserName());
                ViewEntry ve = vec.getFirstEntry();

                while (ve != null) {
                    ViewEntry nextVe = vec.getNextEntry(ve);
                    Fruit f = new Fruit(ve);
                    this.updateSelectors(f);
                    this.allFruits.add(f);
                    ve = nextVe;
                    nextVe.recycle();
                }

                vec.recycle();
                v.recycle();
            } catch (NotesException e) {
                // TODO Stacktrace is no error handling
                e.printStackTrace();
            }

        }

        private void updateSelectors(Fruit f) {
            this.colors.add(f.getColor());
            this.shape.add(f.getShape());
            this.taste.add(f.getTaste());
        }

    }

当然,您可以通过根据其他选择过滤选择值来使其更加复杂(例如,在选择颜色后,仅提供该颜色中可用的形状)。使用类作为对象数据源(例如fruitController)应该很容易。您可以将您的下拉列表绑定到EL中的fruitController.colorFilter等,并将EL中的选择定义为fruitController.Colors

更新2

数据源应该是一个对象数据源,如下所示:

   <xp:this.data>
     <xe:objectData var="fruitController" ignoreRequestParams="true"
       readonly="false" scope="view"
           createObject="#{javascript:return new test.FruitController(session, database);}">
     </xe:objectData>
  </xp:this.data>

对于bean方法,您需要编辑faces-config.xml并将类更改为具有无参数构造函数。对于选择值,您可以坚持使用页面中的toArray()调用,或者更好地更改类以首先返回数组。我相应地更新了上面的类(所以你仍然可以使用EL,不需要SSJS)。

现在,您只需要在选择的onChange事件中为重复添加刷新。由于新值将被发送到对象数据源(您将它们绑定到colorFilter,shapeFilter,tasteFilter),刷新将执行#{fruitController.selectedFruits},将子集传递回面板。

所以这里的概念是:您将所有用户数据一次性地提取到对象数据源中,一旦在该类中加载了过滤器,就不需要重新检索或查找。

让我们知道锄头