How do I pass variables to theme template via custom controller drupal 8 - drupal

I currently have a theme I purchased installed on my Drupal website.
Inside the theme folder there is a templates folder that contains:
page.html.twig
page--front.html.twig
a snippet from page.html.twig looks as follows:
<footer class="site-footer">
<div class="layout-container">
{% if page.footer_first or page.footer_second or page.footer_third %}
<div class="footer-top">
<div class="footer-top-inner">
{{ page.footer_first }}
{{ page.footer_second }}
{{ page.footer_third }}
</div>
</div>
{% endif %}
{% if page.footer_left or page.footer_right %}
<div class="footer-bottom">
<div class="footer-bottom-inner">
{{ page.footer_left }}
{{ page.footer_right }}
</div><!-- /.footer-bottom-inner -->
</div>
{% endif %}
</div>
</footer>
I have a custom module I created (business_listing) that loads different .html.twig templates I add these templates in business_listing.module:
function business_listing_theme($existing, $type, $theme, $path) {
return [
// business-listing-detail.html.twig
'business_listing_detail' => [
'variables' => ['data' => [], 'slides' => [], 'paths' => [], 'page' => []],
],
]
}
Basically I would like to know how I can add the markup for the footer dynamically from my custom modules controller.
I have a page called business-listing-detail.html.twig inside my custom modules templates folder. From what I understand business-listing-detail.html.twig uses/somehow extends page.html.twig in my theme/templates. What I would now like to know is how I can add the sections like {{page.footer_left}} to my business-listing-detail.html.twig or to page.html.twig using my controller? I have tried adding the footer using the following: `
$page['footer_left'] = "This should appear in the .footer-bottom div?";
$build = [];
$build['business_listing_detail'] = [
'#theme' => 'business_listing_detail',
'#data' => $record,
'#slides' => $slides,
'#paths' => $this->paths,
'#page' => $page
];`
in the controller function associated to my business-listing-detail page the hopes that page.html.twig will detect this page.footer_left and render display the footer, however this did not work. The variable exists in business-listing-detail.html.twig but the {% if page.footer_left %} in my themes page.html.twig is not fired. Please please please, any help or advice would be greatly appreciated <3
Basically all I am trying to do, is dynamically render a template for a specific page in my custom module, that allows me to implement/send markup to the sections/regions defined in my theme eg. featured_top, content_top & page.content
Kind regards,
Matt

It seems like you might be going down the wrong path... I'd highly suggest you read up about the Drupal 8 Block system, and then investigate custom blocks.

Related

How to Embed Controllers in a Template using Symfony 4 directory structure

I did a fresh Symfony installation by using Symfony Flex and the new skeleton belong to the next Symfony 4 directory structure. Next, I'm going to embed a controller from a twig template.
I've tried to do it like this:
<div id="sidebar">
{{ render(controller(
'App:Article:recentArticles',
{ 'max': 3 }
)) }}
</div>
The same with How to Forward Requests to another Controller, I've tried:
$response = $this->forward('App:Something:fancy', array(
'name' => $name,
'color' => 'green',
));
But is not working.
There is way to do this?
When we using the short convention a:b:c to refer to the controller, it will only work if the controller belong to an installed bundle. For Symfony 4 structure your app source is not a bundle by default, so the above does not work.
For Symfony 4 approach you can refer to this controller using its fully-qualified class name and method:
App\Controller\ArticleController::recentArticlesAction
Embedding the controller into Twig templates:
{{ render(controller('App\\Controller\\ArticleController::recentArticlesAction')) }}
This is the correct way to do this:
{# templates/base.html.twig #}
{# ... #}
<div id="sidebar">
{{ render(controller(
'App\\Controller\\ArticleController::recentArticles',
{ 'max': 3 }
)) }}
</div>
Source: https://symfony.com/doc/master/templating/embedding_controllers.html

Save charts on server

I have a symfony3 project with working Highcharts functions implemented through the ob/highcharts-bundle and I really like the way the generated charts look with a custom theme.
I would like to be able to run a script on the server that generates an email and along the way builds the charts that I need (complete with my custom theme) and saves to the server so I can link to them from the email.
I've previously done this in pChart, and saving an image on the server from a script is as easy as $myPicture->autoOutput('myimage.png'). While that's easy, I prefer the look of charts from Highcharts.
Is there a similar simple way to do this something like this using Highcharts?
My scripts look like this:
// Controller
$xdata = array(1, 2, 3, 4);
$data_series = array(
0 => array(
"name" => "Series 1",
"data" => array(
0 => 2.0, 1 => 0.0, 2 => 5.0, 3 => 2.3, 4 => 0.45, 5 => 0.4
)
)
);
$ob = new Highchart();
$ob->chart->renderTo('trendchart'); // id of the div where the chart gets rendered
$ob->title->text('Chart title');
$ob->xAxis->categories($xdata);
$ob->series($data_series);
return $this->render('dashboard/main.html.twig', [
'trendChart' => $ob,
]);
and I render this in a twig template:
// twig template
{% extends 'base.html.twig' %}
{% block javascripts %}
{{ parent() }}
<script src="//code.highcharts.com/highcharts.js"></script>
<script src="//code.highcharts.com/modules/exporting.js"></script>
<script src="{{ asset('js/highchartThemes/mytheme.js') }}"></script>
<script>
{{ chart(trendChart) }}
</script>
{% endblock %}
{% block body %}
<div id="trendchart"></div>
{% endblock %}
What I'm hoping for is to make a call from my controller like:
$ob->save('myimage.png');
Does anyone know of a simple/clean way to do something like this?

Symfony - pass custom data from Form Builder to form theme

I would like to set a special div surrounding a bunch of my fields. For that I want to add something to the form builder that I could detect in my form_theme, and set the div when it's there.
I tried to add
->add('field', new myCustomType(), array('inherit_data' => true, "label" => false, "required" => false, 'attr' => array("test" => "aaa")))
to the form builder, setting an custom attr, it's actually rendered in the html as an attribute... But I'm unable to detect it in the form theme.
{{ block('widget_container_attributes') }}
Only gives the widget attributes, and
{{ block('row_container_attributes') }}
doesn't work. I actually have a hard time finding any source online about what variables are available in the blocks of the form theme and how to use them (it was already difficult to know how to call blocks).
I looked for some more information on the official site, here mostly but without any success...
Thanks ahead for any help !
If you put it in your form builder, then you might as well permanently set in your template. If there is some logic required to set the data, then that belongs in your controller anyway, so just put it there to start with.
Controller:
public function someAction()
{
// ....
return $this->render('some_twig_template.twig.html', array(
'attr' => array("test" => "aaa")
);
}
Then in your twig template
{{ dump(attr) }}
{{ dump(attr.test) }}
EDIT:
To render in your template every time, you can set a class on the rendered field directly:
{{ form_label(form.field, 'My label', { 'label_attr': {'class': 'js-hidden-row'} }) }}
{{ form_widget(form.field, { 'attr': {'class': 'js-hidden-row'} }) }}
Then in my javascript you can hide with some simple jQuery:
<script>
jQuery(document).ready(function() {
$('.js-hidden-row').hide();
});
</script>

How can I print Google Books api description?

Hie I am trying to get the synopsis and other items like author and published date printed. But I am Able to achieve this only with certain search terms, an error occurs with other words or terms
Key "description" for array with keys "title, subtitle, authors, publishedDate, industryIdentifiers, readingModes, pageCount, printType, categories, maturityRating, allowAnonLogging, contentVersion, imageLinks, language, previewLink, infoLink, canonicalVolumeLink" does not exist.
I am using symfony and twig. this is what the twig file looks like :
{% for item in items %}
<article>
<img src="{{ item.volumeInfo.imageLinks.thumbnail}}"/>
<h4>{{ item.volumeInfo.title}}</h4>
{{ item.volumeInfo.description }}
<strong> {{ item.volumeInfo.publishedDate }}</strong><br/>
<b>{{ item.volumeInfo.authors | join }}</b>
</article>
What am I doing wrong? why does this work only sometimes ? how can I make it work correctly all the time?
class GoogleBooksController extends Controller
{
public function getVolumeAction($title)
{
$client =new client();
$response = $client- >get("https://www.googleapis.com/books/v1/volumes?q=$title");
$data=$response->json();
$items=$data['items'];
return $this->render('BookReviewBundle:GoogleBooks:volume.html.twig', array('items'=>$items
// ...
)); }
Thanks
I belive the description field is not mandatory, so you can do follow
{% if item.volumeInfo.description is defined %}
{{ item.volumeInfo.description }}
{% endif %}

KnpMenuBundle - send Options and use them in Twig

I wrote the last days on my nav-bar-menu whit KnpMenuBundle. I want simply to give the template a few parameters on the way and then react on it. Is it possible? I tried this:
$menu->addChild('Registration', array('route' => 'fos_user_registration_register',
'icon' => array('glyphicon' => 'briefcase')));
And then I want to pick this in Twig template:
{% if icon['glyphicon'] is defined %}
<span class="glyphicon glyphicon-{{icon['glyphicon']}} "></span>
{% endif %}
I tried a lot, but nothing works. What can I try next?
Here is how i did it
The Menu class:
$menu->addChild('Home', array(
'route' => 'home',
'extras' => array('icon' => 'home')
));
My menu call in the template, i ask for a specific twig template
{{ knp_menu_render('MyBundle:Menu:primaryNav', {'template': 'MyBundle:Menu:primaryNav.html.twig'}) }}
In the twig template, i copy/paste the knpmenubundle template and edit some blocks. you may be able to do this with 'extends' and template's inheritance stuffs as well (probably a better idea).
Example of edited block for icon :
{% block spanElement %}
<a href="#" class="dropdown-toggle">
{% if item.extras.icon is defined %}<i class="icon-{{ item.extras.icon }}"></i>{% endif %}
<span class="menu-text"> {{ block('label') }}</span>
<b class="arrow icon-angle-down"></b>
</a>
{% endblock %}
What you needed was probably this "extras" field in the menu class :)
I don't know if this can still help but there's a much easier way to use font awesome with knp menu. There's an option where you can give a class to your link. You just need to create a child without a label an add setLinkAttribute. Ex:
$menu
->addChild('', array('route' => 'backend_index'))
->setLinkAttribute('class', 'fa fa-home');
This will create an "a" tag with the class fa fa-home. Even if Font Awesome documentation says the icons are designed for inline elements, it will work with "a" tag. You can then use some css to improve the design. In my case, I just changed font-size and line-height.

Resources