Does spring.ftl (freemarker bindings) support nested paths? How? - spring-mvc

How can I write the freemarker templates like this:
<#import "spring.ftl" as s>
<#s.form path="object" action="/new.do" method="POST">
<#s.formInput "name"/> <!-- I want this resolved as "object.name" -->
<!--
100s of other properties...
-->
</#s.form>
instead of this:
<#import "spring.ftl" as s>
<form action="/new.do" method="POST">
<#s.formInput "object.name"/>
<!--
100s of other properties...
-->
</form>

You can bind the object like this:
<#s.bind "object"/>
Then you can use your first example
<#s.formInput "name"/>

As far as I can tell, spring.ftl doesn't support nested paths. It is conceivable that one could write one's own nestedPath macro that functioned similar to the nestedPath JSP tag. You'd probably need a bind macro that recognized it as well, and maybe more to get all the form input macros working.
Or, maybe it's possible to import and use the JSP tags themselves instead of spring.ftl or custom macros.

Related

How to prevent escape of html tags in Spring MVC?

I have some data inside my database with html tags like
<b>, <br>
But, when I try to store it into a model object and render it on a JSP, it is rendered with the tags. The tags are not evaluated.
Any idea on how to get my page to process those tags? Below is the code I use in my JSP.
<div class="col-xs-6 form-group">
<label>Comments</label>
${requestObject.comments}
</div>
Edit:
I tried the below code also, with no luck.
<c:out escapeXml="false" value="${requestObject.comments}" />
Database Content
<b>Oh Snap</b>
HTML Source
<b>Oh Snap</b>
I am expecting my text to be rendered bold
Oh Snap
Not sure whether this is what you are seeking, but this should allow HTML to be evaluted:
<%# taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<spring:htmlEscape defaultHtmlEscape="false" />
If you have Spring form or message tags, you can do: htmlEscape="false".
UPDATE:
Sadly, the c:out syntax will take precedence over the Spring tag on this but you can also try:
<spring:escapeBody htmlEscape="false">
<%=requestObject.comments%>
</spring:escapeBody>

Grails 2.5.0 - Render template in gsp only if the template exists

I'm using a layout where a number of javascript libraries are included at the bottom the file, just above the close of the body tag. What I want to do is add some custom javascript below them on various pages but not all pages. Is there some equivalent of
<g:render template="customjs"/>
I can use in the layout gsp that only renders the template if it exists and does not crash on pages without the _customjs.gsp?
The answer is here https://stackoverflow.com/a/3394720/1790092
If your controller name is "MyJsController"
Consider wrapping this code into a TagLib for better reuse
<g:set var="controller" value="myJs" />
<g:set var="template" value="customjs" />
<g:set var="patternResolver" value="${new org.springframework.core.io.support.PathMatchingResourcePatternResolver()}" />
<g:set var="pathPattern" value="grails-app/views/${controller}/_${template}.gsp" />
<g:if test="${patternResolver.getResources(pathPattern)}">
<g:render template="/${controller}/${template}" />
</g:if><g:else>
not found!
</g:else>

How to render a template page by calling its method from TAL portlet(##manage-portlets)

How do I call a method which is in the filesystem from a TAL Portlet (made available by collective.portlet.tal)?
This is how I did it: I defined a new BrowserView (createPictMenu.py in my case) and then registered it as the renderer for a new portlet component:
class AddressTAL(BrowserView)
def my_address()
address_bar = ViewTemplatePageFile('templates/address_left.pt') # this
is the page template I want for my new portlet.
And in configure.zcml:
<plone:portlet
name="collective.portlet.tal.TALPortlet"
interface="collective.portlet.tal.talportlet.ITALPortlet"
assignment="collective.portlet.tal.talportlet.Assignment"
view_permission="zope2.View"
edit_permission="cmf.ManagePortal"
renderer=".browser.createPictMenu.AddressTAL"
addview="collective.portlet.tal.talportlet.AddForm"
editview="collective.portlet.tal.talportlet.EditForm"
/>
Then I went to localhost:8080/myproject/##manage-portlets and selected the TAL Portlet option from the Add Portlet dropdown list. I informed title as address and for description I inserted the snippet below to call address_tal():
<span tal:define="global li view/myaddress">
<span tal:replace="structure li" />
</span>
Unfortunately, it didn't work. Please help.
You should have registered your class AddressTAL with a browser:view directive, not a plone:portlet one. Like this:
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser">
<browser:page
name="address-view"
class=".browser.createPictMenu.AddressTAL"
for="*"
permission="zope2.View"
/>
</configure>
And then call it with:
<div tal:define="my_address python:context.restrictedTraverse('##address-view').my_address()" >
Your method returns <span tal:content="my_address" />
</div>
Or:
<div tal:define="address_view context/##address-view" >
Your method returns <span tal:content="address_view/my_address" />
</div>
It's of very little information or matter that the method is on the file system. That's where it should be. Having it in the ZODB is possible but a bad idea.
But there are many types of methods, and how you call them from TAL differs.
You can have what in the ZMI is called "Script (Python) methods" that are accessed through portal_skins, you can have methods on content objects and you can have methods on views. These are all callable from TAL.
For methods that are neither of these, you will have to create a method of the above type that you can call, which in turn then calls the method you want to call. For a portlet the obvious place to create that method is by adding a method on the Renderer, which is a type of view, and which you can call from the portlets template.
In your case, the method you want to call is a method on the renderer already. That means you just call it.
<p tal:content="view/myaddress" />
Note that you have forgotten the self parameter in the definition. Also, please follow PEP8.

How to get viewlet by an plone object url

I'm trying to get viewlet belowcontenttitle for an object by its URL.
Something like below, but using object URL instead of 'plone'.
id="viewlet-below-content-title" tal:content="structure provider:plone.belowcontenttitle"
Can I do it using restrictedTraverse?
Your best bet is to create a new view for the belowcontenttitle viewlet; template:
<div tal:content="structure provider:plone.belowcontenttitle"/>
registered with:
<browser:page
for="*"
name="belowcontenttitle"
permission="zope2.View"
template="template_shown_above.pt"
/>
Then you can use that view with a simple traverse:
<div tal:replace="structure context/path/to/other/object/##belowcontenttitle" />
This looks up the view in the context of the other object; the template is rendered and returned, replacing the div.

Meteor Template Inside Script Tag

I want to fill a script type="text/html tag with a Meteor template.
So, this is an odd thing to do, I know. Half the reason I want to do this is because Cloud9 can't tell the difference between JS script tags and HTML script tags, and its syntax highlighting and tag-completion breaks when you try to write HTML in script tags. The other half of me is just curious to see if this is possible, because an ugly-as-sin workaround exists.
So this:
<body>
<script type="text/html" id="test">
{{> test}}
</script>
</body>
<template name="test">
<span>Test</span>
</template>
Produces this:
<script type="text/html" id="test">
<!--label:YRgyaMH8-->
</script>
Anyone have a way to force it to render the template, instead of what looks like evaluate the name as a comment?
Submitting another answer b/c I'd like to keep my previous one just for the records. I think this approach will work better though.
Inside your html, you're going to define two sections. The first is where you're going to place your template code. It will go inside a comment inside a plain div tag. The second is where the template will be placed for Knockout to consume. It looks like this:
<template name="koTemplate">
<div id="myTemplate">
<span>Here is my template with children</span>
</div>
<script type="text/html" id="test"></script>
</template>
Then in your client JS code, you're going to add a callback to run when the template is rendered
Template.koTemplate.rendered = function () {
// Get the first node, then get the content inside of it
var templateHtml = this.firstNode.innerHTML;
// Remove the element so it doesn't get rendered
this.firstNode.parentNode.removeChild(this.firstNode);
// another option is to surround the contents inside the template w/comments, but that loses syntax highlighting
// Get the target node for placing the template in
var templateNode = this.lastNode;
// place the content from the original node to the target node
templateNode.innerHTML = templateHtml;
};
This will basically get the content of the template, remove the template, then place it inside the script tags. The result will look like:
<script type="text/html" id="test">
<span>Here is my template with children</span>
</script>
I would suggest moving away from using the script tag and instead use some other generic tag that Cloud9 won't treat as JS and Meteor won't fudge with. Using the example in my comment on the question, it would look something like this:
<div id="template">
<!--<span>test</span>-->
</div>
And in your JS you would parse that:
var template = document.getElementById('template').firstChild.nodeValue,
result = parseTemplate(template, values);
That's the basic idea. You'd have to convert it over to Knockout's template parsing after getting the result.

Resources