Uploaded image for project: 'Wicket'
  1. Wicket
  2. WICKET-2493

Border component's <wicket:body /> tag doesn't work within a repeater such as a ListView

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Won't Fix
    • 1.4.1
    • 1.4.1
    • wicket
    • None

    Description

      Hi,
      I've been using Wicket for about a month now, I've been "practicing" with every aspects of it, and it just feels right and great for my needs.
      But right now, I'm running into a problem using Borders, I've consulted online help and other related topics, and I've done some working examples
      of using Borders as well. the <wicket:body /> tag works well if it's directly placed under <wicket:border> just as the examples show, and it still works when
      it is placed under some other simple container within <wicket:border>, like a link, or a WebMarkupContainer, but it won't work if it's placed under a repeater.

      I have a border component declared as the following:
      MyBorder.html
      <wicket:border>
      <table>
      <tr wicket:id="rows">
      <wicket:body />
      </tr>
      </table>
      </wicket:border>

      I would like my border component function as a repeating view that outputs table-like data, but having the outter page who uses this border to define the specific contents that will be rendered as each row of the table, something like:

      MyPage.html
      <div wicket:id="myBorder">
      <span wicket:id="myField1" />
      <hr />
      <span wicket:id="myField2" />
      </div>

      Then in my code:
      MyPage.java

      ...
      MyBorder myBorder = new MyBorder("myBorder");
      add(myBorder);

      myBorder.add( new Label("myField1", model1) );
      myBorder.add( new Label("myField2", model2) );
      ...

      MyBorder.java
      ...
      ListView lv = new ListView("rows", list)
      {
      public void populateItem(ListItem item)
      {
      }
      }
      add(lv);
      ...

      Doing this would result in an exception complaining that
      Unable to find component with id 'myField1' in [MarkupContainer [Component id = _body]]

      I understand that because "myField1" has to be added to the border; however, where do I add it? From the Border API, it stated that if the "body" is not an immediate child of border (example see below), than you must use code like the following someContainer.add(getBodyContainer()) to add the body component to the correct container.
      So I'm adding "myField1" in my code, like
      lv.add(myField1);

      Then I get the following exception:
      "The component [Component id = myField1] has the same wicket:id as another component already added at the same level"

      I also understand that I shouldn't be adding components to repeaters directly; instead I should be adding it to the ListItem upon each iteration, so I did something like:
      public void populateItem(ListItem item)
      {
      item.add( getBodyContainer() );
      }

      The way I understand the above code is that the "getBodyContainer()" method returns what has been specified as the body of the border component; which is "myField1" and "myField2" in this case.
      As for the models of the two labels, I'll use some callbacks to make sure each iteration returns the correct model or values for the label to display.
      It is supposed to work, at least I thought so, but Wicket then complains that

      WicketMessage: Markup element at index 5 failed to advance the markup stream
      at org.apache.wicket.markup.MarkupStream.throwMarkupException(MarkupStream.java:465)
      at org.apache.wicket.MarkupContainer.renderComponentTagBody(MarkupContainer.java:1604)
      at org.apache.wicket.MarkupContainer.onComponentTagBody(MarkupContainer.java:1525)
      at org.apache.wicket.Component.renderComponent(Component.java:2626)
      at org.apache.wicket.MarkupContainer.onRender(MarkupContainer.java:1536)
      at org.apache.wicket.Component.render(Component.java:2457)
      at org.apache.wicket.markup.html.list.ListView.renderItem(ListView.java:638)
      at org.apache.wicket.markup.html.list.ListView.renderChild(ListView.java:626)
      at org.apache.wicket.markup.repeater.AbstractRepeater.onRender(AbstractRepeater.java:103)
      at org.apache.wicket.Component.render(Component.java:2457)
      at org.apache.wicket.MarkupContainer.renderNext(MarkupContainer.java:1414)
      at org.apache.wicket.MarkupContainer.renderComponentTagBody(MarkupContainer.java:1601)
      at org.apache.wicket.MarkupContainer.renderAssociatedMarkup(MarkupContainer.java:675)
      at org.apache.wicket.markup.html.border.Border.onComponentTagBody(Border.java:305)
      ...
      Then I looked at MarkupContainer.renderComponentTagBody(MarkupContainer.java:1604)
      and noticed that Wicket is trying to compare some kind of index...

      I am really confused at this, why the markup stream had not been advanced, I'm simply adding some component to the ListItem upon each iteration, did I do anything wrong? What should I do if I wanted to achive the above design using Borders? or should I use something else?

      Looking forward to an answer,

      thanks in advance!
      really appreciated!!

      Attachments

        Activity

          People

            ivaynberg Igor Vaynberg
            intelligs Shu Gao
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: