On Tue, Aug 29, 2017 at 10:40 AM, Daniel Dekany <[email protected]> wrote:
> Tuesday, August 29, 2017, 3:03:02 PM, Woonsan Ko wrote:
>
>> On Tue, Aug 29, 2017 at 5:00 AM, Daniel Dekany <[email protected]> wrote:
>>> Tuesday, August 29, 2017, 5:25:31 AM, Woonsan Ko wrote:
>>>
>>>> Hi Daniel,
>>>>
>>>> Thanks for the remarks and hints! Please see my question inline.
>>>>
>>>> On Sat, Aug 26, 2017 at 4:50 AM, Daniel Dekany <[email protected]> wrote:
>>>>> Saturday, August 26, 2017, 10:44:03 AM, Daniel Dekany wrote:
>>>>>
>>>>> [snip]
>>>>>>   <#macro foo>
>>>>>>     <#local status = 'blah'>
>>>>>>     <@spring.bind "user.name">
>>>>>>       ${status.value} <#-- Means 'blah'.value, won't work -->
>>>>>
>>>>> To clarify, here I have assumed that spring.bind calls
>>>>> env.setVariable("status", ...) internally. Then the local with the
>>>>> same name shadows that tempolate-namespace scoped variable.
>>>>
>>>> It seems working with env.setVariable("status", ...):
>>>>
>>>>     // Excerpt from
>>>> https://github.com/woonsan/incubator-freemarker/blob/feature/FREEMARKER-55-2/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/BindDirective.java
>>>
>>> Looks good. But what are your thoughts on using a nested content
>>> parameter instead?
>>
>> I'm sure I'm missing something or in misunderstandings. I want to try
>> the option using a nested content parameter instead, but I don't know
>> how to do that. ;-)
>> Ideally, <@spring.bind ... /> directive needs to set a local variable
>> called "status" or whatever (if the variable name can be given by a
>> nested content parameter) and developers should be able to use the
>> status variable ("status" or whatever) somehow inside the directive.
>> So, my assumption was, if the parameter is given to the directive, I
>> can probably fill in a variable somehow by resolving the bind status
>> object. I guess I'm totally ignorant on how nested content parameters
>> work with directives...
>
> A directive can't create a nested content variable. The caller can
> declare a nested content parameter, like `<@spring.bind ...; status>`,
> and then the directive can specify the actual value of that parameter
> when it calls the nested content with
> `callPlace.executeNestedContent`. (Of course it's likely that the
> caller will chose a shorter name, like `s`; see earlier mails.)

Ah, I think I now understand it!
So, for example, if I do this:

  callPlace.executeNestedContent(new TemplateModel [] { status }, out, env);

, then the nested template may read/use the passed status object by
referring to by the name (e.g, 's') given by themselves, right?

I totally overlooked the fact that I can pass arguments to the nested
content when invoking #executeNestedContent().
I'll try it out again. I personally it is better to use nested content
parameters instead of #setVariable() as they are local.
The following example seems a lot better than the JSP taglib to me:

<@spring.bind "user.email"; status>
  <input type="text" name="email" value="${status.value!}" />
</@spring

Thanks again for the advice!

Cheers,

Woonsan

>
> You may wonder if we should allow the directive to create a nested
> content variable. I think it's a probably a quite bad library design
> if you need that. Creating variables without the caller seeing that
> makes understanding what's going on significantly harder. Worse, that
> magically appearing variable can hide a variable from a higher scope.
> If the caller doesn't ask for the creation of the variable, then that
> variable should be under the `spring` namespace. Of course that
> (`spring.status`) would be more verbose than using a nested content
> parameter, so it doesn't make sense in this case.
>
>> Regards,
>>
>> Woonsan
>>
>>>
>>>> Another question: is it okay to assume that I have a
>>>> DefaultObjectWrapper when this directive is executed and throw an
>>>> exception otherwise?
>>>
>>> At the moment it's enough to expect it to be an
>>> ObjectWrapperAndUnwrapper. FreeMarkerServlet also requires that BTW.
>>> I'm not sure if in the future expecting DefaultObjectWrapper will be
>>> necessary, but hopefully not. (Custom JSP tag support expects a
>>> DefaultObjectWrapper at the moment, for wrapping JSP functions.)
>>>
>>>>> [snip]
>>>>>> With nested content parameter it's also more obvious what's going on,
>>>>>> and if you chose a shorter name it's not that verbose either:
>>>>>>
>>>>>>   <@spring.bind "user.name"; s>
>>>>>>     ${s.value}
>>>>
>>>> If I choose to use nested content parameter instead of having
>>>> env.setVariable() calls, how can I get access to the parameter, s?
>>>> Can I access it through any argument of the #execute() method in the
>>>> Java code? Any example java code using nested content parameter?
>>>
>>> I'm not sure what you try to achieve. As the nested content parameter
>>> is local to the nested content, similarly as a local variable is local
>>> to the method body in Java, where do you want to access `s` from, and
>>> why?
>>>
>>>> Thanks in advance,
>>>>
>>>> Woonsan
>>>>
>>>>> [snip]
>>>>>
>>>>> Eh... of course the comment is outdated here. It will work in this
>>>>> case. `s` can't be hidden by anyone there, it wouldn't mater if we had
>>>>> <#local s = 'blah'> for example.
>>>>>
>>>>> --
>>>>> Thanks,
>>>>>  Daniel Dekany
>>>>>
>>>>
>>>
>>> --
>>> Thanks,
>>>  Daniel Dekany
>>>
>>
>
> --
> Thanks,
>  Daniel Dekany
>

Reply via email to