Is it possible to pass on all variable in scope to an include?

paul
Member | 3
+
0
-

I'm trying to create a generic input collection. I would like to pass on all variables in a block to the include in that block, but I'm not sure if that's possible.

I've provided an example in this Fiddle:

https://fiddle.nette.org/latte/#…

(ChatGPT suggested using ‘_’, but that definitely doesn't work ;))

Or am I missing a better way to handle ‘overrides’ on a collection of inputs?

Thanks!

Last edited by paul (2023-05-04 17:04)

dkorpar
Member | 132
+
0
-

If U really need this it kinda looks like a code smell, something being wrongly managed…
Are you setting variables correctly to template? Maybe create object with properties and pass that to template instead of having a lot of scalar variables passed to template? It's hard to say without seing whole code…
Maybe using component would be better there then actual partial view? It all depends…

Last edited by dkorpar (2023-05-05 21:46)

paul
Member | 3
+
0
-

Hi @dkorpar,

In simplifying the code for the fiddle, some of the details might have gotten lost. And two competing issues have been brought together.

Practically when broken down into the main ‘wish’. I'm looking for a way to create (form) components, such as this:

{parameters
	string $value,
	string $name,
    string $label,
    string $extra_label,
    bool $required,
}

<p>{$label}</p>
<p>{$extra_label}</p>
<input type="text" name="{$name}" {$required ? 'required'} value="{$value}" class="border-purple-500 hover:border-purple-800 shadow-sm shadow-green-300"/>

and have them easily accessible in a page template.

Issue 1: Apply different config to component

Fact 1: I have multiple projects.
Fact 2: I have a number of basic (form) elements that I would like to use in all those projects (e.g. a form field). Element templates also contain the javascript handling around them for instance (such as checking for required, highlighting it on an error, etc). Design can be slightly different per project, e.g. colors used and other style elements.

I'm going to use ‘classes’ as an example, but the problem is a bit wider.

So for instance, in one project I want to use the field component to have yellow highlights and green shadows, in another blue highlights and a different font. The component itself knows which parts can be configured, but doesn't know all the options there are possible within all the projects. Hence my idea to use variables / parameters. This style knowledge should be centralized somewhere in the project and should not be known in the rest of the code / templates (ergo per project / per element classes to be set somewhere).

So my (non-latte experienced) try is to add something like this to the field component template:

{* This is the default color scheme *}
{var $colors = [
    'border' => 'border-purple-500 hover:border-purple-800',
    'shadow' => 'shadow-sm shadow-green-300',
]}

and change the template to:

{parameters
	string $value,
	string $name,
    string $label,
    string $extra_label,
    bool $required,
}

{* This is the default color scheme *}
{var $colors = [
    'border' => 'border-purple-500 hover:border-purple-800',
    'shadow' => 'shadow-sm shadow-green-300',
]}

<p>{$label}</p>
<p>{$extra_label}</p>
<input type="text" name="{$name}" class="{$colors['border']} {$colors['shadow']}"/>

And then figure out a way to override that.

I thought about putting the $colors in a {block colors} and then extend the layout in blue_field, with the blue config, like this:

{parameters
	string $value,
	string $name,
    string $label,
    string $extra_label,
    bool $required,
}

{block colors}
{* This is the default color scheme *}
{var $colors = [
    'border' => 'border-purple-500 hover:border-purple-800',
    'shadow' => 'shadow-sm shadow-green-300',
]}
{/block}

<p>{$label}</p>
<p>{$extra_label}</p>
<input type="text" name="{$name}" class="{$colors['border']} {$colors['shadow']}"/>

and then make blue-field-input.latte:

{extends 'field-input.latte'}

{block colors}
{var $colors = [
              'readonly:bg' => 'bg-gray-100',
              'focus:border' => 'focus:border-blue-500',
              'focus:ring' => 'focus:ring-blue-500',
          ]}
{/block}

But I cannot seem to access the $colors from the rest of the field-input.latte template (Undefined variable $colors in <b>/tmp/latte/parts-input_helpers-field-input.latte--9acd242958.php).

All other solutions I can come up with are not pretty (Using PHP and importing a config from somewhere, or PHP defines).

Question: Is there a way to access a variable from a block defined in the current layout or is there another way to include or retrieve some global config in a layout?

Issue 2: One collection, simplify imports

Without a collection, for each form element we need to do:

{include '../../parts/input_elements/field-input.latte',
	name: 'username',
	type: 'text',
	label: 'Your username',
}

Which (aside from ugly) also means we always have to adjust the filename string each time we copy an element to another page (which is at another directory level).

In order to have cleaner code in page templates, ideally I'd like to be able to import just one collection (of form elements) in a page template (for which we do need to set the right filename string) and then use simple element names.

So I would like to be able to do:

{import '../../parts/collection.latte'}

{include field-input,
	name: 'username',
	type: 'text',
	label: 'Your username',
}

I'm not sure if it's possible, but I didn't find a way to import a layout file (such as the one above) and convert it into a block, unless you include it like this. So the collection is then creating a block and including the layout, but has to pass on all relevant variables

  {block field-input}
	  {* Technically we would just want to import the layout file, but import only imports blocks *}
      {include 'input_elements/field_input.latte', name: $username, type: $text, label: $label}
  {/block}

So my question here is: Is there another way to create a collection (and simplify the block/template names)?

paul
Member | 3
+
0
-

Martk wrote:

https://fiddle.nette.org/latte/#…

Thanks @Martk, that's exactly what I was looking for!

Cleanly solves the problem at hand with regards to the parameter passing.

Do you also have a clean solution to the ‘collection building’ to centralize ‘ugly path finding’ to just one import instead of 20 form element includes? (See Issue #2 above in my previous message)

Owh wait.. This solves both!

Last edited by paul (2023-05-08 12:38)