Re: Nested Java directives - best practice on how to make values available to inner directive?

Daniel Dekany <[email protected]>
Newsgroups gmane.comp.web.freemarker.user
Message-ID <[email protected]>
Thursday, January 31, 2008, 4:51:14 AM, Alistair Israel wrote:

> I've searched the mailing list archives up to a several months back
> but couldn't find anything on this.
>
> What I'm basically trying to do is write a custom "@form" directive in
> Java. Within the @form directive's body, I'd like to have various
> "@input" directives (also written in Java). As to why I would want to
> do this in Java rather than as a regular macro - I want the directives
> to insert Javascript validation code based on annotations on the form
> bean object.
>
> So, conceptually, I'd like to be able to say:
> <@form name="someForm" action="someAction">
> <@input type="text" property="name"/>
> </@form>
>
> I'd like to make the value of @form name ("someForm") available to the
> @input directive (so the @input directive can lookup the name from the
> template model, inspect the class, find annotations and so on and so
> forth.
>
> At first I tried adding a local variable via
> Environment.setLocalVariable() in my directive's execute(). This fails
> with "Not executing macro body".
>
> Delving through the code, it's apparent that while a custom macro
> directive has currentMacroContext (that lets us define/access local
> variables through the ".locals" special variable), a custom Java
> directive doesn't. Why is that so?

I'm not too familiar with the source-code, but I suppose because Java
language already has its own system of variables (like fields, local
variables on the stack, TLS, etc). Anyway, what you are looking for is
called "parent-child communication" or "parent-children communication"
on this list. But this feature was only added in 2.4, which is
unreleased and unstable. Also I don't think even there this was solved
when the "parent" is a TemplateDirectiveModel (or
TemplateTransformModel) call.

To fellow FM developers:

- Given that 2.4 will not be released in the foreseeable future, and
  even then it will not be 100% BC, parent-children communication
  definitely should be backported to 2.3.x. This is again a very basic
  feature for a template language, shame that it isn't there for
  years. (Reminds me to the history of #nested...) Would backporting
  be difficult?

- Can TemplateDirectiveModel and TempateTransformModel calls
  participate as parents in the current trunk? (And as children for
  that mater?) I don't think so... of course, they should be able to.
  Java and FTL are just to languages to implement custom directives.

> So, I was able to make it work by using a global variable instead
> (Environment.setGlobalVariable()). The only thing that bothers me is
> that it really doesn't need to be a global variable - the scope of the
> value of the current form name is just that: the current form. I could
> conceptually overwrite or define a global variable that other
> templates depend upon for other purposes.

As far as I know that's still the best workaround you can do right
now.

> [ Aside: perhaps if there was some way to use namespaces to
> distinguish my directives (as well as any 'local' variables they need)
> it wouldn't bother me as much. However, using
> Configuration.setSharedVariable (via Spring's FreeMarkerConfigurer)
> only lets me provide a simple string name - not sure if any prefixes
> (e.g., "my.form") will be interpreted as a namespace.

They won't be (unless the Spring guys did some big trick...), since a
shared variable is always a top-level variable, for technical reasons.
Of course, the value of the shared variable can be a map or JavaBean
or something other structural, so if "my" is the name of the shared
variable, and it's value has a "form" subvariable (JavaBean property
or whatever), then you have that my.form.

> This, in fact, was a separate question I meant to ask the list. ]
>
> How would the members of the list suggest I do this - make a value
> local to my parent directive available to nested directives - short of
> explicitly passing them?

I say, use globals for now... Which can be even more irritating when
you have directives that can be nested into the same kind of directive
(like: <@ul bullet="box.gif">...<@ul bullet="arrow.gif">...</@ul>...</@ul>)

> - Alistair A. Israel

-- 
Best regards,
 Daniel Dekany


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.