bernhard Posted August 2, 2022 Author Share Posted August 2, 2022 6 minutes ago, dotnetic said: think you can drop the parentheses after items or content. Also you might want to use a n:if clause on the ul, so the markup is discarded if there are no items. No, because $block is a rockmatrix block having an items() method but not having an items property. Same goes for content(). The whole block will only render if there are items using RockFrontend's renderIf() method: $rockfrontend->renderIf("sections/newsitems.latte", $block->items()) 10 minutes ago, dotnetic said: Or just use {dump $page->title} Thx for letting me know ? Though personally I don't see any benefit in using another syntax if I can simply use plain PHP (which I already know)... 1 Link to comment Share on other sites More sharing options...
d'Hinnisdaël Posted August 2, 2022 Share Posted August 2, 2022 19 minutes ago, dotnetic said: I am also using Latte in an actual project and love it so far. For the integration into ProcessWire I am using TemplateEngineFactory. It also has a Latte renderer (but with Latte 2 atm, actual version is 3). Did you run into any breaking changes upgrading from Latte 2 to 3? I haven't yet updated the Latte renderer for TemplateEngineFactory as I haven't had enough time to give Latte 3 a go. Link to comment Share on other sites More sharing options...
dotnetic Posted August 2, 2022 Share Posted August 2, 2022 3 minutes ago, d'Hinnisdaël said: Did you run into any breaking changes upgrading from Latte 2 to 3 I did not upgrade yet, I am in the process of integration Latte v3 into the TemplateEngineLatte renderer, but still need time for it. Right now I am using v2 Link to comment Share on other sites More sharing options...
dotnetic Posted August 2, 2022 Share Posted August 2, 2022 13 minutes ago, bernhard said: Thx for letting me know ? Though personally I don't see any benefit in using another syntax if I can simply use plain PHP (which I already know) This is just syntactic sugar and uses Tracys debug bar, similar to using `{bd ($myvar)}. Using things like tags and filters are also syntactic sugar. {$page->intro|noescape} // or <div n:if="$features"> Tags have some advantages over plain PHP in the template context. For example they are chainable and easy to read/write: {$page->intro|noescape|upper} // outputs unescaped HTML content in uppercase Link to comment Share on other sites More sharing options...
dotnetic Posted August 2, 2022 Share Posted August 2, 2022 I used Smarty and Twig before, and have to say, that Latte feels much better, and the conditional rendering of elements is a great simplification. 1 Link to comment Share on other sites More sharing options...
bernhard Posted August 2, 2022 Author Share Posted August 2, 2022 6 minutes ago, dotnetic said: This is just syntactic sugar and uses Tracys debug bar, similar to using `{bd ($myvar)}. It still looks like it's doing the exact same thing to me? {dump $site} {bd($site)} I'd hoped that your version might make the click below the dump work so that I end up at the correct line in my latte file, but it always leads me to the cached/compiled version of latte... Link to comment Share on other sites More sharing options...
dotnetic Posted August 2, 2022 Share Posted August 2, 2022 1 hour ago, bernhard said: It still looks like it's doing the exact same thing to me? Yes exactly but with an easier syntax (imho), but dump is just one example. I don't know anything about the caching, and yeah it is bad that not the real file is shown in the dump Link to comment Share on other sites More sharing options...
bernhard Posted August 4, 2022 Author Share Posted August 4, 2022 RockFrontend is finally there ?? Link to comment Share on other sites More sharing options...
bernhard Posted September 21, 2022 Author Share Posted September 21, 2022 PM: "can we have the separator line not only on top of each list item but also after the last one?" <div n:foreach="$block->steps() as $step"> {$rockfrontend->render('img/hr.svg')} <div>...</div> {$rockfrontend->renderIf('img/hr.svg', $iterator->last)} </div> The $iterator is available automatically in LATTE loops! And it plays perfectly together with renderIf() ? See https://latte.nette.org/en/tags#toc-iterator Link to comment Share on other sites More sharing options...
maetmar Posted September 23, 2022 Share Posted September 23, 2022 PHP is for me unfortunately something that does not come very inuitive (so, I guess you know now I am by no means a hardcore developer). So it´s always time consuming with lots of trial and error to find (forum, google) code snippets that do what I want to do. Since I started using LATTE thanks to this thread and thanks to @bernhard and his RockFrontend module, it seems like a gamechanger for me. Processwire has become extremly more usefull and inutitive for me since. Thank you! I am currently rebuilding my code templates I use as starter-kits for new projects and convert them to LATTE. Does anyone have and is willing to share a skeleton template to build a nav-tree menu (mulitlevel) with LATTE? Something that produces similar HTML code like this: <ul class='navbar-nav'> <li class='nav-item active'> <a href='/processwire/' class='nav-link'>Home</a> </li> <li class='nav-item dropdown'> <a href='/processwire/kontakt/' class='nav-link dropdown-toggle'>Kontakt</a> <ul class='dropdown-menu'> <li class='nav-item'> <a href='/processwire/kontakt/kontakt-unterseite-a/' class='dropdown-item'>Kontakt Unterseite A</a> </li> </ul> </li> <li class='nav-item'> <a href='/processwire/seite-b/' class='nav-link'>Seite B</a> </li> </ul> 1 Link to comment Share on other sites More sharing options...
teppo Posted September 23, 2022 Share Posted September 23, 2022 8 minutes ago, maetmar said: Does anyone have and is willing to share a skeleton template to build a nav-tree menu (mulitlevel) with LATTE? Just wanted to point out that when it comes to building menus, it can get a bit... complicated. This is why modules such as MarkupMenu exist. I'm not saying that you can't build your own menu logic without a module using custom code, just that it's — in my opinion — one of those things that you don't necessarily need to ? Depends a lot on your use case, of course; some sites have a super simple menu logic. And sorry for going off-topic, as well as shameless self-promotion via MarkupMenu ? Link to comment Share on other sites More sharing options...
bernhard Posted September 25, 2022 Author Share Posted September 25, 2022 On 9/23/2022 at 2:25 PM, maetmar said: Since I started using LATTE thanks to this thread and thanks to @bernhard and his RockFrontend module, it seems like a gamechanger for me. Processwire has become extremly more usefull and inutitive for me since. Thank you! Thx! I'm happy to hear that ? This is a completely recursive multi-level menu using LATTE + RockFrontend magic that should get you started ? <ul class="uk-nav uk-nav-primary uk-margin-top uk-margin-large-bottom"> {* define block that is used for recursion *} {define items, $items, $first} {foreach $items as $item}{* loop all items*} {* define variables for inside the loop *} {var $active = $rockfrontend->isActive($item)} {var $subid = "tm-menu-".$item->id} {var $numc = ($item->numChildren() && $item!==$first) } {* list item markup *} <li n:class="$active ? 'uk-active'"> <a href="{$item->url}" n:attr="rf-toggle: $numc ? '#'.$subid"> {$item->title} <svg n:if="$numc" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--tabler" width="20" height="20" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m6 9l6 6l6-6"></path></svg> </a> {* list for child-items *} <ul id="{$subid}" n:if="$numc" class="uk-nav-sub" {!$active?'hidden'}> {include items, $item->children()->prepend($item), $item} </ul> </li> {/foreach} {/define} {* now include the block for the first level of items *} {include items, $home->children()} </ul> 1 Link to comment Share on other sites More sharing options...
MarkE Posted October 9, 2022 Share Posted October 9, 2022 Thanks for the menu suggestion @bernhard. I have done a variation on this to do a hierarchical menu which relects the page tree structure. The code below should be considered illustrative, rather than a recipe. In particular, you will need to adapt it to whatever css framework you are using. Also, my "nav.latte" is in the context of a repeater matrix item (part of my page builder framework), so the called methods live in the custom page class of the getForPage() (custom page classes don't work with repeaters directly). {* in nav.latte *} {var $selector = ($page->theme_selector) ?: "template=ThemeDisplay"} {* specific to my page builder. Define whatever selector you want for menu items here. *} {* define block that is used for recursion *} {define items, $items, $first, $selector, $shown = new ProcessWire\PageArray} {do $items = $page->getForPage()->treeSort($items)} // or you could put the function in init.php, suitably modified {foreach $items as $item}{* loop all items*} {* define variables for inside the loop *} {var $subid = "tm-menu-" . $item->id} {var $numc = ($item->numChildren($selector) && $item !== $first)} {var $active = (($item == $rockfrontend->wire->page) || ($numc && $item->children()->has($rockfrontend->wire->page)))} {* I had a problem with $rrockfrontend->isActive() not highlighting what I wanted, hence the above custom code *} {* list item markup (NB Bulma css) *} <a n:if="!$numc && !($shown->has($item) && $item !== $first)" href="{$item->url}" n:class="navbar-item, $active ? 'is-active'"> {$item->title} {do $shown->add($item)} </a> <div n:if=$numc class="navbar-item has-dropdown is-hoverable"> <a n:class="navbar-link, $active ? 'is-active'" href="{$item->url}">{$item->title} </a> {do $shown->add($item)} {* list for child-items *} <div class="navbar-dropdown"> {var $children = $item->children($selector)} {include items, $children->prepend($item), $item, $selector, $shown} {do $shown->add($children)} </div> </div> {/foreach} {/define} <nav class="navbar is-fixed-top is-transparent" role="navigation" style="{$page->theme_style|noescape}" aria-label="main navigation"> <div class="navbar-brand"> <a class="navbar-item" href="{$urls->root}"> <img src="{$logo->url}" alt="{$logo->description}"> </a> <a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="navbarMain"> <span aria-hidden="true"></span> <span aria-hidden="true"></span> <span aria-hidden="true"></span> </a> </div> <div id="navbarMain" class="navbar-menu"> <div class="navbar-start"> {* now include the block for the first level of items *} {include items, $pages->find($selector), $home, $selector} </div> </div> </nav> /* In the custom page class */ /** * Sort pages by how they appear in the page tree hierarchy * * @param $pages * @return void */ public function treeSort($pageItems) { foreach($pageItems as $index => $item) { $item->treeSortVal = $this->treeSortVal($item)[0]; } $pageItems->sort('treeSortVal'); return $pageItems; } private function treeSortVal($item) { $val = $item->sort + 1; $increment = 1; if ($item->numParents() > 0 && $item->parent() !== $this->pages()->get('/')) { $siblingNum = max($item->siblings()->explode('sort')); $parentVal = $this->treeSortVal($item->parent()); $increment = (1 / ($siblingNum + 2)) * $parentVal[1]; // (add 2 because we added 1 to sort to get $val, then we want 1 more than the greatest $val so that the fraction is always less than 1) $val = ($val * $increment) + $parentVal[0]; } else { } return [$val, $increment]; } 1 Link to comment Share on other sites More sharing options...
bernhard Posted October 9, 2022 Author Share Posted October 9, 2022 1 hour ago, MarkE said: {* I had a problem with $rrockfrontend->isActive() not highlighting what I wanted, hence the above custom code *} Could you please explain that in detail? This is one of the things that a really believe should not be built custom for every project. They should be done in a place where we can share logic across project and simply call the function that should work everywhere. What I also do not understand: What do you mean by reflect the page tree hierarchy? And what are the custom page class methods for? Doesn't my menu version do the same just without those helper functions? If I call $page->children() then they are already sorted in the correct order, no? Link to comment Share on other sites More sharing options...
MarkE Posted October 9, 2022 Share Posted October 9, 2022 55 minutes ago, bernhard said: Could you please explain that in detail? isActive() selects the parent page as active as well as the current page. I have a structure where the home ('/') page is the landing page and the (immediate) children need to be at the same level as Home. isActive() always shows Home as active whenever one of the other menu items is active. 55 minutes ago, bernhard said: What I also do not understand: What do you mean by reflect the page tree hierarchy? I mean that the menu hierarchy (other than Home) looks exactly like the page tree (but just for pages which are menu items). So if the page tree is: Home - Child 1 - Child 2 -- Grandchild 1 -- Grandchild 2 - Child 3 etc. the menu will be: Home Child1 Child2 Child3 - Grandchild 1 - Grandchild 2 55 minutes ago, bernhard said: If I call $page->children() then they are already sorted in the correct order, no? Not always. If no sort order is specified, they will be in id order (I think) - which is fine if you created them in the order you want. If you specify "sort=sort" then the top level will be correct, but lower levels will get mixed in - see 55 minutes ago, bernhard said: And what are the custom page class methods for? So those give a sort order as it appears in the page tree hierarchy: like 1, 2, 3, 4, 4.33, 4.66, 5 where 4.33 and 4.66 are the grandchildren. That way you don't encounter a child in the list before you have had its parent (which messes up the menu). EDIT: BTW, the $shown var is to prevent children being shown subsequently as higher-level items - not sure if that was fixing a problem in the original code or was just needed in my version. Link to comment Share on other sites More sharing options...
bernhard Posted October 9, 2022 Author Share Posted October 9, 2022 4 hours ago, MarkE said: isActive() selects the parent page as active as well as the current page. I have a structure where the home ('/') page is the landing page and the (immediate) children need to be at the same level as Home. isActive() always shows Home as active whenever one of the other menu items is active. Thx @MarkE I've modified the behaviour of isActive() so that it treats the homepage different than all other pages. It does now only mark the homepage active if the currently views page is the homepage (id=1). I have not hat that case until now but I think that makes sense 99,9% (maybe 100%) of the time since the homepage would otherwise always be "active" (as any page is a child of the root page), which is likely not what we want. Thx for the input ? 4 hours ago, MarkE said: I mean that the menu hierarchy (other than Home) looks exactly like the page tree (but just for pages which are menu items). So if the page tree is: Home - Child 1 - Child 2 -- Grandchild 1 -- Grandchild 2 - Child 3 etc. the menu will be: Home Child1 Child2 Child3 - Grandchild 1 - Grandchild 2 Sorry I still don't get it I think. My menus always reflect the page tree. If I want the "home" menu item on the same level as child1, 2 and 3 I simply output it above: <ul> <li><a href=/ n:class="$page->is('/') ? 'uk-active'">HOME</a></li> <li n:foreach="$home->children() as $item"> <a href="{$item->url}" n:class="$rockfrontend->isActive($item) ? 'uk-active'"> {$item->title} </a> </li> </ul> Is that what you are talking about? 4 hours ago, MarkE said: 5 hours ago, bernhard said: If I call $page->children() then they are already sorted in the correct order, no? Not always. If no sort order is specified, they will be in id order (I think) - which is fine if you created them in the order you want. If you specify "sort=sort" then the top level will be correct, but lower levels will get mixed in - see I think you are making things more complicated than they need to be. $page->children() already return the children in the admin sort order. So if you call $page->children() recursively in your menu than the menu perfectly reflects the page tree. Quote How to force pages to sort by their admin order with $pages->find() Unlike $page->children(), the $pages->find() method does not automatically sort by the order they appear in the site tree. This is because $pages->find() is not limited to finding pages specific to one parent, so it may be pulling pages from multiple places (according to your selector). If your parent page(s) are not already sorting by a specific field, you may still tell the find() to sort by the parent's order by literally specifying sort=sort in your selector. This is the same as saying "sort by whatever order I dragged the pages to in the admin." But note that if the results have multiple parents, the resulting order isn't likely to be that useful. https://processwire.com/docs/selectors/ So the problem might be that you are using $pages->find() or maybe that you apply a selector to page->children() ?! For me $page->children() did a perfect job without any extra magic ? 1 Link to comment Share on other sites More sharing options...
MarkE Posted October 9, 2022 Share Posted October 9, 2022 14 hours ago, bernhard said: I've modified the behaviour of isActive() so that it treats the homepage different than all other pages. It does now only mark the homepage active if the currently views page is the homepage (id=1). The issue is a bit more complex than that, maybe because of the way my menus work. I tend to have (viewable) pages which have (viewable) children, so the top-level menu items can also be pages, in which case they also appear in the dropdown and can be selected either by clicking the top-level item or the one on the dropdown. If you just fix the home page highlighting then, in my case, the parent will be highighted in the dropdown as well as on the top level. See pics below: What I want (& my code above gives): What isActive() gives me (currently): 14 hours ago, bernhard said: I think you are making things more complicated than they need to be. $page->children() already return the children in the admin sort order. So if you call $page->children() recursively in your menu than the menu perfectly reflects the page tree. Aagh! Of course you are right. I changed it to find() so that the home page was also included. Your menu assumed that home was not a menu item (hence also the issue with isActive() ). So now I have changed it to $home->children($selector) and the order is correct and all my complications go away (but I do then need to prepend $first to $items). Never mind it was an interesting exercise and may come in useful one day. 1 Link to comment Share on other sites More sharing options...
bernhard Posted November 22, 2022 Author Share Posted November 22, 2022 Another (even simpler) version for uikit breadcrumbs: <ul class="uk-breadcrumb"> <li n:foreach="$page->parents() as $p"> <a href="{$p->url}">{$p->title}</a> </li> <li><span>{$page->title}</span></li> </ul> ? Link to comment Share on other sites More sharing options...
bernhard Posted May 22, 2023 Author Share Posted May 22, 2023 Very interesting blog article that compares twig / blade / latte: https://blog.nette.org/en/quiz-can-you-defend-against-xss-vulnerability 2 Link to comment Share on other sites More sharing options...
netcarver Posted May 22, 2023 Share Posted May 22, 2023 Thanks for the link, Bernhard, I've been trying blade in Laravel recently, but think I need to try out Latte as well. 2 Link to comment Share on other sites More sharing options...
d'Hinnisdaël Posted May 22, 2023 Share Posted May 22, 2023 @netcarver I've been using Latte in Laravel almost exclusively. Blade is great, but Latte is even better. There's a composer package for integrating Latte, but it was out of date when I last checked so I wrote my own which was quite straightforward. Interestingly, you can mix and match, calling Blade views from Latte and vice versa, which is a lifesaver when dealing with vendor files and third-party packages. 3 Link to comment Share on other sites More sharing options...
netcarver Posted May 22, 2023 Share Posted May 22, 2023 @d'Hinnisdaël Thanks for the post - is your integration available on github at all? Link to comment Share on other sites More sharing options...
d'Hinnisdaël Posted May 23, 2023 Share Posted May 23, 2023 @netcarver Yes, I've created a gist that should do. 1 Link to comment Share on other sites More sharing options...
wbmnfktr Posted May 25, 2023 Share Posted May 25, 2023 Can someone please give me a hint on how to use RockFrontend with Latte and combination with RepeaterMatrix? I just can't find a way to show the content of my blocks (RepeaterMatrix types). {* home.latte *} <ul n:if="$page->blocks"> {foreach $page->blocks as $block} <li> {include '../blocks/' . $block->type . '.latte'} </li> {/foreach} </ul> {* oneOfTheBlocks.latte *} <div> {* NOPE *} {$block->headline} </div> <div> {* NOPE *} {$page->headline} </div> Link to comment Share on other sites More sharing options...
bernhard Posted May 26, 2023 Author Share Posted May 26, 2023 It should work just like any other PW api... Does it render empty divs? Does it throw an exception? I'm never using {include ...}, I'm always using {$rockfrontend->render(...)}, but both should work. Link to comment Share on other sites More sharing options...
Recommended Posts