Twig not detecting the custom function - php

I have written a Twig custom function (in a Twig custom extension). I notice the template does not read the function and keeps throwing me the "Method Exists" error.
Was wondering if you have faced this before. Any ideas ?
The custom extension file; $post and $list are both objects:
<?php
namespace App\Twig;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
class ShowContentExtension extends AbstractExtension
{
public function getFunctions()
{
return [
new TwigFunction('ShowList', [$this, 'ShowList']),
new TwigFunction('ShowPost', [$this, 'ShowPost'])
];
}
public function ShowList($list) {
foreach ($list->post as $post) {
$this->ShowPost($post);
}
}
public function ShowPost($post) {
return !((count(array_keys($post->documents))) < 2 && array_key_exists('header', $post->documents));
}
}
and this is where they are being called:
{% if ShowList(list) %}
<h2 >{{ title }}</h2>
<div>
<div>
{% for post in list %}
{% if post|length > 0 %}
{% include ./_links.html.twig' with { 'list': list} %}
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
and :
{% if ShowPost(post) %}
<div>
<div>
<a href="{{ post.link }}">
<span>{{ post.title }}</span>
</a>
</div>
</div>
{% endif %}
and this is the screenshot of the error :
error screenshot

Related

Adding a global action in EasyAdmin, place my button underneath the table instead of above

I created a global Action :
public function export(
Admin $user,
StructureRepository $structureRepository,
ExportCsvEntity $exportCsvEntity,
string $entityClass
): HttpFoundationResponse {
$zipcodes = $structureRepository->getZipcodesByStructureFromAdmin($user->getId());
$exportCsvEntity->export(
$zipcodes,
$entityClass
);
return $exportCsvEntity->download($entityClass);
}
public function exportButton(): Action
{
return Action::new('export', 'admin.crud.user.field.activities_tracking.button.export')
->linkToCrudAction('export')
->displayAsLink()
->setCssClass('btn btn-primary')
->createAsGlobalAction()
;
}
Then in my Crud Controller I call it :
if ($this->getUser() instanceof Admin) {
$export = $this->exportAction->exportButton();
$actions->add(Crud::PAGE_INDEX, $export);
}
In the doc its written => Global actions are displayed above the listed entries.
But in my case the button is underneath the table
Have a look here
My template is extending '#!EasyAdmin/crud/index.html.twig'then I override the global_actions block :
{% block global_actions %}
{{ parent() }}
{% endblock global_actions %}
Now my button is above the table but also underneath :
Have a look here
What do I do wrong ?
You are correct when trying to do this by overriding the index template.
An easy way to do this considering how the template is organized is to modify the global_actions block by filtering actions you do not want to show above the list. For example by using a css class to not show a global action above the list.
{% block global_actions %}
<div class="global-actions">
{% for action in global_actions|filter(a => 'under-list' not in a.cssClass) %}
{{ include(action.templatePath, { action: action }, with_context = false) }}
{% endfor %}
</div>
{% endblock global_actions %}
And in your crud controller:
Action::new('customAction', $label, $icon)
->addCssClass('under-list')
->createAsGlobalAction()
->linkToCrudAction('customAction');
And you need to add your new list of actions under your list by overriding the main block.
{% block main %}
{{ parent() }}
{% block under_list_global_actions %}
<div class="under-list-global-actions">
{% for action in global_actions|filter(a => 'under-list' in a.cssClass) %}
{{ include(action.templatePath, { action: action }, with_context = false) }}
{% endfor %}
</div>
{% endblock under_list_global_actions %}
{% endblock main %}
And you should get your custom global action (with the css class under-list) under your list.

How to Call a function of Controller From Twig

This is my view:
<div class="CSlider">
<div class="CProducts" >
<table>
<tr>
{% for count in 1..result|length %}
<td>
{% block tile %}
{% include 'tile.twig' %}
{% endblock %}
<h1>
{{ result[ count - 1 ].id }}
</h1>
</td>
{% if count is divisible by (6) %}
</tr>
<tr>
{% endif %}
{% endfor %}
</table>
</div>
</div>
And this is my controller:
class COlxMyAdsController extends COlxDatabaseHandler {
protected $view;
public function __construct($container){
parent::__construct($container);
$this->view=$container->view;
}
public function fetchMyLiveAdIdsByUserId( Request $request, Response $response ) {
$args=$request->getParams();
$args=$args['id'];
$results = $this->m_objOlxUserDetails->fetchMyLiveAdIdsByUserId($args);
return $this->view->render($response,'profile.twig',['result' => $results]);
}
}
I want to call a function of the controller from the view. How can I do this using Twig?
Here we can Use Exit_Tags
Through which we can assign a URL to that exit_tag to call this function

Adding help block using form theming

In my app I'm trying to display form help block using tips from official Symfony2 cookbook. Here is my code:
{% extends 'form_div_layout.html.twig' %}
{% block form_widget_simple %}
{{ block('base_form_widget_simple') }}
{{ dump(help) }}
{% if help is defined %}
<span class="help">{{ help }}</span>
{% endif %}
{% endblock %}
And using this theme:
{{ form_row(form.pageTitle, {'help': 'some help'}) }}
With this I'm getting error Variable "help" does not exist. Any ideas what have I missed?
P.S. I use Symfony 2.7.1.
Create a Form type extension extending the form type:
namespace Acme\AppBundle\Form\Extension;
use ...
class FieldTypeHelpExtension extends AbstractTypeExtension
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->setAttribute('help', $options['help']);
}
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['help'] = $options['help'];
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'help' => null
]);
}
public function getExtendedType()
{
return 'form';
}
}
Define the extension as a service:
acme_app.form.extension.field_type_help:
class: Acme\AppBundle\Form\Extension\FieldTypeHelpExtension
tags:
- { name: form.type_extension, alias: form }
Create a template extending form div layout:
{% extends 'form_div_layout.html.twig' %}
{% block field_help %}
{% if help is defined and help %}
<p class="help-block">{{ help|trans }}</p>
{% endif %}
{% endblock field_help %}
{% block integer_widget %}
{{ parent() }}
{{ block('field_help') }}
{% endblock integer_widget %}
{% block form_widget %}
{{ parent() }}
{{ block('field_help') }}
{% endblock form_widget %}
Configure this template as form theme on config.yml
twig:
form_themes:
- 'Form/fields.html.twig'
Now you can use it when render the a field on a template:
{{ form_widget(form.name, { 'help': 'this is help' }) }}
Or in your Form type:
$form->add('name', 'text', ['help' => 'this is help']);

The show action of Symfony 2 Sonata Admin Bundle is not working

I'm integrating Sonata Admin Bundle into my Symfony 2.6 application by following Symfony 2 jobeet tutorial. Everything is fine except the Show action. I have an entiry "Job" and so I have src/Ibw/JobeetBundle/Admin/JobAdmin.php which have a function configurShowField(ShowMapper $showMapper) like below
<?php
namespace Ibw\JobeetBundle\Admin;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Validator\ErrorElement;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use Ibw\JobeetBundle\Entity\Job;
class JobAdmin extends Admin
{
// ....
protected function configureShowField(ShowMapper $showMapper)
{
$showMapper
->add('category')
->add('type')
->add('company')
->add('webPath', 'string', array('template' => 'IbwJobeetBundle:JobAdmin:list_image.html.twig'))
->add('url')
->add('position')
->add('location')
->add('description')
->add('how_to_apply')
->add('is_public')
->add('is_activated')
->add('token')
->add('email')
->add('expires_at')
;
}
// ....
}
When I click the Show button and go to the view page (admin/ibw/jobeet/job/xxx/show), it shows none of the fields. The original template processed is /vendor/sonata-project/admin-bundle/Resources/views/CRUD/base_show.html.twig:
{% extends base_template %}
{% block actions %}
<li>{% include 'SonataAdminBundle:Button:edit_button.html.twig' %}</li>
<li>{% include 'SonataAdminBundle:Button:history_button.html.twig' %}</li>
<li>{% include 'SonataAdminBundle:Button:list_button.html.twig' %}</li>
<li>{% include 'SonataAdminBundle:Button:create_button.html.twig' %}</li>
{% endblock %}
{% block tab_menu %}{{ knp_menu_render(admin.sidemenu(action), {'currentClass' : 'active', 'template': admin_pool.getTemplate('tab_menu_template')}, 'twig') }}{% endblock %}
{% block show %}
<div class="sonata-ba-view">
***
{{ sonata_block_render_event('sonata.admin.show.top', { 'admin': admin, 'object': object }) }}
{% for name, view_group in admin.showgroups %}
<table class="table table-bordered">
{% if name %}
<thead>
{% block show_title %}
<tr class="sonata-ba-view-title">
<th colspan="2">
{{ admin.trans(name) }}
</th>
</tr>
{% endblock %}
</thead>
{% endif %}
<tbody>
{% for field_name in view_group.fields %}
{% block show_field %}
<tr class="sonata-ba-view-container">
{% if elements[field_name] is defined %}
{{ elements[field_name]|render_view_element(object) }}
{% endif %}
</tr>
{% endblock %}
{% endfor %}
</tbody>
</table>
{% endfor %}
{{ sonata_block_render_event('sonata.admin.show.bottom', { 'admin': admin, 'object': object }) }}
</div>
{% endblock %}
The inner content of <div class="sonata-ba-view"></div> is not shown except three asterisks I printed. Is there any configuration I'm missing?
You're missing a s in your function's name.
it's
configureShowFields(FormMapper $formMapper)
not
configureShowField(FormMapper $formMapper)
Try to add call in your admin.yml
ibw_jobbeet.admin.jobadmin:
class: Ibw\JobeetBundle\Admin\JobAdmin
...
calls:
- [ setTemplate, ['show', path_to_your_view.html.twig]]
Read more about templates in SonataAdmin

How to implement rel=prev and rel=next to Symfony2.3 pagination?

I am using Symfony2.3 for my project and for pagination I am using KNP paginator Bundle.
I want to know that How I can implement rel=prev and rel=next in our page ?
My Controller :
<?php
namespace XXX\ABCBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Session\Session;
use Doctrine\ORM\EntityManager;
/**
* author Siddharth Singh (siddharth.find#gmail.com)
*/
class ArcController extends Controller {
/**
* #Route("/arch", name="_arch")
* #Template()
*/
public function indexAction() {
$em = $this->getDoctrine()->getEntityManager();
$AArtEntity = $em->getRepository('XXXABCBundle:Arc')->findAll(array('updated'=>'DESC'));
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$AArtEntity, $this->get('request')->query->get('page', 1)/* page number */, 10/* limit per page */
);
return array('article' => $pagination);
}
}
Twig File :-
{% extends 'XXXABCBundle::layout.html.twig' %}
{% block body %}
{% for artic in article %}
<div class="txt">
<p>{{artic.description|striptags|titletruncate(250)}}</p>
</div>
{% endfor %}
<div class="arcive_Paging">
<ul class="ul_paging">
<span class="acitve">{{ knp_pagination_render(article) }}</span>
</ul>
</div>
{% endblock %}
Thanks !
Accepted answer does not work because rel=prev and rel=next must be inside head tag.
I use this macros:
{% macro pagination_meta(pagination) %}
{% set total = pagination.totalItemCount %}
{% set items_per_age = pagination.itemNumberPerPage %}
{% set current = pagination.currentPageNumber %}
{% set last = (total / items_per_age) | round(0, 'ceil') %}
{% set page_parameter = pagination.paginatorOption('pageParameterName') %}
{% if current != 1 %}
<link rel="prev" href="{{ path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params') | merge({ (page_parameter): (current - 1) })) }}" />
{% endif %}
{% if current != last %}
<link rel="next" href="{{ path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params') | merge({ (page_parameter): (current + 1) })) }}" />
{% endif %}
{% endmacro %}
Inside a template usage looks like this:
{% import 'AppBundle::macros.html.twig' as macros %}
{% block head %}
{{ parent() }}
{{ macros.pagination_meta(entities) }}
{% endblock %}
You can do it by overriding default pagination template. Check Templates part of the official documentation:
https://github.com/KnpLabs/KnpPaginatorBundle/blob/master/Resources/doc/templates.md
for example:
Tell KnpPaginatorBundle to load your template for rendering pagination, add these lines of code to config.yml:
knp_paginator:
template:
pagination: YourBundle::pagination.html.twig
And copy default pagination template code to your template in src/YourBundle/Resources/views/pagination.html.twig. You can get the code here:
https://github.com/KnpLabs/KnpPaginatorBundle/blob/master/Resources/views/Pagination/sliding.html.twig

Categories