Tapestry 5.3通过自定义组件在主体末尾添加html

时间:2013-01-21 19:06:19

标签: java tapestry

我已经看过许多关于通过MarkupWriter以编程方式添加html的教程,但它添加了使用该组件的html。

有没有办法告诉作者在关闭身体标签之前添加它?

另外,我如何获得组件的主体?

3 个答案:

答案 0 :(得分:1)

我认为它不需要那么复杂

@Environmental
private Heartbeat heartbeat;

@SetupRender
void setupRender(MarkupWriter writer) {
    writer.element("div");
}

// let the body render as normal

@AfterRender
void afterRender(final MarkupWriter writer) {
    Element wrapper = writer.element();
    writer.end();
    final String bodyMarkup = wrapper.getChildMarkup();

    // remove the body 
    wrapper.remove();

    heartbeat.defer(new Runnable() {
        public void run() {
            Element pageBody = writer.getDocument().find("html/body");
            pageBody.raw(bodyMarkup);
        }
    });
}

答案 1 :(得分:0)

要获取组件的主体,您应该@Inject ComponentResources并调用getBody()。

要在身体末端添加一些东西需要稍微多想一想。我可以看到两种方式。

使用@HeartbeatDeferred注释,您可以在渲染所有其他组件后访问DOM。像这样:

public class MyComponent {
    private Element body;

    void setupRender(MarkupWriter writer) {
        body = writer.getDocument().find("html/body");
    }

    @HeartbeatDeferred
    void addToBody() {
        body.text("Some text here");
    }
}

另一种方法是直接在body标签下定义一个嵌套所有其他组件的组件。该组件将模型对象推送到其设置的@SetupRender方法中。然后,定义为顶级组件的子组件的组件可以使用@Environmental批注来查找模型对象并为其做出贡献。顶级组件然后呈现模型。

例如:

<html>
   <body>
       <t:toplevelcomponent>
          <t:childcomponent />
          <div>...</div>
          <div>...</div>
       </t:toplevelcomponent>
   </body>
</html>

public class TopLevelModel {
    private List<String> contributions;

    // getters and setters
}

public class TopLevelComponent {
      @Inject
      Environment environment;

      public void setupRender() {
          environment.push(TopLevelModel.class, new TopLevelModel());
      }

      public void afterRender(MarkupWriter writer) {
          TopLevelModel model = environment.pop(TopLevelModel.class);
          for (String contribution : model.getContributions()) {
              // add text to the body tag
              writer.getElement().text(contribution); 
          }
      }
}

public class ChildComponent {
      @Environmental
      private TopLevelModel topLevelModel;

      public void setupRender() {
           topLevelModel.getContributions().add("Foo");
           topLevelModel.getContributions().add("Bar");
      }
}

答案 2 :(得分:0)

解决方案:

    private Element pageBody;
    private String componentBodyMarkup;
    private Element wrapper;

    @Environmental
    private Heartbeat heartbeat;

    @SetupRender
    private RenderCommand setupRender() {
        return new RenderCommand() {
            public void render(MarkupWriter writer, RenderQueue queue) {
                wrapper = writer.element("div");

                RenderCommand renderBody = new RenderCommand() {
                    public void render(MarkupWriter writer, RenderQueue queue2) {
                        RenderCommand bodyRenderCommand = typeCoercer.coerce(componentResources.getBody(), RenderCommand.class);
                        queue2.push(bodyRenderCommand);
                    }
                };
                queue.push(renderBody);
            }
        };
    }

    @BeforeRenderBody
    private boolean beforeRenderBody(MarkupWriter writer) {
        return false;
    }

    @AfterRender
    private void afterRender(MarkupWriter writer) {
        pageBody = writer.getDocument().find("html/body");

        writer.end();

        componentBodyMarkup = wrapper.getChildMarkup();
        wrapper.remove();

        Runnable appendToBody = new Runnable() {
            public void run() {
                pageBody.raw(componentBodyMarkup);
            }
        };
        heartbeat.defer(appendToBody);
    }