Knp Paginator Bundle route error when using slug - symfony

I'd like to implement the Knp Pagination for a table.
It is a page where I edit documents, so my route looks like that:
#Route("/document/edit/{id}/") and depending on the document, there is a different ID.
There are several panels on the page and one of them contains a table of different agencies. For that table I used the knp_paginator:
/**
* #var $paginator \Knp\Component\Pager\Paginator
*/
$paginator = $this->get('knp_paginator');
$agencyTable = $paginator->paginate(
$docAgencies,
$request->query->getId('page', 1),
5
);
the $docAgencies is defined like that so it's no query, but that's the way I need to get the information!
$document = $em->getRepository('DocumentBundle:Document')->findOneByIdInContext($id, $currentuser);
$docAgencies = $document->getAgencies();
When first accessing the page, everything is fine and page one of the table is being shown, but as soon as I try to click on another page of the table I get an error:
Controller "DocumentBundle\Controller\Document\EditController::editAction()" requires that you provide a value for the "$id" argument (because there is no default value or because there is a non optional argument after this one).
and my route looks like this:
http://localhost/sp/web/app_dev.php/document/document/edit?page=3
so the id of the document was just deleted and there's nothing to be accessed.
I tried to add a /{page} to my route like it was recommended in other Stackoverflow questions but this doesn't seem to work for me either.
That's how I tried it:
* #Route("/document/edit/{id}/{pag}", name="documentBundle_edit", requirements={"id" = "\d+", "pag" = "\d+"}, defaults={"id" = 0, "pag":1})
the editAction:
public function editAction(Request $request, $id, $pag) {
..
and within the paginate function:
$paginator = $this->get('knp_paginator');
$agencyTable = $paginator->paginate(
$docAgencies,
$pag,
5
);
any ideas why this is not working?
update twig view
{% block content %}
{{ form_start(form) }}
<div class="row">
{% include 'Form/form_errors_banner.html.twig' %}
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-body">
<legend>{{ 'header.info'|trans }}</legend>
{% include 'DocumentBundle:Panels:DocumentInfo.html.twig' %}
</div>
</div>
<div class="panel panel-default">
<div class="panel-body">
<legend>{{ 'label.comments'|trans }}</legend>
{% include 'AppBundle::CommentTable.html.twig' with {
'entity': document,
'add_comments': true
} %}
</div>
</div>
</div>
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-body">
<legend>{{ 'label.distribution'|trans }}</legend>
<div id="upload_profile_no">
{% trans_default_domain 'AppBundle' %}
{# CONFIG #}
{% if deleteButton is not defined %}
{% set deleteButton = true %}
{% endif %}
{{ form_label(form.agencies) }}<br>
{{ form_widget(form.agencies) }} <br> <br>
<table class="footable">
{# header fields #}
<thead>
<tr>
<th data-field="iata">{{ 'label.iata'|trans }}</th>
<th data-field="name">{{ 'label.name'|trans }}</th>
<th data-field="city">{{ 'label.city'|trans }}</th>
<th data-field="country">{{ 'label.country'|trans }}</th>
{% if deleteButton %}<th data-field="delete"></th>{% endif %}
</tr>
</thead>
{% block tablebody %}
{# body fields #}
<tbody>
{% for agency in docAgencies %}
<tr>
<td data-title="iata" data-market="{{ agency.market.id }}">{{ agency.id }}</td>
<td data-title="name">{{ agency.account }}</td>
<td data-title="city">{{ agency.cityName }}</td>
<td data-title="country">{{ agency.market.id }}</td>
{% if deleteButton %}
<td data-title="delete">
<button class="btn btn-danger btn-xs btn-remove-row" type="button" data-index="{{ agency.id }}">
<span class="glyphicon glyphicon-minus"></span>
</button>
<button class="btn btn-primary btn-xs btn-undo-remove hidden" type="button" data-index="{{ agency.id }}">
<span class="glyphicon glyphicon-repeat"></span>
</button>
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
{% endblock %}
</table>
{% if docAgencies.pageCount > 1 %}
<div class="navigation text-center">
{{ knp_pagination_render(docAgencies) }}
</div>
{% endif %}
</div>
<br>
<div class="row">
<div class="col-md-6">
{{ form_row(form.airlines, { 'attr': { 'class': 'form-inline'} }) }}
</div>
<div class="col-md-6">
{{ form_row(form.products, { 'attr': { 'class': 'form-inline'} }) }}
</div>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-body">
<legend>{{ 'label.attachments'|trans }}</legend>
{% set fileDomain = 'document' %}
{% include 'AppBundle::AttachmentConfig.html.twig' %}
{% include 'AppBundle::DisplayAttachments.html.twig' with {'entity': document} %}
{% include 'AppBundle::FileUpload.html.twig' %}
</div>
</div>
</div>
</div>
<div class="row">
{% include 'AppBundle::HelpSubmitButton.html.twig' %}
</div>
{{ form_end(form) }}
{% include 'DocumentBundle:Action/UploadProfile:modals.html.twig' %}
{% endblock content %}
the part for the pagination is the table with {% for agency in docAgencies %}
**update 2 **
my full controller:
class EditController extends Controller {
/**
* #Route("/document/edit", name="documentBundle_edit2")
* #Route("/document/edit/{id}/{pag}", name="documentBundle_edit", requirements={"id" = "\d+", "pag" = "\d+"}, defaults={"id" = 0, "pag" = 1})
* #Template()
*/
public function editAction(Request $request, $id, $pag) {
$currentuser = $this->container->get('security.token_storage')->getToken()->getUser();
$em = $this->getDoctrine()->getManager();
$document = $em->getRepository('DocumentBundle:Document')->findOneByIdInContext($id, $currentuser);
$allComments = $document->getComments();
$docAgencies = $document->getAgencies();
$statusRepository = $em->getRepository('DocumentBundle:Status');
if($this->get('security.authorization_checker')->isGranted('ROLE_DOCUMENT_EDIT') && $document->getStatus()->getName() == 'Effective' && $document->isActive()
|| $this->get('security.authorization_checker')->isGranted('ROLE_CONTRACT_ADMIN')){
/*
* GET DOCUMENT FROM DB
*/
/*
* CHECK Document
*/
if($document == null)
{
return $this->get('app.error_helper')->throwError('error.404');
}
$form = $this->createForm(DocumentEditType::class, $document);
/*
* CREATE PAGINATION FOR TABLES
*/
/**
* #var $paginator \Knp\Component\Pager\Paginator
*/
$paginator = $this->get('knp_paginator');
$agencyTable = $paginator->paginate(
$docAgencies,
$pag,
5
);
$agencyTable->setTemplate('DocumentBundle::table_pagination.html.twig');
$agencyTable->setUsedRoute('documentBundle_edit');
$agencyTable->setParam('id', $id);
$commentTable = $paginator->paginate(
$allComments,
$pag,
5
);
$commentTable->setTemplate('DocumentBundle::table_pagination.html.twig');
/*
* IF REQUEST IS VALID
*/
$form->handleRequest($request);
if ($form->isValid()) {
$effective = date_format($document->getEffective(), 'Y-m-d');
$expires = date_format($document->getExpires(), 'Y-m-d');
$now = date('Y-m-d');
if($now < $effective) {
$status = $statusRepository->findOneById('3');
} elseif ($now >= $expires) {
$status = $statusRepository->findOneById('2');
} else {
$status = $statusRepository->findOneById('1');
}
$document->setStatus($status);
$em->flush();
$this->addFlash(
'success',
'The document has been edited!'
);
return $this->redirectToRoute('documentBundle_document_list');
}
/*
* DISPLAY Document
*/
return $this->render('DocumentBundle:Document:edit.html.twig', Array(
'document' => $document,
'docAgencies' => $agencyTable,
'comments' => $commentTable,
'form' => $form->createView(),
));
} else {
/*
* THROW ERROR
* If the acting user is not allowed to perform this action
*/
return $this->redirectToRoute('documentBundle_view_document', array(
'id' => $id
));
}
}
}
table_pagination.html.twig
<nav>
<ul class="pagination">
{# Previous #}
{% if startPage == 1 %}
<li class="disabled">
<a href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{% else %}
<li>
<a href="{{ path(app.request.attributes.get('_route'), {'page': startPage - 1}) }} " aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{% endif %}
{# Pages #}
{% if pageCount < 12 %}{# less than 12 Pages #}
{% for i in 1..pageCount %}
<li {% if startPage == i %}class="active"{% endif %}>{{i}}</li>
{% endfor %}
{% else %}
{% if startPage < 8 %}{# any current page before 7 #}
{# Pages #}
{% for i in 1..8 %}
<li {% if startPage == i %}class="active"{% endif %}>{{i}}</li>
{% endfor %}
<li class="disabled">...</li>
<li>{{pageCount - 1}}</li>
<li>{{pageCount}}</li>
{% else %}
{% if startPage > pageCount - 7 %}{# any current page in the last 7 #}
{# Pages #}
<li>1</li>
<li>2</li>
<li class="disabled">...</li>
{% for i in 7..0 %}
<li {% if startPage == pageCount - i %}class="active"{% endif %}>{{pageCount - i}}</li>
{% endfor %}
{% else %}{# any other Page #}
<li>1</li>
<li>2</li>
<li class="disabled">...</li>
<li>{{startPage - 2}}</li>
<li>{{startPage - 1}}</li>
<li class="active">{{startPage}}</li>
<li>{{startPage + 1}}</li>
<li>{{startPage + 2}}</li>
<li class="disabled">...</li>
<li>{{pageCount - 1}}</li>
<li>{{pageCount}}</li>
{% endif %}{# any current page in the last 7 #}
{% endif %}{# any current page before 8 #}
{% endif %}{# less than 12 Pages #}
{# Next #}
{% if startPage == pageCount %}
<li class="disabled">
<a href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
{% else %}
<li>
<a href="{{ path(app.request.attributes.get('_route'), {'page': startPage + 1}) }} " aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
{% endif %}
</ul>
</nav>
**update including #ste 's help **
Edit Controller:
* #Route("/document/edit/{id}/{page}", name="documentBundle_edit", requirements={"id" = "\d+", "page" = "\d+"}, defaults={"page" = 1})
* #Template()
*/
public function editAction(Request $request, $id, $page) {
$em = $this->getDoctrine()->getManager();
$document = $em->getRepository('DocumentBundle:Document')->findOneByIdInContext($id, $currentuser);
$allComments = $document->getComments();
$docAgencies = $document->getAgencies();
/*
* CREATE PAGINATION FOR TABLES
*/
/**
* #var $paginator \Knp\Component\Pager\Paginator
*/
$paginator = $this->get('knp_paginator');
$agencyTable = $paginator->paginate(
$docAgencies,
$page,
5
);
$agencyTable->setTemplate('DocumentBundle::table_pagination.html.twig');
$commentTable = $paginator->paginate(
$allComments,
$page,
5
);
$commentTable->setTemplate('DocumentBundle::table_pagination.html.twig');
return $this->render('DocumentBundle:Document:edit.html.twig', Array(
'document' => $document,
'docAgencies' => $agencyTable,
'comments' => $commentTable,
'form' => $form->createView(),
));
}
the pagination template
{# Pagination to be included anywhere. Needs {page, pageCount} #}
<nav>
<ul class="pagination">
{# Previous #}
{% if startPage == 1 %}
<li class="disabled">
<a href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{% else %}
<li>
<a href="{{ path(route, query|merge({'page': startPage - 1})) }} " aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{% endif %}
{# Pages #}
{% if pageCount < 12 %}{# less than 12 Pages #}
{% for i in 1..pageCount %}
<li {% if startPage == i %}class="active"{% endif %}>{{i}}</li>
{% endfor %}
{% else %}
{% if startPage < 8 %}{# any current page before 7 #}
{# Pages #}
{% for i in 1..8 %}
<li {% if startPage == i %}class="active"{% endif %}>{{i}}</li>
{% endfor %}
<li class="disabled">...</li>
<li>{{pageCount - 1}}</li>
<li>{{pageCount}}</li>
{% else %}
{% if startPage > pageCount - 7 %}{# any current page in the last 7 #}
{# Pages #}
<li>1</li>
<li>2</li>
<li class="disabled">...</li>
{% for i in 7..0 %}
<li {% if startPage == pageCount - i %}class="active"{% endif %}>{{pageCount - i}}</li>
{% endfor %}
{% else %}{# any other Page #}
<li>1</li>
<li>2</li>
<li class="disabled">...</li>
<li>{{startPage - 2}}</li>
<li>{{startPage - 1}}</li>
<li class="active">{{startPage}}</li>
<li>{{startPage + 1}}</li>
<li>{{startPage + 2}}</li>
<li class="disabled">...</li>
<li>{{pageCount - 1}}</li>
<li>{{pageCount}}</li>
{% endif %}{# any current page in the last 7 #}
{% endif %}{# any current page before 8 #}
{% endif %}{# less than 12 Pages #}
{# Next #}
{% if startPage == pageCount %}
<li class="disabled">
<a href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
{% else %}
<li>
<a href="{{ path(route, query|merge({'page': startPage + 1})) }} " aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
{% endif %}
</ul>
</nav>
and this is how I add the pagination to my template:
{{ knp_pagination_render(docAgencies) }}

It seems that you have a problem in table_pagination.html.twig.
You should replace this:
{{ path(app.request.attributes.get('_route'), {'page': THE_PAGE_YOU_HAVE}) }}
with this:
{{ path(route, query|merge({'pag': THE_PAGE_YOU_HAVE})) }}
or this
{{ path(app.request.attributes.get('_route'), app.request.query.all|merge({'pag': THE_PAGE_YOU_HAVE})) }}
Let me know if it works.
Further, you should remove the default value for id in your route for editAction

Related

How to use template form when edit object

I have a form with an embedded form (collectionType). I made a template. It works when I add a new object. But how to use this template when I edit an object ? Below my code an 2 pictures to illustrate my problem
{% extends 'base.html.twig' %}
{% form_theme form _self %}
{% block _paris_rencontres_row %}
<div class="sports" id="renc-xx" style="background-color: rgba(182, 184, 185, 0.200);">
<div
class="row">
{# <ul class="sports" data-prototype="{{ form_widget(form.vars.prototype)|e('html_attr') }}"></ul> #}
<div class="col-md-3">
{{ form_row(form.vars.prototype.playedAt) }}
</div>
<div class="col-md-3">
{{ form_row(form.vars.prototype.sport) }}
</div>
</div>
<div class="row">
<div class="col-md-3">
{{ form_row(form.vars.prototype.player_1) }}
</div>
<div class="col-md-3">
{{ form_row(form.vars.prototype.player_2) }}
</div>
<div class="col-md-2">
{{ form_row(form.vars.prototype.cote) }}
</div>
<div class="col-md-2">
{{ form_row(form.vars.prototype.resultat) }}
</div>
</div>
<hr>
</div>
{% endblock %}
{% block body %}
{# {{ include('paris/_form.html.twig', {form:form, button: 'Ajouter'}) }} #}
<button type='button' id='btn-add' class='add_sport_link btn btn-primary'>Ajouter paris</button>
{{ form_start(form) }}
<div class="paris">
<div class="row">
<div class="col-md-4">
{{ form_row(form.mise) }}
</div>
<div class="col-md-4">
{{ form_row(form.type) }}
</div>
<div class="col-md-4">
{{ form_row(form.win) }}
</div>
</div>
<div class="col-md-4 matchs">
{% if form.rencontres|length > 0 %}
{% for index in 0..form.rencontres|length - 1 %}
{{ dump(index) }}
{{ form_row(form.rencontres[index]) }}
{% endfor %}
{% else %}
{{ form_row(form.rencontres) }}
{% endif %}
</div>
</div>
{{ form_end(form) }}
{% endblock %}
add (form.rencontres|length == 0):
enter image description here
edit (form.rencontres|length > 0):
enter image description here
Regards
PS: Sorry for my english
EDIT: My controller
#NicoHaase I dont think the problem is in the code.
I want just display my form template when I edit an object as when I add an object
`code
/**
* #Route("/paris/add", name="paris_add")
*/
public function add(Request $request)
{
$em = $this->getDoctrine()->getManager();
$paris = new paris();
$form = $this->createForm(ParisType::class, $paris);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em->persist($paris);
$em->flush();
return $this->redirectToRoute('paris');
}
return $this->render("paris/add.html.twig", [
'form' => $form->createView()
]);
}
/**
* #Route("/paris/{id}", name="paris_edit", requirements={"id":"\d+"})
* #param Paris $paris
* #param Request $request
*/
public function edit(Request $request, Paris $paris)
{
$form = $this->createForm(ParisType::class, $paris);
$form->handleRequest($request);
return $this->render("paris/add.html.twig", [
"paris" => $paris,
"form" => $form->createView(),
]);
}
`

Multiple items in bootstrap carousel `carousel-item` using Twig/Timber/Wordpress and Bootstrap 4

what I want is that each carousel-item hold card group with 3 cards inside .. so ..
in this particular case, there are 8 related posts, it would like this .. *[(1)(2)(3)] -> [(4)(5)(6)] -> [(7)(8) ]
[Twig file]
{% set division = (related|length - 1)/ 3 %}
{% from _self import post_cards %}
<div class="container">
<div id="carouselExampleIndicators" class="carousel slide">
<ol class="carousel-indicators">
{% for i in 0..division %}
<li data-target="#carouselExampleIndicators" data-slide-to="{{ i }}" class="{{ i == 0 ? 'active' : ''}}"></li>
{% endfor %}
</ol>
{# -- inner elements -- #}
<div class="carousel-inner bg-warning">
{% for post in related %}
{% if (loop.index0 is divisible by(3)) or (loop.first) %}
<div class="carousel-item {{ loop.first ? 'active' : ''}}"> {# d-flex #}
<div class="card-group w-100">
{% endif %}
{{ post_cards('col-md-4 my-4', post)}}
{% if (loop.index0 is divisible by(3)) or (loop.first) %}
</div>
</div>
{% endif %}
{% endfor %}
</div>
{# --- end of inner elements --- #}
</div>
</div>{# END container --- #}
{# --- card macro #}
{% macro post_cards(classes, post) %}
<div class="{{ classes }}">
<div class="card h-100">
<a class="text-decoration-none blog-card-link h-100" alt="Link to blog post" role="button"
target="_self" href="{{ post.link }}">
<img src="{{ post.thumbnail.src }}" class="card-img-top my-0" alt="Image for {{ post.title }}">
<div class="card-body">
<p class="post-category font-weight-medium">{{ post.category }}</p>
<h3 class="card-title font-weight-bold">{{ post.title }}</h3>
<p class="card-text">
{% set post_preview = post.meta('on_blog_list') %}
{{ post_preview ? post_preview|truncate(10) : post.preview.length(10).read_more(null) }}
</p>
</div>
<div class="card-footer bg-transparent border-0">
<span class="blog-date">
{{ post.date }}
</span>
<a class="d-inline btn-link arrow-link float-right"
alt="Read more" role="button"
target="_self" href="{{ post.link }}">
read
</a>
</div>
</a>
</div>
</div>
{% endmacro post_cards %}
..generates following
code above generates this
so cards fall outside the carousel-item
You have same condition for opening and closing div.
Try something like this.
{# -- inner elements -- #}
<div class="carousel-inner bg-warning">
{% set x = 0 %}
{% for post in 1..15 %}
{% set x = x + 1 %}
{% if x == 1 %} {# opening div on 1st item #}
<div class="carousel-item {{ loop.first ? 'active' : ''}}"> {# d-flex #}
<div class="card-group w-100">
{% endif %}
{{ post_cards('col-md-4 my-4', post)}}
{% if x == 3 %} {# closing div after 3rd item #}
</div>
</div>
{% set x = 0 %}
{% endif %}
{% endfor %}
</div>
{# --- end of inner elements --- #}

Customize SonataAdminBundle base_edit_form.html.twig

I would like to show the map in the form generated by Sonata Admin Bundle
This is my formMapper,
class PlaceInfoAdmin extends Admin
{
public function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('General')
->add('lati')
->add('longi')
->add('name')
I am using ivory google map API.
Simplifying what I want to do,
put this code at the last of template used by PlaceInfoAdmin
{{ ivory_google_api([
data.map,
data.form.field.vars['autocomplete']
])}}
put this code between rendered the cide of longi and name.
{{ ivory_google_map(data.map) }}
Now I research the twig files and found out maybe form is rendered by base_edit_form.html.twig,
However where should I alter?? or How can I find this twig is called by PlaceInfoAdmin?? (not by another ****Admin class)
{% block form %}
{{ sonata_block_render_event('sonata.admin.edit.form.top', { 'admin': admin, 'object': object }) }}
{% set url = admin.id(object) is not null ? 'edit' : 'create' %}
{% if not admin.hasRoute(url)%}
<div>
{{ "form_not_available"|trans({}, "SonataAdminBundle") }}
</div>
{% else %}
<form
{% if sonata_admin.adminPool.getOption('form_type') == 'horizontal' %}class="form-horizontal"{% endif %}
role="form"
action="{% block sonata_form_action_url %}{{ admin.generateUrl(url, {'id': admin.id(object), 'uniqid': admin.uniqid, 'subclass': app.request.get('subclass')}) }}{% endblock %}"
{% if form.vars.multipart %} enctype="multipart/form-data"{% endif %}
method="POST"
{% if not sonata_admin.adminPool.getOption('html5_validate') %}novalidate="novalidate"{% endif %}
{% block sonata_form_attributes %}{% endblock %}
>
{{ include('SonataAdminBundle:Helper:render_form_dismissable_errors.html.twig') }}
{% block sonata_pre_fieldsets %}
<div class="row">
{% endblock %}
{% block sonata_tab_content %}
{% set has_tab = ((admin.formtabs|length == 1 and admin.formtabs|keys[0] != 'default') or admin.formtabs|length > 1 ) %}
<div class="col-md-12">
{% if has_tab %}
<div class="nav-tabs-custom">
<ul class="nav nav-tabs" role="tablist">
{% for name, form_tab in admin.formtabs %}
<li{% if loop.index == 1 %} class="active"{% endif %}><i class="fa fa-exclamation-circle has-errors hide" aria-hidden="true"></i> {{ name|trans({}, form_tab.translation_domain ?: admin.translationDomain) }}</li>
{% endfor %}
</ul>
<div class="tab-content">
{% for code, form_tab in admin.formtabs %}
<div class="tab-pane fade{% if loop.first %} in active{% endif %}" id="tab_{{ admin.uniqid }}_{{ loop.index }}">
<div class="box-body container-fluid">
<div class="sonata-ba-collapsed-fields">
{% if form_tab.description != false %}
<p>{{ form_tab.description|raw }}</p>
{% endif %}
{{ form_helper.render_groups(admin, form, form_tab['groups'], has_tab) }}
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% else %}
{{ form_helper.render_groups(admin, form, admin.formtabs['default'].groups, has_tab) }}
{% endif %}
</div>
{% endblock %}
{% block sonata_post_fieldsets %}
</div>
{% endblock %}
{{ form_rest(form) }}
{% block formactions %}
<div class="sonata-ba-form-actions well well-small form-actions">
{% block sonata_form_actions %}
{% if app.request.isxmlhttprequest %}
{% if admin.id(object) is not null %}
<button type="submit" class="btn btn-success" name="btn_update"><i class="fa fa-save" aria-hidden="true"></i> {{ 'btn_update'|trans({}, 'SonataAdminBundle') }}</button>
{% else %}
<button type="submit" class="btn btn-success" name="btn_create"><i class="fa fa-plus-circle" aria-hidden="true"></i> {{ 'btn_create'|trans({}, 'SonataAdminBundle') }}</button>
{% endif %}
{% else %}
{% if admin.supportsPreviewMode %}
<button class="btn btn-info persist-preview" name="btn_preview" type="submit">
<i class="fa fa-eye" aria-hidden="true"></i>
{{ 'btn_preview'|trans({}, 'SonataAdminBundle') }}
</button>
{% endif %}
{% if admin.id(object) is not null %}
<button type="submit" class="btn btn-success" name="btn_update_and_edit"><i class="fa fa-save" aria-hidden="true"></i> {{ 'btn_update_and_edit_again'|trans({}, 'SonataAdminBundle') }}</button>
{% if admin.hasroute('list') and admin.isGranted('LIST') %}
<button type="submit" class="btn btn-success" name="btn_update_and_list"><i class="fa fa-save"></i> <i class="fa fa-list" aria-hidden="true"></i> {{ 'btn_update_and_return_to_list'|trans({}, 'SonataAdminBundle') }}</button>
{% endif %}
{% if admin.hasroute('delete') and admin.isGranted('DELETE', object) %}
{{ 'delete_or'|trans({}, 'SonataAdminBundle') }}
<a class="btn btn-danger" href="{{ admin.generateObjectUrl('delete', object) }}"><i class="fa fa-minus-circle" aria-hidden="true"></i> {{ 'link_delete'|trans({}, 'SonataAdminBundle') }}</a>
{% endif %}
{% if admin.isAclEnabled() and admin.hasroute('acl') and admin.isGranted('MASTER', object) %}
<a class="btn btn-info" href="{{ admin.generateObjectUrl('acl', object) }}"><i class="fa fa-users" aria-hidden="true"></i> {{ 'link_edit_acl'|trans({}, 'SonataAdminBundle') }}</a>
{% endif %}
{% else %}
{% if admin.hasroute('edit') and admin.isGranted('EDIT') %}
<button class="btn btn-success" type="submit" name="btn_create_and_edit"><i class="fa fa-save" aria-hidden="true"></i> {{ 'btn_create_and_edit_again'|trans({}, 'SonataAdminBundle') }}</button>
{% endif %}
{% if admin.hasroute('list') and admin.isGranted('LIST') %}
<button type="submit" class="btn btn-success" name="btn_create_and_list"><i class="fa fa-save"></i> <i class="fa fa-list" aria-hidden="true"></i> {{ 'btn_create_and_return_to_list'|trans({}, 'SonataAdminBundle') }}</button>
{% endif %}
<button class="btn btn-success" type="submit" name="btn_create_and_create"><i class="fa fa-plus-circle" aria-hidden="true"></i> {{ 'btn_create_and_create_a_new_one'|trans({}, 'SonataAdminBundle') }}</button>
{% endif %}
{% endif %}
{% endblock %}
</div>
{% endblock formactions %}
</form>
{% endif%}
{{ sonata_block_render_event('sonata.admin.edit.form.bottom', { 'admin': admin, 'object': object }) }}
{% endblock %}
{% endblock %}
Ho
Create a template that extends base_edit.html.twig:
{% extends 'SonataAdminBundle:CRUD:base_edit.html.twig' %}
{% block form %}
{# your custom code #}
{{ parent() }}
{% endblock %}
Then to make sure only the admin you want uses that template pass it in the definition of your admin service with a setTemplate call:
librinfo_crm.admin.contact:
class: Librinfo\CRMBundle\Admin\ContactAdmin
arguments: [~, Librinfo\CRMBundle\Entity\Contact, SonataAdminBundle:CRUD]
tags:
- name: sonata.admin
manager_type: orm
group: Customers Relationship Management
label: librinfo.crm.contact_admin.label
label_translator_strategy: blast_core.label.strategy.librinfo
calls:
- [ setTemplate, [edit, LibrinfoCRMBundle:OrganismAdmin:edit.html.twig]]

How to show mobile menu on Shopify Site

I have designed a new site using the Timber Framework in Shopify and I am now trying to sort out the responsive side to ensure this works on all devices properly.
The problem I am currently facing is that when the screen is resized to below 768px the desktop menu goes away which is fine but no menu shows up at all and I am not sure why this is. Initially when I added the Timber Framework then this was working and I have looked through the theme.liquid file but can't work why this is happening.
The site itself can be viewed at : http://www.prontaprint247.com
If somebody could please advise as to where I have gone wrong as not sure how to fix this issue.
Any help or advice would be appreciated.
My menu code in theme.liquid
<div id="NavDrawer" class="drawer drawer--left">
<div class="drawer__header">
<div class="drawer__title h3">{{ 'layout.drawers.browse' | t }}</div>
<div class="drawer__close js-drawer-close">
<button type="button" class="icon-fallback-text">
<span class="icon icon-x" aria-hidden="true"></span>
<span class="fallback-text">{{ 'layout.drawers.close_menu' | t }}</span>
</button>
</div>
</div>
<!-- begin mobile-nav -->
<ul class="mobile-nav">
<li class="mobile-nav__item mobile-nav__search">
{% include 'search-bar' %}
</li>
{% for link in linklists.main-menu.links %}
{% comment %}
Create a dropdown menu by naming a linklist the same as a link in the parent nav
More info on dropdowns:
- http://docs.shopify.com/manual/your-website/navigation/create-drop-down-menu
{% endcomment %}
{% assign child_list_handle = link.title | handleize %}
{% if linklists[child_list_handle].links != blank %}
<li class="mobile-nav__item{% if link.active %} mobile-nav__item--active{% endif %}" aria-haspopup="true">
<div class="mobile-nav__has-sublist">
{{ link.title }}
<div class="mobile-nav__toggle">
<button type="button" class="icon-fallback-text mobile-nav__toggle-open">
<span class="icon icon-plus" aria-hidden="true"></span>
<span class="fallback-text">See More</span>
</button>
<button type="button" class="icon-fallback-text mobile-nav__toggle-close">
<span class="icon icon-minus" aria-hidden="true"></span>
<span class="fallback-text">{{ 'cart.general.close_cart' | t | json }}</span>
</button>
</div>
</div>
<ul class="mobile-nav__sublist">
{% for childlink in linklists[child_list_handle].links %}
<li class="mobile-nav__item {% if childlink.active %} mobile-nav__item--active{% endif %}">
{{ childlink.title | escape }}
</li>
{% endfor %}
</ul>
</li>
{% else %}
<li class="mobile-nav__item{% if link.active %} mobile-nav__item--active{% endif %}">
{{ link.title }}
</li>
{% endif %}
{% endfor %}
{% comment %}
If customer accounts are enabled, provide login and create account links
{% endcomment %}
{% if shop.customer_accounts_enabled %}
{% if customer %}
<li class="mobile-nav__item">
{% if customer.first_name != blank %}
{% capture first_name %}{{ customer.first_name }}{% endcapture %}
{{ 'layout.customer.logged_in_as_html' | t: first_name: first_name }}
{% else %}
{{ 'layout.customer.account' | t }}
{% endif %}
</li>
<li class="mobile-nav__item">
{{ 'layout.customer.log_out' | t | customer_logout_link }}
</li>
{% else %}
<li class="mobile-nav__item">
{{ 'layout.customer.log_in' | t | customer_login_link }}
</li>
<li class="mobile-nav__item">
{{ 'layout.customer.create_account' | t | customer_register_link }}
</li>
{% endif %}
{% endif %}
</ul>
<!-- //mobile-nav -->
</div>

Liquid default expanded menu

I have a liquid dropdown menu with a list of products that only expand when you click. I figured out how to open it by default when loading the site.
I simply found the <ul> tag for my dropdown list and changed it from this:
<ul id="Collapsible{{ forloop.index }}" class="site-nav__submenu site-nav__submenu--expanded" aria-hidden="false">
to this:
<ul id="Collapsible{{ forloop.index }}" class="site-nav__submenu site-nav__submenu--expand" aria-hidden="false">
However, I would also like it to be closed by default on small screens.
So far I haven't been able to find a solution that allows me to do that. I'm open to both liquid and CSS solutions. Anyone got any ideas?
Here is my code as it looks now with the default expand:
<div class="grid">
<nav class="grid__item small--text-center medium-up--one-fifth" id="makeShort" role="navigation">
<hr class="hr--small medium-up--hide">
<button data-target="site-nav" id="ToggleMobileMenu" class="mobile-menu-icon medium-up--hide" aria-haspopup="true" aria-owns="SiteNav">
<span class="line"></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"></span>
<span class="icon__fallback-text">{{ 'layout.navigation.menu' | t }}</span>
</button>
<div id="SiteNav" class="site-nav" role="menu">
<ul class="list--nav">
{% for link in menus.main-menu.links %}
{% assign child_list_handle = link.title | handleize %}
{% if menus[child_list_handle].links != blank %}
<li class="site-nav--has-submenu site-nav__element">
{% if link.title == 'Shop' %}
<button class="site-nav__link btn--link site-nav__expand hidden" aria-expanded="false" aria-controls="Collapsible{{ forloop.index }}">
{{ link.title }}
<span>+</span>
</button>
<button class="site-nav__link btn--link site-nav__collapse" aria-expanded="true" aria-controls="Collapsible{{ forloop.index }}">
{{ link.title }}
<span>-</span>
</button>
<ul id="Collapsible{{ forloop.index }}" class="site-nav__submenu site-nav__submenu--expand" aria-hidden="false">
{% for childlink in menus[child_list_handle].links %}
<li class="{% if childlink.active or collection.current_type == childlink.title or collection.current_vendor == childlink.title %}{% unless forloop.first and childlink.title contains 'All' and current_tags.size > 0 %} site-nav--active {% endunless %}{% endif %}">
{{ childlink.title | escape }}
</li>
{% endfor %}
</ul>
</li>
{% else %}
<button class="site-nav__link btn--link site-nav__expand hidden" id="hideOnLargeScreen" aria-expanded="false" aria-controls="Collapsible{{ forloop.index }}">
{{ link.title }}
<span>+</span>
</button>
<button class="site-nav__link btn--link site-nav__collapse" id="hideOnLargeScreen" aria-expanded="true" aria-controls="Collapsible{{ forloop.index }}">
{{ link.title }}
<span>-</span>
</button>
<ul id="Collapsible{{ forloop.index }}" class="site-nav__submenu site-nav__submenu--expanded" id="hideOnLargeScreen" aria-hidden="false">
{% for childlink in menus[child_list_handle].links %}
<li class="{% if childlink.active or collection.current_type == childlink.title or collection.current_vendor == childlink.title %}{% unless forloop.first and childlink.title contains 'All' and current_tags.size > 0 %} site-nav--active {% endunless %}{% endif %}">
{{ childlink.title | escape }}
</li>
{% endfor %}
</ul>
{% endif %}
{% else %}
<li class="site-nav__element {% if link.active %}site-nav--active{% endif %}">
{% if link.title == 'Shop' %}
{{ link.title }}
{% else %}
{{ link.title }}
{% endif %}
</li>
{% endif %}
{% endfor %}
{% if shop.customer_accounts_enabled %}
{% if customer %}
<li>
{{ 'layout.customer.account' | t }}
</li>
<li>
{{ 'layout.customer.log_out' | t }}
</li>
{% else %}
<li>
{{ 'layout.customer.log_in' | t }}
</li>
<li>
{{ 'layout.customer.create_account' | t }}
</li>
{% endif %}
{% endif %}
</ul>
{% include 'custom.social-bar' %}
</div>
<hr class="medium-up--hide hr--small {% if template == 'index' %}{% if settings.home_section_1 == 'banner-image' or settings.home_section_1 == 'featured-products' %}hr--border-bottom{% endif %}{% endif %}">
</nav>
It's nothing that belongs to liquid or Shopify. You easily can do this with common solutions. For example you could use jQuery by putting something like this into your theme js file:
$( window ).resize(function() {
if ($(window).width() < 700 ) { // Size of "small"
$('.list--nav ul').addClass('site-nav__submenu--expanded').removeClass('site-nav__submenu--expand');
} else {
$('.list--nav ul').addClass('site-nav__submenu--expand').removeClass('site-nav__submenu--expanded');
}
});
But you also could put the css code of .site-nav__submenu--expand into a condition for large devices like:
#media (min-width:960px) {
.site-nav__submenu--expand {...}
}

Resources