Symfony Twig exception - symfony

I am trying to use a HTML table bundle:
https://github.com/ekyna/TableBundle
Here is the calling code:
$table = $this->get('table.factory')->createBuilder(
new InventoryType(),
['name' => 'project_inventory_list']
)->getTable($request);
$content = ['content_area' => $table->createView()];
return $this->render('MyProjectBundle:Default:index.html.twig', $content);
I am getting an exception:
An exception has been thrown during the rendering of a template
("Catchable Fatal Error: Object of class
Ekyna\Component\Table\TableView could not be converted to string") in
MyProjectBundle:Default:index.html.twig at line 6.
Stepped through code not sure whats going on - hoping it's a trivial issue???
| EDIT
{% extends 'mYThemeBundle:layout:base-layout.html.twig' %}
{% block title %}HEADER{% endblock %}
{% block page_content %}
{{ content_area }}
{% endblock %}

In your TWIG template, you have to do the following:
{% extends 'mYThemeBundle:layout:base-layout.html.twig' %}
{% block title %}HEADER{% endblock %}
{% block page_content %}
{{ ekyna_table_render(content_area ) }}
{% endblock %}
You need to use the TWIG function ekyna_table_render to render the table view.

After installing EkynaBundle (documentation was not up to date) I also needed to adjust the template as demonstrated above in addition to:
Install and enable WhiteOctoberPagerfantaBundle
Install and enable BraincraftedBootstrapBundle
Install twig extensions
Install and enable LiipImagineBundle
Thanks for all the help.

Related

Symfony-twig template form theme error

I have everything working correctly and now I'm trying to work with form themes. This is my code to generate the form without a theme.
{% extends 'base.html.twig' %}
{% block body %}
{% include 'menu/menu.html.twig' %}
{% if addpost is defined %}
<div id='add_post_form'>
{{ form_start(addpost) }}
{{ form_widget(addpost) }}
{{ form_end(addpost) }}
</div>
{% endif %}
{% endblock %}
But when I'm adding a form-theme with the following code
{% form_theme form 'form/form_div_layout.html.twig' %}
I get this error:
Variable "form" does not exist
When i execute this without the line, I'm getting the following error:
Unknown "form_help" function. Did you mean "form_rest", "form_end"?
the form_div_layout.html.twig contains the code found at github symfony twig form theme
At my config.yml I've added the following under the twig section,
form_themes:
- 'form/form_div_layout.html.twig'
.
either not, i still have this error
what is missing ???
My file structure
If all your forms are going to use the same theme you only need to add the line in your config, but if you want a particular form theme in a particular template you can use the template tag.
The reason you're getting the 'form is not defined error' is because you don't have a variable called form passed the the template, your form variable is called addpost, so you need to use
{% form_theme addpost 'form/form_div_layout.html.twig' %}

symfony twig extends: 'only extend if'

In twig there is the 'extends' tag, as found here; http://twig.sensiolabs.org/doc/tags/extends.html#conditional-inheritance
Now what I wanna do is something along the lines of the following example from that page:
{% extends standalone ? "minimum.html" : "base.html" %}
But rather than having 2 templates to extend from, I just want to extend from a template if a specific condition is met.
Now I've tried things such as:
{% extends boolean ? "template.html.twig" : "" %}
and:
{% if boolean %}
{% extends "template.html.twig" %}
{% endif %}
but the former gives an error saying it cannot find a template (since "" obviously isnt a valid path), and the latter just doesn't appear to do anything at all (or rather, it loads for a while and ends up not showing anything)
I've tried some other approaches, but couldn't come up with anything, so figured I'd ask here if I might be missing something.
Thanks in advance for any replies :)
EDIT: To sum up my intent; I am wondering if I can tell my template to only extend if a certain condition is met, and otherwise skip the extend step. (if condition then extend else do nothing)
Twig files are generated into PHP classes.
The extends tag should be the first tag in the template, as:
the {% extends %} tag will be converted to the PHP extends so the child template will inherit from the parent template.
the {% if %} tag is generated as a PHP if, inside a method of the template class, so you can't use {% if %} to extend some class or not.
Anyway, you can extends a variable coming from your context, so you should put your condition in the controller.
if ($boolean) {
$template = 'hello.twig';
} else {
$template = 'world.twig';
}
$this->render("MyBundle:MyFeature:child.html.twig", array('template' => $template);
And then in child.html.twig:
{% extends template %}
I came with this hack: added empty layout only with content block. Seems to be working :) I can pass variable from controller and page is loaded with or without layout.
<!-- base.html.twig -->
<head>
...stuff...
</head>
<body>
{% block content %}{% endblock %}
</body>
<!-- empty.html.twig -->
{% block content %}{% endblock %}
<!-- some_page.html.twig -->
{% extends boolean ? 'base.html.twig' : 'empty.html.twig' %}
{% block content %}
Now this is my real content
{% endblock %}
In pure twig language, it could be something like this :
{% if app.request.pathinfo starts with '/react' %}
{% set extendPath = "::react_base.html.twig" %}
{% else %}
{% set extendPath = "CoreBundle::layout.html.twig" %}
{% endif %}
{% extends extendPath %}

Toggle html validation globally

I've made a couple of twig extensions but I'm stumped on this one.
I have the following template logic that I want to make into an extension.
I need reuse this logic into many different forms instead of copying and pasting the following code everywhere:
{% if html5validation is not defined %}
{{ form_start(some_form) }}
{% else %}
{% if html5validation %}
{{ form_start(some_form) }}
{% else %}
{{ form_start
(
company, {'attr': {'novalidate': 'novalidate'}}
)
}}
{% endif %}
{% endif %}
With the above code from the controller I can do the following to turn the html5 validator on and off:
$this->render(..., array(html5validation => false));
I want put the template logic into the twig extension below...
I just don't know if it's possible to implement what I've done above in a twig extension.
class HTML5Validation extends \Twig_Extension
{
public function getFunctions()
{
return array(
new \Twig_SimpleFunction('html5validation', array($this, 'setValidation')),
);
}
public function setValidation($boolean)
{
//Implement the same logic as the twig template.
}
public function getName()
{
return 'html5validator';
}
}
The short answer is no - you can't do this using a twig extension, it's not what they're meant for.
Looking at your template fragment I'd say you need to customise the form_start block. To do this see Symfony Form Theming and How to customise form rendering.
EDIT: This solution does not work if your customised code requires local twig variables - only global twig variables are available for form theming. You can define your own twig globals in config.yml or in a twig extension.
For example, to override form_start globally, you find the default definition of the form_start block in form_div_layout.html.twig, copy it into your own form theme file e.g. YourBundle/Form/fields.html.twig, modify it as required and and update the twig configuration to apply your form theme file. Something like this:
{# src/YourBundle/Form/fields.html.twig #}
{% extends 'form_div_layout.html.twig' %}
{% block form_start -%}
{% if html5validation is not defined %}
{{ parent() }}
{% else %}
{% if html5validation %}
{{ parent() }}
{% else %}
{{ parent
(
company, {'attr': {'novalidate': 'novalidate'}}
)
}}
{% endif %}
{% endif %}
{%- endblock form_start %}
Config:
# app/config/config.yml
twig:
form:
resources:
- 'YourBundle:Form:fields.html.twig'
I actually found a better way to do what I wanted.
As a plus it works globally instead of having to populate more fields into your controller!
In YourBundle/Resources/views/validation.toggle.html.twig
{% extends 'form_div_layout.html.twig' %}
{% block form_start -%}
{% if html5validation is defined and html5validation == false %}
{% set attr = attr|merge({'novalidate': 'novalidate'}) %}
{% endif %}
{{ parent() }}
{%- endblock form_start %}
Then if you want to turn off html5 validation across the whole website:
# app/config/config.yml
twig:
global:
html5validation: false
Or
Even better just use it in your dev_config.yml if you want validation on by default on production mode but the ability to toggle validation on and off for dev mode.
# app/config/dev_config.yml
twig:
global:
html5validation: false
resources:
- 'YourBundle::validation.toggle.html.twig'
Finally use it in your twig template normally:
{% form_theme your_form 'YourBundle::validation.toggle.html.twig' %}
form_start(your_form)
Reusable and non invasive, exactly like I wanted it. :)
I got the hint from:
https://github.com/symfony/symfony/issues/11409#issuecomment-49358377
In the absence of a more elegant solution, you can always put the twig fragment given in your question into a separate file and use twig include from your various forms. The included fragment has access to the variables from the surrounding context:
{# YourBundle/Resources/views/form_start.html.twig #}
{% if html5validation is not defined %}
{{ form_start(some_form) }}
{% else %}
{% if html5validation %}
{{ form_start(some_form) }}
{% else %}
{{ form_start
(
company, {'attr': {'novalidate': 'novalidate'}}
)
}}
{% endif %}
{% endif %}
Then in the twig file for the form:
{% include 'YourBundle::form_start.html.twig' %}
If you typically pass a 'form' variable into render() in your controller(s) then you can use that in your form_start fragment. Otherwise you can pass the appropriate form in as a variable:
{% include 'YourBundle::form_start.html.twig' with {'form': localForm} %}

Symfony2: Custom Error Page Extend base.html.twig

I am trying to customize the error pages in Symfony.
This is my error.html.twig file located in app/Resources/TwigBundle/views/Exception/:
{% extends '::base.html.twig' %}
{% block body %}
<h1>{{ status_code }}: {{ status_text }}</h1>
{% endblock %}
Unfortunately I get the following error message:
Fatal error: Uncaught exception
'Symfony\Component\Routing\Exception\ResourceNotFoundException' in
[...]
vendor\symfony\symfony\src\Symfony\Component\HttpKernel\EventListener\RouterListener.php
on line 144
When I remove {% extends '::base.html.twig' %} everything works fine. Any ideas how to have my base template included in the error page?
Edit 1:
The strange thing is that it seems to work when a 403 is thrown, e.g., when I access /user but don't have the necessary privilege.
Edit 2:
I pasted the whole content of my base.html.twig into the error.html.twig file and noticed that the error was caused due to the menu rendered by the KnpMenuBundle bundle:
{{ knp_menu_render('ACMEMemberBundle:Builder:mainMenu', { 'style': 'pills', 'currentClass': 'active' }) }}
When I remove this line, everything works fine. But this is not the way I would like to go. Is there no possibility to keep the navigation?
file should be located in app/Resources/views/Exception/
instead of
app/Resources/TwigBundle/views/Exception/
Did you put the page in the following place?
/app/ResourceS/TwigBundle/views/Exception/error404.html.twig
{% extends '::base.html.twig' %}
{% block content %}
{%trans%}errors.404{%endtrans%}
{% endblock %}
// app/Resouces/views/base.html.twig
×
{% include('path/to/include') %}
○
{% include('::path/to/include') %}
I finally have done it putting the whole code (base+current) in the same 'error.html.twig' file.
It works for me and avoided a huge headache.
plz remove :: in first line https://symfony.com/doc/current/templating.html
{% extends 'base.html.twig' %}
{% block body %}
<h1>{{ status_code }}: {{ status_text }}</h1>
{% endblock %}

How to get source of twig block in twig template?

I have following twig block in template which extends main layout:
{% block abc %}
{{ name }}
{% endblock %}
next I have a head block in the same template. I want to pass block abc as template for twig.js:
{% block head %}
<script type="text/html" id="template-abc">
{{ blocksource('abc') }}
</script>
{% endblock %}
so the rendering result is:
{{name}}
How can I do this?
I tried building "blocksource" function in twig extension, but I don't know how to access block source form here.
function blocksource( Twig_Environment $env, $blockname) {
$source = ???;
return $source;
}
Use verbatim tag, it will do what you want.
{% verbatim %}
{{ things_you_want_to_show_as_twig_template }}
{% endverbatim %}
Everything inside this tag will not be interpreted by twig engine.
You can read more on that in twig documentation.

Resources