Hi people, there have been a few threads around lately about getting the
HTML string from a block / render command on the serverside including:

http://tapestry.1045711.n5.nabble.com/Rendering-components-in-Alerts-td5543434.html
http://tapestry.1045711.n5.nabble.com/How-does-MultiZoneUpdateEventResultProcessor-get-a-html-string-from-a-RenderCommand-td5518968.html

http://tapestry.1045711.n5.nabble.com/tml-parameter-rendered-into-a-JavaScript-string-td5512889.html

I have come up with what I think to be the most elegant solution.

Please find below the source for a component which does the following:
1. Takes a count parameter and a render command parameter
2. For each count, updates a "current" property which can be referenced by
the render command and adds the render command to the render queue

3. Removes the elements from the DOM in @AfterRender and uses the HTML in a
javascript alert

Page.html
=======
        <t:tmlToString t:count="5" t:id="tmlToString">
                <p:renderMe>
                        <div>foo ${tmlToString.current} bar</div>
                </p:renderMe>
        </t:tmlToString>

Page.java
=======
        @InjectComponent
        @Property
        private TmlToString tmlToString;


TmlToString.java
============
public class TmlToString {
        @Parameter
        @Property
        private RenderCommand renderMe;

        @Property
        @Parameter(defaultPrefix=BindingConstants.LITERAL, required=true)
        private int count;

        @Property
        private int current;

        @Inject
        private JavaScriptSupport javaScriptSupport;

        private Element wrappingDiv;

        @BeginRender
        RenderCommand beginRender() {
                return new RenderCommand() {
                        public void render(MarkupWriter writer, RenderQueue
queue) {
                                wrappingDiv = writer.element("div");
                                List<RenderCommand> commands = new
ArrayList<RenderCommand>();
                                for (int i = 0; i < count; ++ i) {
                                        final int finalI = i;
                                        commands.add(new RenderCommand() {
                                                public void
render(MarkupWriter writer2, RenderQueue queue2) {
                                                        current = finalI;

queue2.push(renderMe);
                                                }
                                        });
                                }
                                Collections.reverse(commands);
                                for (RenderCommand command : commands) {
                                        queue.push(command);
                                }
                        }
                };
        }

        @AfterRender
        void afterRender(MarkupWriter writer) {
                writer.end();
                String html = wrappingDiv.getChildMarkup();
                wrappingDiv.remove();
                javaScriptSupport.addScript("alert(\"%s\")", html);
        }
}

Result
======
alert("<div>foo 0 bar</div><div>foo 1 bar</div><div>foo 2 bar</div><div>foo
3 bar</div><div>foo 4 bar</div>");


Cheers,
Lance.

Reply via email to