Smarty template inheritance only provides local scope variables? - smarty

Using the latest version of Smarty 3 with template inheritance I'd like to set a variable in a child template and use it in the parent:
list.tpl
{extends file="page.tpl"}
{block name="head"}
{$page_var = array("abc", "xyz")}
{/block}
{block name="content"}
<div>...</div>
{/block}
page.tpl
<!DOCTYPE html>
<html>
<head>
{block name="head"}
{$page_var = array()}
{/block}
{mytemplatefunc foo=array("bar") + $page_var}
...
The main page template initializes a variable and the child page sets the variable if needed. The main page template would then use that variable when calling a template function. But $page_var is always empty. It's as if the scope of the template variables are always local. Is going back to {include} the only solution?
I've tried {assign scope='global'} and {assign scope='parent'} even though they are intended for includes. I also tried using my own static class methods and variables (to hang onto the value) but it never works. And elsewhere it's been suggested trying to use variables outside of {block} but that goes directly against the documentation.

Why do you redefine $page_var in the Template Extension (list.tpl)?
Have you tried adding values to the original $page_var instead?
So instead of
$page_var = array("abc", "xyz")
you could do
array_push($page_var, "abc", "xyz")

Related

Thymeleaf custom dialect - nested attributes

I would like to ask if it is possible to have nested attributes in HTML tag which can reuse result of previous one. For example
<p custom:one="some text to process" custom:two="process result of custom:one">
where custom:one can be used standalone but custom:two have to be used with custom:one. The final result will be produced by custom:two
if I got you right, you can do it with local variables
You need to specify th:with to declare a variable.
Note that the declared variable is available within the element.
<div th:with="newValue = 'Hello ' + ${val}">
<span th:text="${val}">One</span>
<span th:text="${newValue}>Two</span>
</div>
Let me know if that's what you're looking for.

how to use a variable from another .ftl in freemarker

I'm trying to use a defined variable in a second template to have the same output in the current one.
template 1:
[#if definition.name=="configMINIMAL_STACK_SIZE"]
[#assign valueMinimalStackSize = definition.value]
[/#if]
Second template:
#define configMINIMAL_STACK_SIZE ((uint16_t)${valueMinimalStackSize})
how could I have the same output of "valueMinimalStackSize " in the second template please ?
Thanks for the help
You could have a template that sets these variables, let's call it "commons.ftl", and then use <#include "commons.ftl"> at the beginning of other templates.

pass thymeleaf variable as parameter in method

I concatenate the state and my stateCounter to one String. This is my value for my HashMap which stores all the States but I don't get it to to put this variable in my method.
<span th:with="stateName=${item.state} + ${item.stateCounter}"></span>
<td th:text="${{order.getStateRepository().get(${stateName})}}"></td>
Some notes:
(1) Using a <td> tag suggests you are also using a <table>. Having a <span> tag next to a <td> tag inside a table is not valid HTML (assuming this is what it looks like in your template - maybe this is just a copy/paste thing).
(2) If your order object has a stateRepository field, then you don't need to use a getter order.getStateRepository(). You can just use the field name order.stateRepository. You are already doing this with item.state, for example. Thymeleaf will figure out from the field name how to use the related getter - e.g. item.getState().
(3) The scope (availability/visibility) of a local variable, such as stateName in th:with="stateName=${item.state} is limited to the tag in which it is declared, and also to any sub-tags. You do not have any sub-tags in your <span> - therefore the variable is not visible anywhere outside of your span. So, it is not available inside the <td> tag.
(4) Do you need to use a local variable in your example?
Instead of using get(stateName), you can use the expression referred to by stateName directly:
get(item.state + item.stateCounter)
So overall, this should work (based on the assumptions above):
<td th:text="${order.stateRepository.get(item.state + item.stateCounter)}"></td>
Maybe you do need the local variable, of course. It may depend on the wider context of the Thymeleaf template.
You are trying to use local variable. It will work if you try as follows:
<div th:with="stateName=${item.state} + ${item.stateCounter}">
<td th:text="${order.getStateRepository().get(stateName)}"></td>
</div>

Template inheritance: remove block that was added in grandparent and appended to in parent

In a smarty template, I have three templates:
base.tpl
{block name="myBlock"}
base
{/block}
child.tpl
{extends file="base.tpl"}
{block name="myBlock" append}
child
{/block}
grandchild.tpl
{extends file="child.tpl"}
{block name="myBlock"}{/block}
When rendering grandchild.tpl, the output is
base
So the grandchild-template wants to replace the content of whole block, but only replaces the appended part. How do I delete the whole block?
Related: How to remove content appended to block in parent template?
The solution here is in child.tpl change block definition from:
{block name="myBlock" append}
child
{/block}
into:
{block name="myBlock"}
{$smarty.block.parent} child
{/block}

Provide sass variables definitions on command-line

Is there a standard, or simple, way to define sass variables on the command line, or pass them from the environment? What I am doing is trying to create to different CSS files from a single SCSS source file. Each output file will be specialized for a certain target device and included from the HTML page with media queries.
Update: It looks like this may not be enough. The #if syntax doesn't actually allow conditional sass blocks, only conditional CSS blocks. This means even if I can define a variable it wouldn't allow me to do different processing in the file. Any ideas?
Use SASS custom functions. A complete working example below.
styles.sass:
$primary_color: getenv("SASS_VAR_PRIMARY_COLOR", white)
body
background: $primary_color
sass_functions.rb:
module Sass::Script::Functions
def getenv(name, default)
assert_type name, :String
value = ENV.fetch(name.value, nil)
if not value
return default
end
begin
Sass::Script::Parser.parse(value, 0, 0)
rescue
Sass::Script::String.new(value)
end
end
end
Command line:
SASS_VAR_PRIMARY_COLOR='#123456' sass -r ./sass_functions.rb styles.sass styles.css
If you use Compass, you may put module Sass::Script::Functions directly into config.rb and compile the styles with:
SASS_VAR_PRIMARY_COLOR='#123456' sass --compass styles.sass styles.css
The facility I needed is simply not in SASS. Even if you could define variables on the command-line the "if" facility is insufficient to actually do conditional blocks in the style sheet.
Instead I've resorted to the old stand-by of M4. I simply preprocess the SASS with M4, doing command-line options and full conditional blocks.
I couldn’t find a way to specify sass variables from the command line but you can mimic this behaviour by creating multiple specialized SCSS files that import a base SCSS file.
For example:
// base_style.scss
#debug "* Format = #{$format} *";
#if $format == 1
{
$body-font-family: "Palatino" !global;
}
#else if $format == 2
{
$body-font-family: "Arial" !global;
}
#else
{
#warn "Undefined format";
}
body
{
font-family: $body-font-family;
}
// style_1.scss
$format: 1;
#import "base_style.scss";
// style_2.scss
$format: 2;
#import "base_style.scss";
Then from the command line:
sass style_1.scss style_1.css
sass style_2.scss style_2.css
Note that you can also specify the rules for different target media in one single (S)CSS file with distinct media queries in it. In this case, you only need one source file.
I'm pretty sure I understand what you're saying. Sometimes it's good to group things together in a .scss file that would end up in conditional stylesheets so you can find them easier.
At the moment there's still not the ability to compile a sass stylesheet in to separate stylesheets without grouping all your conditional rules in to a partial.
However, using Paul Irish's suggestion to conditionally add a class name to the html tag: http://paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/
<!--[if lt IE 7 ]> <html class="ie6"> <![endif]-->
<!--[if IE 7 ]> <html class="ie7"> <![endif]-->
<!--[if IE 8 ]> <html class="ie8"> <![endif]-->
<!--[if IE 9 ]> <html class="ie9"> <![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--> <html class=""> <!--<![endif]-->
You could do something like this:
.something {
regular rules...
.ie8 & {
conditional rules...
}
}
That way you can still have organization as well as conditional styling. I hope this helps!

Resources