列数可变的检票桌

发布于 2024-10-27 20:37:48 字数 1011 浏览 3 评论 0 原文

我一直在通过向页面添加 ListView (以 List 形式向其提供我的数据)来创建表格,并将相应的 id 分配给中的每一列html 文件。

但是现在我遇到的情况是,我没有简单的 List,而是 List>。我还获得了一个包含嵌套映射的所有可能键的列表 (List)。现在我需要创建一个表,其中 Map 的每个值都应位于键名称指向该值的列中。

假设我有以下数据:

keys = ['a', 'b']

data = [ { 'a' = 1, 'b' = 2 },
         { 'a' = 3, 'b' = 4 },
         { 'a' = 5, 'b' = 6}] 

我想创建表:

<table>
    <tr>
        <th>a</th>
        <th>b</th>
    </tr>
    <tr>
        <td>1</td>
        <td>2</td>
    </tr>
    <tr>
        <td>3</td>
        <td>4</td>
    </tr>
    <tr>
        <td>5</td>
        <td>6</td>
    </tr>
</table>

知道嵌套 Map 中的键的名称和数量可以更改,在 wicket 中实现此功能的最佳方法是什么?

I've been creating tables by adding a ListView (providing it with my data as a List<MyObject>) to the page, and assigning the corresponding ids to each column in the html file.

However now I have a situation where instead of a simple List<MyObject> I have List<Map<String,MyObject>>. I also get a list with all the possible keys of the nested map (List<String>). Now I need to create a table where each value of the Map should be in the column with the name of the key pointing to that value.

Let's say I have the following data:

keys = ['a', 'b']

data = [ { 'a' = 1, 'b' = 2 },
         { 'a' = 3, 'b' = 4 },
         { 'a' = 5, 'b' = 6}] 

I would like to create the table:

<table>
    <tr>
        <th>a</th>
        <th>b</th>
    </tr>
    <tr>
        <td>1</td>
        <td>2</td>
    </tr>
    <tr>
        <td>3</td>
        <td>4</td>
    </tr>
    <tr>
        <td>5</td>
        <td>6</td>
    </tr>
</table>

Knowing that the names and number of keys in the nested Map can change, what is the best way to implement this in wicket?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

任性一次 2024-11-03 20:37:48

下面是使用 DefaultDataTable 和嵌套 ListView 的示例。

请注意,虽然 DataTable 方法可能看起来不那么简单(嗯,这取决于旁观者的眼睛),但它实际上将数据获取与可视化更清晰地分开,并且您可以获得开箱即用的分页:尝试添加更多数据,或降低 rowsPerPage (DefaultDataTable 的最后一个构造函数参数)。

public class HomePage extends WebPage {

    static final String A = "a";
    static final String B = "b";

    public HomePage() {
        final List<String> keys = Arrays.asList(A, B);
        final List<Map<String, Integer>> data = Arrays.asList(
            map(A, 1).put(B, 11).toMap(),
            map(A, 2).put(B, 12).toMap(),
            map(A, 3).put(B, 13).toMap(),
            map(A, 4).put(B, 14).toMap(),
            map(A, 5).put(B, 15).toMap(),
            map(A, 6).put(B, 16).toMap(),
            map(A, 7).put(B, 17).toMap(),
            map(A, 8).put(B, 18).toMap(),
            map(A, 9).put(B, 19).toMap());

        // Using a DefaultDataTable
        ISortableDataProvider dataProvider = new SortableDataProvider() {
            public Iterator iterator(int first, int count) {
                int start = Math.min(0, first);
                int end = Math.min(data.size(), start + count);
                return data.subList(start, end).iterator();
            }
            public int size() {
                return data.size();
            }
            public IModel model(Object object) {
                return new CompoundPropertyModel(object);
            }
        };
        List columns = new ArrayList();
        for (String key : keys)
            columns.add(new PropertyColumn(Model.of(key), key));
        add(new DefaultDataTable("dataTable", columns, dataProvider, 20));

        // Using a nested ListViews
        add(new ListView("headers", keys) {
            @Override
            protected void populateItem(ListItem item) {
                item.add(new Label("header", String.valueOf(item.getModelObject())));
            }
        });
        add(new ListView("listView", data) {
            @Override
            protected void populateItem(ListItem item) {
                final Map rowMap = (Map) item.getModelObject();
                item.add(new ListView("nested", keys) {
                    @Override
                    protected void populateItem(ListItem item) {
                        Object value = rowMap.get(item.getModelObject());
                        item.add(new Label("value", String.valueOf(value)));
                    }
                });
            }
        });
    }

    // to make building the data structure a little more fun :)
    private MapBuilder<String, Integer> map(String key, Integer value) {
        return new MapBuilder<String, Integer>().put(key, value);
    }
    private static class MapBuilder<K, V> {
        Map<K, V> map = new HashMap<K, V>();
        MapBuilder<K, V> put(K key, V value) {
            map.put(key, value);
            return this;
        }
        Map<K, V> toMap() {
            return map;
        }
    }
}


<html xmlns:wicket="http://wicket.apache.org">
<body>

  <table wicket:id="dataTable"></table>

  <table>
    <tr>
      <th wicket:id="headers">
          <span wicket:id="header"></span>
      </th>
    </tr>
    <tr wicket:id="listView">
      <td wicket:id="nested">
        <span wicket:id="value"></span>
      </td>
    </tr>
  </table>

</body>
</html>

Below, examples using DefaultDataTable and nested ListViews.

Note that, while the DataTable approach may look less straightforward (well, it depends on the eye of the beholder), it actually separates more cleanly data fetching from visualization, and you get pagination out-of-the-box: try adding more data, or lowering the rowsPerPage (DefaultDataTable's last constructor param).

public class HomePage extends WebPage {

    static final String A = "a";
    static final String B = "b";

    public HomePage() {
        final List<String> keys = Arrays.asList(A, B);
        final List<Map<String, Integer>> data = Arrays.asList(
            map(A, 1).put(B, 11).toMap(),
            map(A, 2).put(B, 12).toMap(),
            map(A, 3).put(B, 13).toMap(),
            map(A, 4).put(B, 14).toMap(),
            map(A, 5).put(B, 15).toMap(),
            map(A, 6).put(B, 16).toMap(),
            map(A, 7).put(B, 17).toMap(),
            map(A, 8).put(B, 18).toMap(),
            map(A, 9).put(B, 19).toMap());

        // Using a DefaultDataTable
        ISortableDataProvider dataProvider = new SortableDataProvider() {
            public Iterator iterator(int first, int count) {
                int start = Math.min(0, first);
                int end = Math.min(data.size(), start + count);
                return data.subList(start, end).iterator();
            }
            public int size() {
                return data.size();
            }
            public IModel model(Object object) {
                return new CompoundPropertyModel(object);
            }
        };
        List columns = new ArrayList();
        for (String key : keys)
            columns.add(new PropertyColumn(Model.of(key), key));
        add(new DefaultDataTable("dataTable", columns, dataProvider, 20));

        // Using a nested ListViews
        add(new ListView("headers", keys) {
            @Override
            protected void populateItem(ListItem item) {
                item.add(new Label("header", String.valueOf(item.getModelObject())));
            }
        });
        add(new ListView("listView", data) {
            @Override
            protected void populateItem(ListItem item) {
                final Map rowMap = (Map) item.getModelObject();
                item.add(new ListView("nested", keys) {
                    @Override
                    protected void populateItem(ListItem item) {
                        Object value = rowMap.get(item.getModelObject());
                        item.add(new Label("value", String.valueOf(value)));
                    }
                });
            }
        });
    }

    // to make building the data structure a little more fun :)
    private MapBuilder<String, Integer> map(String key, Integer value) {
        return new MapBuilder<String, Integer>().put(key, value);
    }
    private static class MapBuilder<K, V> {
        Map<K, V> map = new HashMap<K, V>();
        MapBuilder<K, V> put(K key, V value) {
            map.put(key, value);
            return this;
        }
        Map<K, V> toMap() {
            return map;
        }
    }
}


<html xmlns:wicket="http://wicket.apache.org">
<body>

  <table wicket:id="dataTable"></table>

  <table>
    <tr>
      <th wicket:id="headers">
          <span wicket:id="header"></span>
      </th>
    </tr>
    <tr wicket:id="listView">
      <td wicket:id="nested">
        <span wicket:id="value"></span>
      </td>
    </tr>
  </table>

</body>
</html>
回梦 2024-11-03 20:37:48

您可以嵌套ListView。您想要的标记将如下所示:

<table>
  <tr><th wicket:id="headerlist"><span wicket:id="header"></span></th></tr>
  <tr wicket:id="contentlist"><td wicket:id="column">
    <span wicket:id="data"></span>
  </td></tr>
</table>

然后您将需要三个 ListView。第一个 (headerlist) 将填充 keys 列表中的标头。这很简单,所以我将跳过该示例。

第二个 (contentlist) 将位于您的data 列表中。在 populateItems 方法中,您将添加第三个 ListViewcolumn),它将再次遍历 keys 列表:

add(new ListView<Map<String,MyObject>>("contentlist", data) {
  protected void populateItem(ListItem<Map<String,MyObject>> item) {
    final Map<String,MyObject> map = item.getModelObject();
    // Inner list - using item.add to add to the inner list
    item.add(new ListView<String>("column", keys) {
      protected void populateItem(ListItem<String> item) {
        String key = item.getModelObject();
        item.add(new Label("data", map.get(key).toString()));
      }
    });
  }
});

You can nest ListView. The markup you want will look something like this:

<table>
  <tr><th wicket:id="headerlist"><span wicket:id="header"></span></th></tr>
  <tr wicket:id="contentlist"><td wicket:id="column">
    <span wicket:id="data"></span>
  </td></tr>
</table>

You will then need three ListView. The first (headerlist) will fill in the headers from the keys list. This is simple, so I'll skip the example.

The second (contentlist) will be across your data list. In the populateItems method you will add the third ListView (column), which will again iterate across the keys list:

add(new ListView<Map<String,MyObject>>("contentlist", data) {
  protected void populateItem(ListItem<Map<String,MyObject>> item) {
    final Map<String,MyObject> map = item.getModelObject();
    // Inner list - using item.add to add to the inner list
    item.add(new ListView<String>("column", keys) {
      protected void populateItem(ListItem<String> item) {
        String key = item.getModelObject();
        item.add(new Label("data", map.get(key).toString()));
      }
    });
  }
});
青丝拂面 2024-11-03 20:37:48

您当然可以使用嵌套的ListView,但您也可以使用DataTable 及其后代,专门为此任务而设计。作为奖励,您还可以从中获得诸如排序和分页之类的功能。

You can of course use nested ListViews, but you can also use DataTable and its descendants, which were specifically designed for this task. As a bonus you can also get things like sorting and pagination out of them.

紫﹏色ふ单纯 2024-11-03 20:37:48

谢谢铁雄!我已经填写了 Tetsuo 变量列示例的泛型:

  1. DefaultDataTable
  2. Nested ListViews

Wicket HTML

<html xmlns:wicket="http://wicket.apache.org">
<body>

  <h3>Example 1</h3>
  <table wicket:id="dataTable"></table>

  <br>

  <h3>Example 2</h3>
  <table>

    <tr>
      <th wicket:id="headers">
        <span wicket:id="header"></span>
      </th>
    </tr>

    <tr wicket:id="listView">
      <td wicket:id="nested">
        <span wicket:id="value"></span>
      </td>
    </tr>

  </table>

</body>
</html>

Wicket Java

public class HomePage extends WebPage 
{
    /** Represents serialVersionUID. */
    private static final long serialVersionUID = 20150701L;

    static final String A = "alpha";
    static final String B = "beta";
    static final String C = "gamma";

    public HomePage()
    {
        super();

        final List<String> keys = Arrays.asList(A, B, C);

        final List<Map<String,Integer>> data = Arrays.asList
        (
            map(A, 1).put(B, 11).put(C, 21).toMap(),
            map(A, 2).put(B, 12).put(C, 22).toMap(),
            map(A, 3).put(B, 13).put(C, 23).toMap(),
            map(A, 4).put(B, 14).put(C, 24).toMap(),
            map(A, 5).put(B, 15).put(C, 25).toMap(),
            map(A, 6).put(B, 16).put(C, 26).toMap(),
            map(A, 7).put(B, 17).put(C, 27).toMap(),
            map(A, 8).put(B, 18).put(C, 28).toMap(),
            map(A, 9).put(B, 19).put(C, 29).toMap()
        );

        // Using a DefaultDataTable
        ISortableDataProvider<Map<String,Integer>,String> dataProvider = 
            new SortableDataProvider<Map<String,Integer>,String>()
        {
            /** Represents serialVersionUID. */
            private static final long serialVersionUID = HomePage.serialVersionUID;

            public Iterator<Map<String,Integer>> iterator(long first, long count)
            {
                int start = Math.max(0, (int) first);
                int end = Math.min(data.size(), start + (int) count);
                return data.subList(start, end).iterator();
            }

            public long size()
            {
                return data.size();
            }

            public IModel<Map<String,Integer>> model(Map<String,Integer> object)
            {
                return new CompoundPropertyModel<Map<String,Integer>>(object);
            }
        };

        List<PropertyColumn<Map<String,Integer>,String>> columns =
            new ArrayList<PropertyColumn<Map<String,Integer>,String>>();

        for (String key : keys)
            columns.add(new PropertyColumn<Map<String,Integer>,String>(Model.of(key), key));

        // Example 1 - Using a DataTable
        // Wicket: "dataTable"
        add(new DefaultDataTable<Map<String,Integer>,String>("dataTable", columns, dataProvider, 5));

        // Example 2 - Using nested ListViews
        // Wicket: "headers"
        add
        (
            new ListView<String>("headers", keys)
            {
                /** Represents serialVersionUID. */
                private static final long serialVersionUID = HomePage.serialVersionUID;

                @Override
                protected void populateItem(ListItem<String> item)
                {
                    // Wicket: "header"
                    item.add(new Label("header", String.valueOf(item.getModelObject())));
                }
            }
        );

        add
        (
            // Wicket: "listView"
            new ListView<Map<String,Integer>>("listView", data)
            {
                /** Represents serialVersionUID. */
                private static final long serialVersionUID = HomePage.serialVersionUID;

                @Override
                protected void populateItem(ListItem<Map<String,Integer>> item)
                {
                    final Map<String,Integer> rowMap = item.getModelObject();
                    item.add
                    (
                        // Wicket: "nested"
                        new ListView<String>("nested", keys)
                        {
                            private static final long serialVersionUID = HomePage.serialVersionUID;
                            @Override
                            protected void populateItem(ListItem<String> item)
                            {
                                Integer value = rowMap.get(item.getModelObject());

                                // Wicket: "value"
                                item.add(new Label("value", String.valueOf(value)));
                            }
                        }
                    );
                }
            }
        );
    }

    // Make building the data structure a little more fun :)
    private MapBuilder<String, Integer> map(String key, Integer value)
    {
        return new MapBuilder<String, Integer>().put(key, value);
    }

    private static class MapBuilder<K, V>
    {
        Map<K, V> map = new HashMap<K, V>();

        MapBuilder<K, V> put(K key, V value)
        {
            map.put(key, value);
            return this;
        }

        Map<K, V> toMap()
        {
            return map;
        }
    }
}

通用用法

DefaultDataTable extends DataTable

  • @param 模型对象类型
  • @param 排序参数的类型

IColumn

  • @param 将在此列单元格中呈现的对象的类型
  • @param 排序参数的类型

ISortableDataProvider

  • @param 模型对象类型(JavaDoc 中省略)?
  • @param 排序参数的类型

Thanks Tetsuo! I've filled in the Generics for Tetsuo's variable column examples:

  1. DefaultDataTable
  2. Nested ListViews

Wicket HTML

<html xmlns:wicket="http://wicket.apache.org">
<body>

  <h3>Example 1</h3>
  <table wicket:id="dataTable"></table>

  <br>

  <h3>Example 2</h3>
  <table>

    <tr>
      <th wicket:id="headers">
        <span wicket:id="header"></span>
      </th>
    </tr>

    <tr wicket:id="listView">
      <td wicket:id="nested">
        <span wicket:id="value"></span>
      </td>
    </tr>

  </table>

</body>
</html>

Wicket Java

public class HomePage extends WebPage 
{
    /** Represents serialVersionUID. */
    private static final long serialVersionUID = 20150701L;

    static final String A = "alpha";
    static final String B = "beta";
    static final String C = "gamma";

    public HomePage()
    {
        super();

        final List<String> keys = Arrays.asList(A, B, C);

        final List<Map<String,Integer>> data = Arrays.asList
        (
            map(A, 1).put(B, 11).put(C, 21).toMap(),
            map(A, 2).put(B, 12).put(C, 22).toMap(),
            map(A, 3).put(B, 13).put(C, 23).toMap(),
            map(A, 4).put(B, 14).put(C, 24).toMap(),
            map(A, 5).put(B, 15).put(C, 25).toMap(),
            map(A, 6).put(B, 16).put(C, 26).toMap(),
            map(A, 7).put(B, 17).put(C, 27).toMap(),
            map(A, 8).put(B, 18).put(C, 28).toMap(),
            map(A, 9).put(B, 19).put(C, 29).toMap()
        );

        // Using a DefaultDataTable
        ISortableDataProvider<Map<String,Integer>,String> dataProvider = 
            new SortableDataProvider<Map<String,Integer>,String>()
        {
            /** Represents serialVersionUID. */
            private static final long serialVersionUID = HomePage.serialVersionUID;

            public Iterator<Map<String,Integer>> iterator(long first, long count)
            {
                int start = Math.max(0, (int) first);
                int end = Math.min(data.size(), start + (int) count);
                return data.subList(start, end).iterator();
            }

            public long size()
            {
                return data.size();
            }

            public IModel<Map<String,Integer>> model(Map<String,Integer> object)
            {
                return new CompoundPropertyModel<Map<String,Integer>>(object);
            }
        };

        List<PropertyColumn<Map<String,Integer>,String>> columns =
            new ArrayList<PropertyColumn<Map<String,Integer>,String>>();

        for (String key : keys)
            columns.add(new PropertyColumn<Map<String,Integer>,String>(Model.of(key), key));

        // Example 1 - Using a DataTable
        // Wicket: "dataTable"
        add(new DefaultDataTable<Map<String,Integer>,String>("dataTable", columns, dataProvider, 5));

        // Example 2 - Using nested ListViews
        // Wicket: "headers"
        add
        (
            new ListView<String>("headers", keys)
            {
                /** Represents serialVersionUID. */
                private static final long serialVersionUID = HomePage.serialVersionUID;

                @Override
                protected void populateItem(ListItem<String> item)
                {
                    // Wicket: "header"
                    item.add(new Label("header", String.valueOf(item.getModelObject())));
                }
            }
        );

        add
        (
            // Wicket: "listView"
            new ListView<Map<String,Integer>>("listView", data)
            {
                /** Represents serialVersionUID. */
                private static final long serialVersionUID = HomePage.serialVersionUID;

                @Override
                protected void populateItem(ListItem<Map<String,Integer>> item)
                {
                    final Map<String,Integer> rowMap = item.getModelObject();
                    item.add
                    (
                        // Wicket: "nested"
                        new ListView<String>("nested", keys)
                        {
                            private static final long serialVersionUID = HomePage.serialVersionUID;
                            @Override
                            protected void populateItem(ListItem<String> item)
                            {
                                Integer value = rowMap.get(item.getModelObject());

                                // Wicket: "value"
                                item.add(new Label("value", String.valueOf(value)));
                            }
                        }
                    );
                }
            }
        );
    }

    // Make building the data structure a little more fun :)
    private MapBuilder<String, Integer> map(String key, Integer value)
    {
        return new MapBuilder<String, Integer>().put(key, value);
    }

    private static class MapBuilder<K, V>
    {
        Map<K, V> map = new HashMap<K, V>();

        MapBuilder<K, V> put(K key, V value)
        {
            map.put(key, value);
            return this;
        }

        Map<K, V> toMap()
        {
            return map;
        }
    }
}

Generic Usage

DefaultDataTable extends DataTable

  • @param The model object type
  • @param The type of the sorting parameter

IColumn

  • @param The type of the object that will be rendered in this column's cells
  • @param The type of the sorting parameter

ISortableDataProvider

  • @param The model object type (omitted in JavaDoc) ??
  • @param The type of the sorting parameter
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文