including *.latte templates without caring the directory structure
- medhi
- Generous Backer | 255
This is ugly:
{include '../../../menu.latte'}
{* or *}
{embed '../../../menu.latte'}{/embed}
It's so annoying to search how deep in my directory structure I am, and it
should not matter, why should I care?
Also, if the parent template is moved upper or lower, these paths stop
working.
How about to put all these templates – that are used only to be included – to some predefined directory and then include them without caring about the directory structure?
Last edited by medhi (2020-11-06 22:52)
- Rick Strafy
- Nette Blogger | 81
So you want all templates that you include somewhere in one directory? It's sounds like very bad joke, projects with folders like Includes or Utils are considered as those with design flaws where author didn't make effort to make better project structure, but it's not always true, usually it's better use something like Article/@Common to have common templates that have to do something with articles.
But on the other hand, it would be cool to define template root, for instance
my template root would be here https://github.com/…%40Templates
so I could use {embed '/@Layout/Embeds/menu.latte'}
anywhere, but
until now I didn't have problem with paths, it's very rare when I move latte
file to other directory.
Last edited by Rick Strafy (2020-11-06 23:13)
- medhi
- Generous Backer | 255
I was not proposing any particular solution, but just a general idea to have more pleasant way to include a template.
Now I have something like this in my code:
{embed '../../../../templates/infobox.latte'}
...
{/embed}
Which is… difficult to read at least?
Absolute paths? Maybe, why not :)
- David Grudl
- Nette Core | 8228
You can set your own root for the Latte and then all “absolute” paths will be relative to this root:
$this->template->getLatte()->setLoader(
new Latte\Loaders\FileLoader(__DIR__ . '/templates')
);
The problem is that Presenter is not ready for this and use absolute paths in
methods like formatTemplateFiles(). The easiest solution is therefore to use a
variable $root
or as he wrote @filsedla define constant.
- medhi
- Generous Backer | 255
Šaman wrote:
medhi wrote:
You won't pass a big chunk of HTML/latte into a Control.
Why? Control has own independent template. Even Presenter is Control.
Because I need to pass different big chunks of HTML. A modal for example. It has its own template, but always has different body, which is not suitable for control to pass in.
- dsar
- Backer | 53
This is ugly:
{include '../../../menu.latte'} {* or *} {embed '../../../menu.latte'}{/embed}
I had this problem with a layout shared by multiple modules and I have found a way to hide this (not ideal but at least it hides this ugliness).
In your case just create a menu.latte in the same folder with {include ‘../../../menu.latte’}. Then in your latte files you can just use {include menu.latte}.
Last edited by dsar (2021-03-13 09:21)
- David Grudl
- Nette Core | 8228
Maybe it would be useful to make some Loader, in which you can add more paths and their aliases, like
'components' => __DIR__ . '/../templates/components',
'layouts' => __DIR__ . '/layouts',
'' => __DIR__ . '/templates', // default one
...
So if I write {layout 'layouts/main.latte'}
, it will resolve it
as __DIR__ . '/layouts/main.latte
.
Perhaps more paths could be allowed in which it will try to search for a file:
'layouts' => [
__DIR__ . '/layouts',
__DIR__ . '/../submodule/layouts',
]
'' => [ ... ]
- jdan1131x
- Member | 41
sometimes i am away from site code for months.
so i forget, get rusty ..
today i am thinking, to maximize code reuse,
have directory structure:
→ LayoutModule (nothing but @layout.latte and children all
imported…no Presenters…)
-->→ @layout.latte
-->-->→ child 1
-->-->→ child n+1 …
-->-->FrontModule
-->-->→ @layout.front.latte (imports @layout.latte
above)
-->-->XYZModule
-->-->→ @layout.xyz.latte (imports @layout.latte
above)
-->-->N+1…Module
-->-->→ @layout.N+1....latte (imports
@layout.latte above)
then i would install ALL children, ALL blocks, ALL defines into LayoutModule
and
use existing Latte tools to do so.
my objective is to minimize the number of layout children
and keep them all in one directory.
makes sense without new Loader code or Constant code?
thanks very much,
James
- jdan1131x
- Member | 41
I setup a LayoutModule directory with all my latte files.
then i setup a TestModule directory with Presenters folder and a
TestPresenter.php,
and inside that templates folder I make symbolic link to the
@layout.latte file
in the LayoutModule that I need, then make symlinks to the child latte files as
needed…
So far, this works fine and seems worth my efforts…
James
- chemix
- Nette Core | 1310
I realy like idea like this:
'components' => __DIR__ . '/../templates/components',
'layouts' => __DIR__ . '/layouts',
'embed' => __DIR__ . '/../templates/embed',
'include' => __DIR__ . '/../templates/include',
with support of
'embed' => [
__DIR__ . '/../../../vendor/components/templates/default/embed', // priority 2
__DIR__ . '/../templates/local/embed', // priority 1
]
and next level, maybe, will be possible to use it in template like this with “~”:
{embed '~embed/embed.cody.feature_v4.latte'
document: $villa,
image: $villaImage}
{block content}
{include parent}
{include "~include/include.cody.image-small-gallery.latte", gallery: $villaGallery}
{/block}
{/embed}
the first “virtual folder” behind tilda “~” will define “namespace” for template path
- dakur
- Member | 493
I agree that writing so much of ../
is error-prone. I have
problem with it on every refactoring of directory structure as neither PhpStorm
nor static analysis catch it so I end up with error in UI in the end.
Having alias like in node world or in sass is clever solution, but I vote
for ~
component resolution only – it's just
one char away and we don't want global space pollution again I think. So:
// something => 'src/whatever'
include '~something/template.latte' -> src/whatever/template.latte
include 'something/template.latte' -> ./something/template.latte
Last edited by dakur (2021-05-06 09:24)
- Slava.Aurim
- Member | 19
In my humble opinion, the most elegant solution would be to specify the namespace using a colon:
{include 'widgets:social.latte'}
And adding namespaces via FileLoader:
$this->template->getLatte()->getLoader()->addDirectories(['widgets' => '.../templates/widgets']);
Or in config.neon with the help of LatteExtension:
latte:
scanDirs: #or baseDirs, namespaces, templateDirs , etc.
root: %appDir%/templates
widgets: %appDir%/templates/widgets
Last edited by Slava.Aurim (2021-09-15 19:44)
- Lulco
- Member | 4
@dakur
“neither PhpStorm nor static analysis catch it so I end”
Static analysis can catch it. Check https://github.com/…hpstan-latte
- David Grudl
- Nette Core | 8228
I prefer using a function that returns a path, for example, to components. I can add the function to Latte via an extension:
namespace App\UI\Accessory;
use Latte\Extension;
final class LatteExtension extends Extension
{
public function getFunctions(): array
{
return [
'component' => fn(string $path) => $this->root . '/components/' . $path,
];
}
}
which I will register in the configuration file:
latte:
extensions:
- App\UI\Accessory\LatteExtension
Then, in the template, just use:
{include component('menu.latte')}
- m.brecher
- Generous Backer | 872
@DavidGrudl
For file paths, whether it's {include '....'}
or
<link href={$basePath.'/....'}
, the key feature is IDE
autocompletion because manually filling in the file name is tedious and prone
to typos.
We need to come up with a smart integrated solution for Latte + Latte plugin by @messour for all types of paths in Latte. This would enable existing IDE features such as:
- Folder/file name suggestion
- Built-in file name refactoring
- Indication of non-existent files
I have some ideas in mind, so I'll try to submit a well-thought-out RFC for discussion.