I have committed some JavaDoc clarifications regarding CustomStateKey
and CustomStateScope.


Wednesday, April 18, 2018, 4:07:05 PM, Daniel Dekany wrote:

> Wednesday, April 18, 2018, 4:06:27 AM, Woonsan Ko wrote:
>
>> Sorry for late reply. Please see my comments inline.
>>
>> On Mon, Apr 9, 2018 at 4:14 PM, Daniel Dekany <ddek...@apache.org> wrote:
>>> Monday, April 9, 2018, 8:34:27 PM, Woonsan Ko wrote:
>>>
>>>> Hi,
>>>>
>>>> While trying to implement directives to replace Spring MVC select,
>>>> options and option tags [1], I'm wondering what is the best to nest
>>>> options or option directive inside form directive.
>>>
>>> Or, you mean the "select" directive?
>>>
>>>> One straightforward option is:
>>>>
>>>> <@form.select 'user.favoriteSport'; form>
>>>>   <@option form value="NONE" label="--- Select ---" />
>>>>   <@options form items=sports />
>>>> </@form>
>>>>
>>>> As we don't have something like
>>>> javax.servlet.jsp.tagext.TagSupport#findAncestorWithClass(Tag, Class)
>>>
>>> Yeah, and we should have that. This is something that's missing from
>>> FM2 for a long time too... it's in my "most frequently missed
>>> features" FM2 TODO list. Maybe in 2.3.29.
>>>
>>>> (bottom to top), we can pass the form directive model to the nested
>>>> content like org.apache.freemarker.spring.model.BindDirective does
>>>> already (top to bottom).
>>>
>>> No way, that's way too awkward for the user (especially if you
>>> consider factoring out <@option ... />-s into macros). For now you
>>> should just use Environment.getCustomState(CustomStateKey) to maintain
>>> some state object where you keep track of the current context. (The
>>> main problem with that feature is that there's no template language
>>> feature to access it. Like you can't write two macros that exchange
>>> information through that, purely in the template language. But in your
>>> case that's not a problem, as you implement everything in Java.)
>>
>> I want to make the select directive model accessible from a nested
>> options or option directive model. So I was thinking of something like
>> the following in the select directive:
>>
>>         // create a custom state key to return this
>>         final CustomStateKey<SelectTemplateDirectiveModel>
>> selectCustomStateKey = new
>> CustomStateKey<SelectTemplateDirectiveModel>() {
>>             @Override
>>             protected SelectTemplateDirectiveModel create() {
>>                 return SelectTemplateDirectiveModel.this;
>>             }
>>         };
>>         // pass the custom state key
>>         env.getCustomState(selectCustomStateKey);
>>         // execute nested content such as options or option
>>         callPlace.executeNestedContent(null, out, env);
>>         // snip
>>         // write output...
>>
>> Question is, how can I retrieve the selectCustomStateKey in the nested
>> option(s) directive?
>> Environment#getCustomState(CustomStateKey<T>) requires that the nested
>> directive should have the CustomStateKey instance already somehow.
>
> The CustomStateKey<T> JavaDoc says:
>
> /**
>  * Used with {@link CustomStateScope}-s; each subclass must have
> exactly one instance, which should be stored in
>  * a static final field. So the usual usage is like this:
>  *
>  * <pre>
>  *     static final CustomStateKey MY_STATE = new CustomStateKey() {
>  *         &#x40;Override
>  *         protected Object create() {
>  *             return new ...;
>  *         }
>  *     };
>  * </pre>
>  */
>
> That's why you know the key; it's *static* final value.
>
> The object that it stores should be something like a
> FreemarkerSpringScope (maybe not the best name, just a quick example),
> and it should have a mutable property like selectDirectiveInContext.
> The assumption is that generally there will be more such properties.
> Then you don't define a key for each such property, and doesn't get
> them individually with getCustomScope. Instead, you only have a single
> key, and you get your scope object with it. Everything else
> conveniently happens through the Java API of your scope object.
>
>> I wonder how to do that easily without any hacky solutions such as
>> thread local. servlet request attributes could be the last resort,
>> but doesn't sound good to me either. Could you shed a light here?
>>
>> Regards,
>>
>> Woonsan
>>
>>>
>>>> So, developers are needed to pass it along like the above example,
>>>> unless it is as simple as one-liner like the following:
>>>>
>>>> <@form.select 'user.favoriteSport' items=sports />
>>>>
>>>> Does it sounds good? Or do you have any better ideas?
>>>>
>>>> Regards,
>>>>
>>>> Woonsan
>>>>
>>>> [1] https://www.mkyong.com/spring-mvc/spring-mvc-dropdown-box-example/
>>>>
>>>
>>> --
>>> Thanks,
>>>  Daniel Dekany
>>>
>>
>

-- 
Thanks,
 Daniel Dekany

Reply via email to