Please add ability to pass variables to block function.
For example this block could be rewritten
{% block integer_widget %}
{% spaceless %}
{% set type = type|default('number') %}
{{ block('form_widget_simple') }}
{% endspaceless %}
{% endblock integer_widget %}
to
{% block integer_widget %}
{% spaceless %}
{{ block('form_widget_simple', {type: type|default('number')}) }}
{% endspaceless %}
{% endblock integer_widget %}
and this:
{% block tree_node %}
<ul>
{# we need to save original root variable #}
{% set oldRoot = root %}
{% for node in root.children %}
{{ node.title }}
{% set root = node %}
{{ block('tree_node') }}
{% endfor %}
<!-- {{ oldRoot.children|length }} -->
</ul>
{% endblock %}
to
{% block tree_node %}
<ul>
{% for node in root.children %}
{{ node.title }}
{{ block('tree_node', {root: node}) }}
{% endfor %}
<!-- {{ root.children|length }} -->
</ul>
{% endblock %}
This would indeed be a nice addition!
Currently I'm using the same workaround: setting all variables used within the block prior to including it. This isn't very optimal in cases where the same variable name is used within the main scope (collision). A temporary variable has to be used in these cases to restore the variable value after the block inclusion.
As another workaround it's also possible to put the block contents into a separate file, and then use the 'include'-tag to pass variables to it. Sadly enough this won't work in my project, since I want to embed the main template so I can (optionally) redefine the block.
For the time being I've added a custom 'display_block'-function which simulates this behavior:
File YourVendor\Twig\DisplayBlockFunction.php:
namespace YourVendor\Twig;
class DisplayBlockFunction extends \Twig_SimpleFunction
{
public function __construct()
{
parent::__construct('display_block', null, array('node_class' => '\\YourVendor\\Twig\\DisplayBlockNodeExpression'));
}
}
File: YourVendor\TwigDisplayBlockNodeExpression
namespace YourVendor\Twig;
use Twig_Compiler;
class DisplayBlockNodeExpression extends \Twig_Node_Expression
{
public function __construct($name, \Twig_NodeInterface $arguments, $lineno)
{
parent::__construct(array('arguments' => $arguments), array('name' => $name), $lineno);
}
public function compile(Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this)
->write("\$this->displayBlock(");
foreach ($this->getNode('arguments') as $index => $node) {
switch ($index) {
case 0:
if (!$node instanceof \Twig_Node_Expression_Constant) {
throw new \Twig_Error_Syntax(sprintf('First argument of %s should be a constant value', $this->getAttribute('name')));
}
$compiler->subcompile($node);
break;
case 1:
if (!$node instanceof \Twig_Node_Expression_Array) {
throw new \Twig_Error_Syntax(sprintf('Second argument of %s should be an array of variables to be passed', $this->getAttribute('name')));
}
$compiler->raw(", array_merge(\$context, ")
->subcompile($node)
->raw(")");
break;
}
}
$compiler->raw(", \$blocks)\n");
}
}
Register the function in your environment
$twigEnv->addFunction(new DisplayBlockFunction());
Display a block and pass variables to it:
{{ display_block('form_element_label', { 'element': option } ) }}
:+1: I want this too!
But you should have an option to say that you only want the given variables be available inside the block's scope. Like http://twig.sensiolabs.org/doc/tags/include.html
Something like this:
{% render_block "hello" with { name: 'Ruud' } only %}
This would be great if it's a core functionality
Any progress here?
I have created a PR #1433 which solves it.
+1 here
Closing this PR as I prefer to support the with tag instead.
Most helpful comment
For the time being I've added a custom 'display_block'-function which simulates this behavior:
File YourVendor\Twig\DisplayBlockFunction.php:
File: YourVendor\TwigDisplayBlockNodeExpression
Register the function in your environment
Display a block and pass variables to it: