User defined directives in Freemarker

2011-12-22
2012-09-09
  • In my experience, macros / user-defined directives in freemarker (@xxx/) are
    good choices in building re-usable application-specific UI components. Screens
    solve the re-usability problem to a very large extent, but at a less granular
    level. Macors / directives do it at a level, lower than Screens and are hence
    still relevant in the design of applications. Screens cannot be a complete
    replacements of user-defined variables / macros Given this, I am trying to
    figure out the best way of designing a moqui app. If I were to use User
    defined directives, how would I tell Moqui the implementation classes of these
    directives, so that they are readily available in any ".ftl" templates being
    used (much like *Transforms.properties or handler definitions in
    controller.xml of Ofbiz). I havent seen any configuration within moqui that
    allows me to configure user-defined directives for freemarker. Any thoughts on
    this?

     
  • David E. Jones
    David E. Jones
    2011-12-22

    Are you trying to import macros, or add user-defined directives?

    For macros you can just include the macros FTL file from your FTL file. You
    can even do this with the Moqui XML Screen macros FTL file (using a
    classpath:// location).

     
  • David E. Jones
    David E. Jones
    2011-12-22

    BTW, for user-defined directives implemented in Java you can do something like
    this in the FTL file:

    <#assign upper = "com.example.UpperDirective"?new()>

    For an example of this, see:

    http://freemarker.org/docs/pgui_datamodel_directive.html

     
  • Interesting, thanks David...

     
  • Actually, I am planning to build user-defined directives / macros that will be
    used by end-users/business users in their "contents". This way they would be
    managing the content (which could potentially include page-specific / dynamic
    data). The choice of macros / user-defined directives is obvious. These are
    simple, and look very similar to the xhtml mark that they use in the content
    - which means all the macros / user-defined directives need to be available to
    them without actually "importing" them - primarily like a pre-imported
    library. It would be nice if there is a way to do this with least hassle to
    the business user.

     
  • David E. Jones
    David E. Jones
    2011-12-23

    In general the more you constrain things the more customization you'll need to
    do, unless constraints are contradictory and then it's over-constrained and
    the size of the solution set drops to zero.

    In this case you can probably do it. The context for the FreeMarker template
    includes is inherited from the context of the XML Screen that includes it. In
    FreeMarker macros and even user-defined directives written in Java are just
    objects in the context, so you can use XML Screen actions to prepare them.

     
  • Pardon my comprehension, but I did not understand what you were implying in
    your first para:

    In general the more you constrain things the more customization you'll need
    to do, unless constraints are contradictory and then it's over-constrained and
    the size of the solution set drops to zero.

    I understand that macros and user-defined directives are just objects in the
    context stack and its not very difficult to put them there. But, my problem is
    - I have the need of using the macros in a lot of ftls across the application.
    It would be very ceremonial (and unwieldy at times) to include the macro ftl
    in each of those screens. What will be the downside of adding an
    implementation like

    org.ofbiz.base.util.template.FreeMarkerWorker.addAllOfbizTransforms()
    

    For macros, can we not auto-include the library.ftl so that, in <render- mode=""> across the application, we dont need to
    "include" it again?

     
  • David E. Jones
    David E. Jones
    2011-12-23

    You can do whatever you want, you can even modify the Moqui code if you want.
    However, if you use this forum as a substitute for your own research and
    problem solving, please don't expect me to provide such services for free.

    When setting it up in a screen definition you don't have to do it in every
    screen in your application, just in the root screen of the app since the
    context from the root screen is inherited by all screens under it.