AnsweredAssumed Answered

[Surf] Nested freemarker components render wrong

Question asked by petern on Mar 11, 2009
Latest reply on Mar 13, 2009 by petern
Hi all,
I've had a quick look and can't find out much about why this could be happening, so thought I'd ask here as we don't seem to have a Surf forum yet.

I have come across an issue which occurs if nested <@region>s are used within Freemarker-rendered components. I have a feeling I'm doing something wrong and should be using @component but documentation seems quite scarce, so I don't know how to do that. This works in so far as the HTML is produced, and there's no errors, it just doesn't render things in the right order.

A test case. I have two components: HelloWorld(.xml) and NestedHelloWorld(.xml). HelloWorld points to a webscript (/hello-world):
Hello, world! 2+2 is ${2+2}.
And NestedHelloWorld points to its own webscript (/nested-hello-world):
This is a nested Hello, world! with global scope:<br/>
<blockquote>
  <@region id="HelloWorld" scope="global" />
</blockquote>
Here's one with page scope.
<blockquote>
  <@region id="HelloWorld" scope="page" />
</blockquote>
I have created both Global and Page-scoped versions of HelloWorld, however both do the same thing (same webscript).

I have also a page defined using the template test.ftl. This is as follows:
Here is some early content.<br />
<@region id="HelloWorld" scope="global" /><br />
Here is some middle content.<br />
<@region id="HelloWorld" scope="page" /><br />
Here is some late content.
<hr />
Now let's test a nested hello world.<br />
<@region id="NestedHelloWorld" scope="global" />

Done.

So you'd expect to get:
Here is some early content.<br />
Hello, world! 2+2 is 4.<br />
Here is some middle content<br />
Hello, world! 2+2 is 4.<br />
Here is some late content
——————
Now let's test a nested hello world.<br />
This is a nested HW with global scope:<br/>
<blockquote>Hello, world! 2+2 is 4.</blockquote>
Here's one with page scope.
<blockquote>Hello, world! 2+2 is 4.</blockquote>
Done.

The top-level @regions work fine - the Hello, World!s after the 'early' and 'middle' content work fine, however those which are rendered from inside another region are rendered, and then the rendered content appears before the region tag. Using a bit of chrome to indicate start and end of regions/components, I get the following (excuse the verbosity):
Here is some early content.<br />
<!– Begin region global_x002e_HelloWorld –><!– Begin component global_x002e_HelloWorld –>
Hello, world! 2+2 is 4.
<!– End component global_x002e_HelloWorld –><!– End region global_x002e_HelloWorld –>
<br />
Here is some middle content.<br />
<!– Begin region page_x002e_HelloWorld_x002e_test –><!– Begin component page_x002e_HelloWorld_x002e_test –>
Hello, world! 2+2 is 4.
<!– End component page_x002e_HelloWorld_x002e_test –><!– End region page_x002e_HelloWorld_x002e_test –>
<br />
Here is some late content.
<hr />

Now let's test a nested hello world.<br />
<!– Begin region global_x002e_NestedHelloWorld –><!– Begin component global_x002e_NestedHelloWorld –>
<!– Begin region global_x002e_HelloWorld –><!– Begin component global_x002e_HelloWorld –>
Hello, world! 2+2 is 4.
<!– End component global_x002e_HelloWorld –><!– End region global_x002e_HelloWorld –>
<!– Begin region page_x002e_HelloWorld_x002e_test –><!– Begin component page_x002e_HelloWorld_x002e_test –>
Hello, world! 2+2 is 4.
<!– End component page_x002e_HelloWorld_x002e_test –><!– End region page_x002e_HelloWorld_x002e_test –>
This is a nested Hello, World! with global scope:<br/>
<blockquote style="border: 1px solid black;">
  </blockquote>
Here's one with page scope.
<blockquote>
</blockquote>
<!– End component global_x002e_NestedHelloWorld –><!– End region global_x002e_NestedHelloWorld –>

Done.

Basically it seems that the rendering of <@regions> which are themselves within a <@region> causes the neseted template to render, and the content is placed into the wrong place in the parent template – instead of appearing in the <@region> it appears at the top of the template file.
You basically get a 'stack' of everything rendered at a nest-level greater than 1.
Another way of looking at it, is that it seems that once a @region is opened, further @region are immediately imported.

Am I doing something wrong? My gut feeling is that it wasn't meant to be used this way, and that the @component directive is the answer.

Thanks for reading.

Outcomes