0

我看过很多关于通过 MarkupWriter 以编程方式添加 html 的教程,但它会在使用组件的地方添加 html。

有没有办法告诉作者在结束正文标记之前添加它?

另外,我怎样才能得到组件的主体?

4

3 回答 3

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);
        }
    });
}
于 2013-01-22T20:59:25.333 回答
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");
      }
}
于 2013-01-21T22:19:12.617 回答
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);
    }
于 2013-01-22T19:21:21.047 回答