In my Grails 1.3.7 app, I'd like to use a template to factor out surrounding HTML from views. But, GSP variable assignment isn't working in the contained body(). How can I do something like the following?
_aTemplate.gsp:
<div class="example">
<% out << body() %>
</div>
aView.gsp:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="layout" content="main" />
</head>
<body>
<g:set var="foo" value="${42}"/>
<% assert foo == 42 : foo %>
<tmpl:/aTemplate>
<g:set var="bar" value="${6}"/>
<% assert bar == 6 : bar %>
</tmpl:/aTemplate>
</body>
</html>
The assignment of bar doesn't work: the bar assertion fails, when I get http://localhost:8080/myApp/aView.gsp
org.codehaus.groovy.grails.web.taglib.exceptions.GrailsTagException:
Error executing tag<g:render>: Assertion failed:
(bar == 6). Values: bar = null
at /Users/jbeutel/proj/grailsSandboxes/myApp/grails-app/views/aView.gsp:13
How can I make the template body() work as normal?
Alternatively, is there some other way I could factor out surrounding HTML while keeping it balanced? My use case isn't at the top level, so I haven't tried using layouts. The variable assignment works if I use a TagLib closure instead of a template file, but I don't want to put a lot of HTML into a closure, so I would need to put unbalanced HTML into template files anyway (i.e., separate templates before and after the body). Is there a better way?
You can pass variables from your .gsp into shared templates that it can then consider as follows. I do this to hide a 'login' link in my common header if they are on the login.gsp page
<g:render template="/layouts/header" model="['hidelogin':true]"/>
then in the _header.gsp
<g:if test="${!hidelogin}">
//show your login link
</g:if>
Related
I have been searching for this all over, but can not find an answer or example.
Can a Ractive template be used to construct head elements that are consistant across pages, and can that be loaded from a separate file?
For example: all html, head, and title tag info is loaded via a referencable template from an external file into an index page.
+html+
+head+
+title+
+/title+
+/head+
And if so, how do you do it? As I try to wrap my head around it, jquery and ractive.js would need to load. Is there a different/better solution?
It is possible. But it's not practical and it raises other issues.
Here's a basic implementation that shows how <head> can be templated but without concentrating on putting the template in an external file. This works for me in Chrome and IE.
<html>
<head id="output"></head>
<script id="template" type="text/html">
<title>{{ title }}</title>
</script>
<script type="text/javascript" src="ractive.min.js"></script>
<script type="text/javascript">
var ractive = new Ractive({
template: "#template",
el: "#output",
data: {
title: "This is the title"
}
});
</script>
<body>
...
</body>
</html>
You'll run into problems with this approach because the head elements won't be loaded until after the page has loaded and Ractive kicks in. This may cause the following problems:
Search engines might not be able to read the page title and meta tags
Any javascript you need to load into <head> may not work (I tried some simple examples and was able to get the javascript to run but it failed to reference any elements in the body. Maybe it's a context issue and maybe Ractive has support to overcome this but this is an area I'm unfamiliar with.)
If you require valid HTML, this probably won't work for you because script tags can't be direct children of <html>, and <head> is supposed to have <title> as a direct child.
You're better off using a server-side solution to template <head>.
I am using gulp-file-include to build my html pages using some partials & templates. By using context variables, I can customize each meta headers. However, don't know how I could include a line only if a context variable exists, as the "##else" statement doesn't seem to exist.
My parent HTML looks like:
##include ('_header.html', {
"title":"my page",
"description": "description",
"canonical":"http://www.sourcefromquote.com" })
<body>
A wonderful Page
##include ('_footer.html")
</body></html>
I was thinking to use a _header.html close to something like that :
<html>
<head>
<title>##title</title>
<meta name="description" content="##description">
##if (canonical) { <link rel="canonical" href="##canonical" /> }
</head>
If the "canonical" variable is not set in the the parent HTML, it throws an error (canonical is not defined).
I guess I could include the full tag in a variable and forget about the ##if, but that would not be as clean as expected !
Any ideas ?
Thank you in advance.
In the head, you enter:
##if (context.canonical) {<link rel="canonical" href="##canonical" />}
In the file that includes the header you enter:
##include('_head.html', {
"canonical" : "https://www.website.com/canonical-link.html"
})
I have a pyramid application with multiple views each depending on a single mako template. The views are quite complicated and bug free, so I don't want to split or merge views, and by extension, the corresponding templates.
However, I would like a single view to represent all the others. Merging all the pyramid views and templates is practically not an option.
For example, I have a login view & template and a signup view & template. Now I want my root page to contain both of them. Both login and signup inherit from base.mak, which contains common scripts and style sheet imports. The following is a pictorial representation of the mako import structure I want.
base.mak
/ \
login.mak signup.mak
\ /
root.mak
Alternatively, I tried chaining them as such:
base -> login -> signup -> root
However, I think that the views no longer talk to their respective templates.
My problem comes in when I do the 3rd chain (login.mak -> signup). I'll post analogous and extract code below, since my full code is a bit long (If more code is needed, feel free to shout).
base.mak:
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>
${next.title()}
</title>
#Imports
${next.head()}
</head>
<body>
<div id = "content">
${next.body()}
</div>
</body>
</html>
login.mak:
<%inherit file="base.mak"/>
<%def name="title()">
${next.title()}
</%def>
<%def name="head()">
${next.head()}
</%def>
<div id="login">
<div id="message">
${sMessage}
</div>
<div id="form">
<form action="${url}" method="post"> <--- url returned in views.py
...
</div>
${next.body()}
signup.mak:
<%inherit file="login.mak"/>
<%def name="title()">
</%def>
<%def name="head()">
</%def>
<div id="box">
...
</div>
Now my problem here is that my url returned from my views is undefined when I try to inherit as in above.
Then of course if I get this working, adding base.mak to to inherit from signup should be trivial.
I assume that there is a simple fix for this, but I can't find an example/explanation on how to do this in pyramid, where the templates actually do stuff.
Alternatively, Is there another way to bring together multiple pyramid views and templates into a single view?
Ok, I figured it out. One has to use mako's <%include/>, and then there is no complicated inheritance structure. So, now my files look like this:
root.mak
<%inherit file="base.mak"/>
<%def name="title()">
Welcome
</%def>
<%def name="head()">
</%def>
<%include file="login.mak"/>
<%include file="signup.mak"/>
login.mak:
<%inherit file="base.mak"/>
<%def name="title()">
</%def>
<%def name="head()">
<link rel="stylesheet" type="text/css" href="${request.static_url(...
</%def>
<div id="login">
<div id=".....
</div>
and the same structure with signup.mak. base.mak still looks the same as in the question above.
Now, if you're using pyramid (I assume another framework will work the same), and you have views that receive and pass information from forms for example, then turn them into normal functions (without #view_config(renderer='path/file.mak') and place their functionality into the parent view function, in my case root. In other words:
#view_config(renderer='pyramidapp:templates/root.mak',
context=Root,
name="")
#forbidden_view_config(renderer='pyramidapp:templates/root.mak')
def root(self):
xLoginRet = login(self)
xSignupRet = signup(self)
#logic and functionality for both, return stuff to go to base.mak
I am attempting to create a template using Smarty for php. I would like the template to be reusable so I inheriting it and substituting values using blocks. This works fine except when I need to access these block values in sub-templates. I am calling these sub-templates using smarty's {include} function.
Example:
Template-Parent (template.tpl):
<html>
<head>
{include file=sub_template.tpl}
</head>
<body>
{block name=title}No Title Provided{/block}
</body>
</html>
Sub-Template (sub_template.tpl)
<title>{block name=title}No Title Provided{/block}</title>
Template-Child (template_child.tpl)
{extends file="template.tpl"}
{block name=title}My Website!{/block}
When I view the site, the output is:
<html>
<head>
<title>No Title Provided</title>
</head>
<body>
My Website!
</body>
</html>
After doing some reaserch I did see a note on smarty's website about enclosing {include} functions in dummy {block} tags but have had varied levels of success getting this to work.
Note:
If you have a subtemplate which is included with {include} and it
contains {block} areas it works only if the {include} itself is
called from within a surrounding {block}. In the final parent
template you may need a dummy {block} for it.(http://www.smarty.net/docs/en/advanced.features.template.inheritance.tpl)
Due to this, I have tried:
<html>
<head>
{block name=dummy}{include file=sub_template.tpl}{/block}
</head>
<body>
{block name=title}No Title Provided{/block}
</body>
</html>
This seems to work until I make any change to sub-template. As soon as a change to the sub-template is made, it once again stops responding to the block values set in the child.
Have I misunderstood what the notice was referring to about placing the {include} in dummy block tags or is this a bug with smarty? I am not currently using caching but my other thought was that maybe this is a sub-template caching problem.
Any insight would be greatly appreciated, thanks!
It is true that these templates are compiled and cached into the templates directory. This is why clearing the templates directory temporarily fixed the issue. The template caching is different than the explicit caching that smarty also supports. I have found that the template caching can be overridden with:
$smarty->compile_check = true;
$smarty->force_compile = true;
This allows changes to the template to be made with out needing to delete the cache after change while in development.
in my default-layout.hamlet:
!!!
<html lang="en">
<head>
<meta charset="utf-8">
<title>#{pageTitle pc}
^{pageHead pc}
<body>
<div id="main">
<div id="header">
????
<div id="content">
^{pageBody pc}
from a handler function, I need to replace the ???? above with some HTML contents.
how is this done?
thanks for any input.
EDIT:
I am looking for functionality similar to, for example, django's template blocks. I can define a block inside a template and the handler that uses this template for rendering, can fill in the template's blocks with the needed contents. Right now, yesod has effectively a single block in a template's body. that "defined" by the call ^{pageBody pc}. I know I can build up the output generated by pageBody any way I want using addWidget etc., but right now I will need to output my <div id="header"> and <div id="content"> too and I want to avoid that because all my handlers will have to output these div's to have the same markup structure in all the pages.
I think the answer is to define a function besides defaultLayout. The only thing that's magical about defaultLayout is that subsites (e.g., auth) and error messages use it by default. But you could define a "myDefaultLayout" that takes the other pieces of content you want. You could even define a helper function that wraps up the extra blocks into a single block and then passes that to defaultLayout.