Sulu: How do I determine, that the current page is the search page? - sulu

When I'm running a standard search, for example /search?q=querystring the available urls are pointing to the root:
// dump of the twig url variable:
array:1 [▼
"de" => "/"
]
This is causing my menu to highlight the home link, which is of course not correct ;) - Is there a good way to distinguish the search page from the actual frontpage?

This looks like a bug for me but you can use path variable to check if its actually a page template e.g.
{% if path is defined %}
Don't let the content of the path variable confuse you its the location of the content page in the phpcr tree so it does not represent a url. In some cases it does match the url. In most cases the path variable is a good way to check if a page is a child of another page also if you use other resourcelocator strategies as the default tree one.
e.g. if you create a navigation:
{% for page in sulu_navigation_root_tree('main') %}
{% set addClass = '' %}
{% if page.path starts with path|default() %}
{% set addClass = 'is-active-parent' %}
{% elseif page.uuid == uuid|default() %}
{% set addClass = 'is-active' %}
{% endif %}
{# ... #}
{% endfor %}

Related

11ty - How to display post tags in my post.njk file?

I've used the 11ty/eleventy-base-blog template and have things working well - but I am trying to display the tags nicely within my post.njk file.
At the top of my post (.md) file I have this:
tags: ['Tag 1', 'Tag 2']
Within _includes/layouts/postslist.njk I'm using the following code:
{% for tag in post.data.tags %}
{%- if collections.tagList.indexOf(tag) != -1 -%}
{% set tagUrl %}/tags/{{ tag }}/{% endset %}
<span class="tag">{{ tag }}</span>
{%- endif -%}
{% endfor %}
This template is then used in the index.njk file (my homepage) using this code:
{% set postslist = collections.posts | head(-3) %}
{% set postslistCounter = collections.posts | length %}
{% include "postslist.njk" %}
The output of this is:
<span class="tag">Tag 1</span>
<span class="tag">Tag 2</span>
However, if I use {{ tags }} in my post.njk file I get the following output:
posts,Tag 1,Tag 2
I have also tried using the same code from the 'postslist.njk' file and putting it in my 'post.njk' file but that doesn't work.
How can I display the tags on my post in separated 'span' tags and also remove the 'posts' tag?
If you want me to open up my git repo then let me know.
Thanks!
Why is the posts tag in your tags?
In the starter template you're using (11ty/eleventy-base-blog), the posts/ directory includes a directory data file (posts.json), which gets applied too all files in that directory – i.e. to all posts. Since the .eleventy.js config file uses the Data Deep Merge option, the tags you set in each post get merged with the posts tag. This is why the tags of your post are ['posts', 'Tag 1', 'Tag 2'].
You can solve this in multiple ways. Either use two different frontmatter fields for collection and display purposes, or just filter out the posts tag when displaying the tags of a post.
How to output a list of tags?
If you just do {{ tags }}, you're telling Nunjucks to output an array, so it has to figure out how to convert an array to a string. Apparently, the default behaviour in this case is to simply join them with commas. You can make this more explicit (and include a space after the comma while you're at it):
{{ posts | join(', ') }}
Or, if you want to wrap the items in HTML tags, you can use a loop, optionally with a joiner:
{% set comma = joiner() %}
{% for tag in tags -%}
{% if tag !== 'posts' %}
{{ comma() }} <span class="tag">{{ tag }}</span>
{% endif %}
{%- endfor %}

Unexpected Variable does not exist Error in Preview after Sulu CMS upgrade

I define a handfull of global twig variables in templates outside of the content block, now after the upgrade to sulu 2.0, this is throwing unexpected "Variable does not exist Error" in the preview. The actual page rendering is still intact. After the comment of #JohannesWachter it appears, that the preview is only rendering the content block now and ignoring outside variables.
I have the following (simplified) code, which used to work in sulu 1.6:
main.html.twig
{% extends "base.html.twig" %}
{% set hasContent = content is defined %}
{% if hasContent %}
{% set headline = content.headline is defined and content.headline ? content.headline : content.title %}
{% endif %}
{% block content %}
<div class="row">
{% block row %}
<section class="col-sm-8 main-content">
{% if hasContent and headline is defined%}
<h1 class="headline" property="title">{{ headline }}</h1>
{% endif %}
In the preview I get the following error for the line {% if hasContent and headline is defined%}: Variable "hasContent" does not exist. (main.html.twig line 43)
Is there a way to have this kind of global variables available in the preview and the main page for sulu 2.0?
I fixed it by moving variables used in the content block into the content block:
{% extends "base.html.twig" %}
{# set variables nesessary to adjust base.html.twig only #}
{% block content %}
{% set hasContent = content is defined %}
{% if hasContent %}
{% set headline = content.headline is defined and content.headline ? content.headline : content.title %}
{% endif %}
<div class="row">
{% block row %}
<section class="col-sm-8 main-content">
{% if hasContent and headline is defined%}
<h1 class="headline" property="title">{{ headline }}</h1>
{% endif %}
I tried a bit around with moving the variable definition into a setup.html.twig file, but variables only defined inside an included template are not visible to the outside anymore.

How to check if form has errors in twig?

Beside the form field specific error messages directly attached to the form field I would like to display a message above the form that the form contains errors.
How can I check in a Symfony3 twig template if a form has errors? There used to be something like this in Symfony2:
{% if form.get('errors') is not empty %}
<div class="error">Your form has errors. Please check fields below.</div>
{% endif %}
But this doesn't work in Symfony3. Any ideas? (form.vars.errors doesn't work.)
Use form.vars.errors:
{% if form.vars.errors is not empty %}
{# ... #}
{% endif %}
Attention! Note that this just evaluatues to true, if your root form has errors (or if child forms have errors and allow bubbling the error up to the root form). If regular child elements of your form have errors, this will not evaluate to empty!
So the valid variable is probably of more suitable:
{% if not form.vars.valid %}
{# ... errors ! #}
{% endif %}
With symfony 3.4 it's not possible through form.vars.errors anymore except if you have error_bubbling = true and form compound = false which is unlikely.
You can either use a dirty code like this :
{% set errors = false %}
{% for child in form.children %}
{% if child.vars.errors is defined and child.vars.errors|length %}
{% set errors = true %}
{% endif %}
{% endfor %}
{% if errors %}
[...]
{% endif %}
If you are trying to build a login form with AuthenticationUtils, use a code like this in controller :
//Get the login error if there is one
if ($error = $authenticationUtils->getLastAuthenticationError()) {
//Add error message to mail field
$form->get('mail')->addError(new FormError($error->getMessageKey()));
}
//Last username entered by the user
if ($lastUsername = $authenticationUtils->getLastUsername()) {
$form->get('mail')->setData($lastUsername);
}
//Render view
return $this->render('#ExampleBundle/template.html.twig', array('form' => $form->createView(), 'error' => $error));
And use a simple code like this in twig template :
{% if error %}
[...]
{% endif %}

Do Swig's macros support calling nested macros, dynamically?

I've created a Swig macro that dynamically calls new macros. The result I've found from doing this is that the HTML markup from within the nested macro is not rendering as HTML, rather it's rendering as an HTML text node which includes the HTML tag I used. My test markup was simply an H1 element with "Hello World!" inside the element.
Do Swig's macros support calling nested macros? Or any ideas of how I can get the HTML markup from the nested macro to render as HTML?
Here's the exact code I'm using for this test:
macros.html
Primary/parent macro (HTML renders fine):
{% macro call(macro) %}
{% if (macro.name === "transitions") %}
{% import "transitions.html" as transitions %}
<h1>Transitions!</h1>
{{ transitions[macro.method](macro.vars) }}
{% elseif (macro.name === "grid") %}
{% import "grids.html" as grids %}
<h1>Grids!</h1>
{{ grids[macro.method](macro.path, macro.vars) }}
{% endif %}
{% endmacro %}
transitions.html
Nested/child macro (String is rendered):
{% macro slider(vars) %}
<h1>Hello Slider!</h1>
{% endmacro %}
Okay, that didn't take long. Issue resolved!
Solution safe filter forces the input to not be auto-escaped:
{% macro call(macro) %}
{% if (macro.name === "transitions") %}
{% import "transitions.html" as transitions %}
<h1>Transitions!</h1>
{{ transitions[macro.method](macro.vars)|safe }}
{% elseif (macro.name === "grid") %}
{% import "grids.html" as grids %}
<h1>Grids!</h1>
{{ grids[macro.method](macro.path, macro.vars)|safe }}
{% endif %}
{% endmacro %}
Got the idea from this question: jinja2: macro selecting macro or dynamic macro calls.
Then looked up docs for "safe" on the Swig website http://paularmstrong.github.io/swig/docs/filters/#safe.
Exactly what I needed.
EDIT:
By the way, I also discovered that calling the nested macro in the normal way (macro.method) without using a dynamic key (macro[method]) worked without using the safe filter. Not what I needed for my specific situation, but just thought I'd throw that out there.

Symfony2 Theming form generated by embedded controller action

I am generating the form in embedded controller action. And now i have faced the following problem. The Form Theming is not working in that case.
So what i have:
The tempalte "page.html.twig"
{% block content %}
{% render 'MyBundle:Widget:index' %}
{% endblock %}
The indexAction() creates the form and rendering another template "form.html.twig" which is normally renders a form using form_row, form_rest and so on.
So, now i am trying to customize form theming, and here is my problem.
When i put the code
{% form_theme form _self %}
in the page.html.twig, i got an error the the form variable does not exists. And its correct, the form var is created later in the embedded controller.
But when i put the theming code in embedded template "form.html.twig", i got another error "Variable "compound" does not exist"
{% block form_label %}
{% spaceless %}
{% if not compound %}
{% set label_attr = label_attr|merge({'for': id}) %}
{% endif %}
{% if required %}
{% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %}
{% endif %}
{% if label is empty %}
{% set label = name|humanize %}
{% endif %}
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %} {% if attr.tooltip is defined %}title="{{ attr.tooltip }}"{% endif %}>{{ label|trans({}, translation_domain) }}{% if required %}<span>*</span>{% endif %}</label>
{% endspaceless %}
{% endblock form_label %}
This part of code was copied from this file https://github.com/symfony/symfony/blob/2.1/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
So tried someone to do something like this?
Answering my question myself.
It was a small sentence in Symfony2 docs http://symfony.com/doc/current/book/forms.html
This {% form_theme form _self %} functionality will only work if your template extends another. If your template does not, you must point form_theme to a separate template.
So there are two solutions to solve this problem:
move form theme code to the separate file and include it in a embedded template using
{% form_theme form with 'fields.html.twig' %}
leave the form theme code in the same template, where the form will be generated, but extend the template from some "form.html.twig" empty template.
I have only done the second way, and its works, but I am sure the first one will work as well.