latte icon indicating copy to clipboard operation
latte copied to clipboard

Support for n:embed

Open lubomirblazekcz opened this issue 2 years ago • 2 comments

  • Explain your intentions

Currently it's possible to define component with n:define, like this

<button n:define="UiBtnPrimary, $type = 'solid'" data-type="{$type}" class="ui-btn bg-primary bg-opacity-10 font-normal">
    <span n:block="title"></span>
</button>

But it's not currently possible to embed it same way with n:embed, but latte plugin in phpstorm recognize this as valid latte attribute?

  • It's up to you to make a strong case to convince the project's developers of the merits of this feature

I think that n: macros are strong feature in latte, that no other php/js template engine has. With the strong adoption of TailwindCSS or AlpineJS, the n:define and n:embed would be strong feature for reusable UI components. You could define UI component with n:define and then reuse it in the code with n:embed. So there wouldn't be a lot of duplicated code with the same component. That's currently not possible to do in a good way with the other php/js template engines, and seems latte is one step away from this feature.

To embed that defined component, it's currently only possible to do with {embed}, like this

{embed UiBtnPrimary, $type = 'outline'}
	<span n:block="title">Hello World</span>
{/embed}

But this has it's limitations, let's say you want to extend the component with new classes, or attributes. You would have to define it as params in the n:define and add it as variables in the brackets {}, which could cause problems with tailwindcss detecting the classes, or other purgecss plugins.

Something like this would be much better and easier to use

<button n:embed="UiBtnPrimary" data-action="click->lib-dialog#show" data-action-url="path.json">
    <span n:block="title">Hello World</span>
</button>

Which would output to

<button data-type="outline" class="ui-btn bg-primary bg-opacity-10" data-action="click->lib-dialog#show" data-action-url="path.json">
	<span>Hello World</span>
</button>

Even better would be if define had something like js has <slot></slot>, so you wouldn't need to write block in embed everytime.

<button n:define="UiBtnPrimary, $type = 'solid'" data-type="{$type}" class="ui-btn bg-primary bg-opacity-10 font-normal">
    {slot}{/slot}
</button>

<button n:embed="UiBtnPrimary" data-action="click->lib-dialog#show" data-action-url="path.json">
    Hello World
</button>

For a big projects that reuse a lot of UI components this would be a massive improvement. In @newlogic-digital we noticed this ourselfs. We have a lot of UI components and templates in our projects, and if something like n:embed was possible it would result into reducing a lot of duplicate code. We try to use embed and include when possible, but it's not always ideal.

  • Please support my efforts in maintaining this project at https://github.com/sponsors/dg

We would love to support nette and latte directly! I've sended a few emails and contacted you on twitter with no response 😞

lubomirblazekcz avatar Jun 10 '22 08:06 lubomirblazekcz

This could probably be done, with the caveat that attributes can only be added and the tag name cannot be changed. So this wouldn't work properly:

<button n:embed="UiBtnPrimary" data-type="different type">
    ...
</button>
<div n:embed="UiBtnPrimary">
    ...
</div>

ad {slot}: a related thought https://forum.nette.org/cs/35161-napad-embed-s-anonymnim-blokem

dg avatar Jun 10 '22 10:06 dg

Has there been any movement on this? Is there an alternate solution? I was thinking of custom HTML tags, similar to Web Components in the browser.

template:

<button class="py-2 px-4 bg-blue-500 text-white font-semibold">
    <span><slot></slot></span>
</button>

usage:

<x-button class="button-modifier">
    Hello World
</x-button>

output:

<button class="py-2 px-4 bg-blue-500 text-white font-semibold button-modifier">
    <span>Hello World</span>
</button>

antiknown avatar Nov 19 '23 16:11 antiknown