Privet all!
I'm new to Symfony 4 and generally to PHP and OOP in general. I was helped to make the form using FormCollection the code looks so
AbilityContoller.php
/**
* #Route("/edit", name="ability_edit_all")
*/
public function edit(Request $request)
{
$abilitys = $this->getDoctrine()->getRepository(Ability::class)->findAll();
$form = $this->createForm(AbilityArrayType::class, ['abilitys' => $abilitys]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
foreach ($form->getData()['abilitys'] as $ability){
$this->getDoctrine()->getManager()->persist($ability);
}
$this->getDoctrine()->getManager()->flush();
$this->addFlash('notice', 'Your changes were saved!');
return $this->redirectToRoute('ability_edit_all');
}
return $this->render('ability/edit.all.html.twig', [
'form' => $form->createView()
]);
}
and screenshot
you see that my record with the form has both tags with a choiceType and a simple input
And I also figured out myself with knp_paginator, because if I output more than 15 records with FormCollection, I get an error about the lack of memory in php. I made a static table where I output all my records, sorting and filtering works, pagination is broken as it should.
here is the code
ServiceFile.php
class AbilityService{
protected $em;
protected $container;
public function __construct(EntityManagerInterface $entityManager, ContainerInterface $container)
{
$this->em = $entityManager;
$this->container = $container;
}
public function ReturnData($request){
$em = $this->em;
$container = $this->container;
$query = $em->createQuery(
'
SELECT
t.idItem,
t.code,
t.reloadTime,
t.durationTime,
t.idAbilityType
FROM
App\Entity\Ability t
'
);
dump($query);
//$result = $query->execute();
$pagenator = $container->get('knp_paginator');
$results = $pagenator->paginate(
$query,
$request->query->getInt('page', 1),
$request->query->getInt('limit', 10)
);
return ($results);
}
}
and controller
use App\Service\ServiceFile;
/**
* #Route("/test-edit", name="ability_test_edit_all")
*/
public function edit_test(AbilityService $query, Request $request)
{
$data = $query->ReturnData($request);
return $this->render('ability/edit.alltest.html.twig',[
'form' => $data,
]);
}
here screenshot
Work a perfect!!
I bet I can not figure out how to make the same result, but with FormCollection?
The second question, if it turns out to be pagination, will filtering and sorting work from knp_paginator?
ok,
ok, something happened and it's not right for mine, but Pagination and sorting + filtering work only on <input> tags, inside <select> <option selected> var </ select> nothing works, but the solution is working
controllerFile.php
/**
* #Route("/edit", name="ability_edit_all")
*/
public function edit(AbilityService $abilityService, Request $request)
{
$data = $abilityService->ReturnData($request);
$form = $this->createForm(AbilityArrayType::class, ['abilitys' => $data->getItems()]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
foreach ($form->getData()['abilitys'] as $properties){
dump($properties);
$ability = $this->getDoctrine()->getRepository(Ability::class)->find($properties['id']);
$ability->setIdItem($properties['idItem']);
$ability->setCode($properties['code']);
$ability->setReloadTime($properties['reloadTime']);
$ability->setDurationTime($properties['durationTime']);
$ability->setIdAbilityType($properties['idAbilityType']);
dump($ability);
$this->getDoctrine()->getManager()->persist($ability);
}
$this->getDoctrine()->getManager()->flush();
$this->addFlash('notice', 'Your changes were saved!');//проделать со всеми см edit.html.twig
return $this->redirectToRoute('ability_edit_all');
}
return $this->render('ability/edit.all.html.twig', [
'form' => $form->createView(),
'paginator' => $data
]);
}
twig tempalte
{% extends 'base.html.twig' %}
{% block title %}Ability edit all{% endblock %}
{% block body %}
<style>
label{display:none}
</style>
<h1>Ability edit all</h1>
<a class="btn-add mar-bot-top-20" href="{{ path('ability_new') }}"><i class="fas fa-plus"></i> Create new</a>
<div class="row">
<div class="col-4 text-center">
<div class="navigation">
{{ knp_pagination_render(paginator) }}
</div>
</div>
<div class="col-8 text-left">
<div class="filtration">
{{ knp_pagination_filter(paginator, {
't.idItem': 'IdItem',
't.code': 'Code',
't.reloadTime': 'ReloadTime',
't.durationTime': 'DurationTime',
't.idAbilityType': 'IdAbilityType',
}) }}
</div>
</div>
</div>
<table class="table">
<tr>
<th>{{ knp_pagination_sortable(paginator, 'idItem', 't.idItem') }}</th>
<th>{{ knp_pagination_sortable(paginator, 'Code', 't.code') }}</th>
<th>{{ knp_pagination_sortable(paginator, 'ReloadTime', 't.reloadTime') }}</th>
<th>{{ knp_pagination_sortable(paginator, 'DurationTime', 't.durationTime') }}</th>
<th>{{ knp_pagination_sortable(paginator, 'idAbilityType', 't.idAbilityType') }}</th>
</tr>
{{ form_start(form) }}
{% for ability in form.abilitys %}
<tr>
<td>{{ form_row(ability.idItem) }}</td>
<td>{{ form_row(ability.code) }}</td>
<td>{{ form_row(ability.reloadTime) }}</td>
<td>{{ form_row(ability.durationTime) }}</td>
<td>{{ form_row(ability.idAbilityType) }}</td>
</tr>
{% else %}
<tr>
<td colspan="9">no records found</td>
</tr>
{% endfor %}
{{ form_end(form) }}
</table>
<div class="row">
<div class="col-4 text-center">
<div class="navigation">
{{ knp_pagination_render(paginator) }}
</div>
</div>
<div class="col-8 text-left">
<div class="filtration">
{{ knp_pagination_filter(paginator, {
't.idItem': 'IdItem',
't.code': 'Code',
't.reloadTime': 'ReloadTime',
't.durationTime': 'DurationTime',
't.idAbilityType': 'IdAbilityType',
}) }}
</div>
</div>
</div>
<a class="btn-add" href="{{ path('ability_new') }}"><i class="fas fa-plus"></i> Create new</a>
{% for message in app.flashes('notice') %}
<div class="flash-notice">
{{ message }}
</div>
{% endfor %}
{% endblock %}
and ServiceFile.php
<?php
namespace App\Service;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\Ability;
class AbilityService{
protected $em;
protected $container;
public function __construct(EntityManagerInterface $entityManager, ContainerInterface $container)
{
$this->em = $entityManager;
$this->container = $container;
}
public function ReturnData($request){
$em = $this->em;
$container = $this->container;
$query = $em->createQuery(
'
SELECT
t.id,
t.idItem,
t.code,
t.reloadTime,
t.durationTime,
t.idAbilityType,
t.dateCreated,
t.author,
t.dateChange,
t.lastAuthor
FROM
App\Entity\Ability t
'
);
$pagenator = $container->get('knp_paginator');
$results = $pagenator->paginate(
$query,
$request->query->getInt('page', 1),
$request->query->getInt('limit', 6)
);
return ($results);
}
}
if anyone can tell how to implement sorting within <select> <option selected> var </ select>, you can use <th> {{knp_pagination_sortable (paginator, 'idItem', 't.idItem')}} </ th>
write please!
Related
I am trying to build a list filter in Symfony. I'm still new to PHP, MySQL, and twig. The official documentation doesn't help a lot. It is required that I have a page with a list of all classes and next to that a search bar where the user inputs the class they want and it will show on the page without the others. I'll post my code but I think it is missing a lot of code. I only need little help and maybe sources for documentation on how to do it the official documents aren't very clear for someone with zero experience.
My ClassesRepository.php
<?php
namespace App\Repository;
use App\Entity\Classes;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* #method Classes|null find($id, $lockMode = null, $lockVersion = null)
* #method Classes|null findOneBy(array $criteria, array $orderBy = null)
* #method Classes[] findAll()
* #method Classes[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class ClassesRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Classes::class);
}
public function findbyName()
{
return $this->createQueryBuilder('c')
->getQuery()->getResult();
}
public function getSearchClasses($class){
$qb = $this->createQueryBuilder('c')
->where('c.Title LIKE :Title')
->setParameter('Title', '%' . $class->getTitle() . '%')
->orderBy('c.Title', 'DESC')
->getQuery();
}
}
classesController:
<?php
namespace App\Controller;
use App\Entity\Classes;
use App\Entity\Students;
use App\Entity\Courses;
use Symfony\Component\Form\FormTypeInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
class ClassesController extends AbstractController
{
/**
* #Route("custom/classes", name="classes_list")
*/
public function index()
{
$classes = $this->getDoctrine()->getRepository(classes::class)->findAll();
return $this->render('classes/index.html.twig', [
'classes' => $classes
]);
}
/**
* #Route("/classes/new", name="new_class")
* #Method({"GET","POST"})
*/
public function new(Request $request)
{
$class = new Classes();
$form = $this->createFormBuilder($class)
->add('Title', TextType::class, array('attr' =>
array('class' => 'form-control')))
->add('save', SubmitType::class,array('label' => 'Create',
'attr' => array('class' => 'btn btn-primary mt-3')))
->getForm();
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$class = $form->getData();
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($class);
$entityManager->flush();
return $this->redirectToRoute('classes_list');
}
return $this->render('classes/new.html.twig', array(
'form' => $form->createView()
));
}
/**
* #Route("/classes/edit/{id}", name="edit_class")
* #Method({"GET","POST"})
*/
public function edit(Request $request, $id)
{
$class = new Classes();
$class = $this->getDoctrine()->getRepository(classes::class)->find($id);
$form = $this->createFormBuilder($class)
->add('Title', TextType::class, array('attr' =>
array('class' => 'form-control')))
->add('save', SubmitType::class,array('label' => 'Create',
'attr' => array('class' => 'btn btn-primary mt-3')))
->getForm();
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->flush();
return $this->redirectToRoute('classes_list');
}
return $this->render('classes/edit.html.twig', array(
'form' => $form->createView()
));
}
/**
* #Route("/classes/delete/{id}")
* #Method({"DELETE"})
*/
public function delete(Request $request, $id){
$class = $this->getDoctrine()->getRepository(Classes::class)->find($id);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->remove($class);
$entityManager->flush();
$response = new Response();
$response->send();
}
/**
* #Route("/classes/{id}", name="classes_show")
* #Method({"GET"})
*/
public function show($id){
$_class = $this->getDoctrine()->getRepository(Classes::class)->find($id);
return $this->render('classes/show.html.twig', array('classes' => $_class));
}
// /**
// * #Route("custom/classes/save")
// */
// public function save() {
// $entityManager = $this->getDoctrine()->getManager();
// $classes = new Classes();
// $classes->setTitle('Grade 2');
// $entityManager->persist($classes);
// $entityManager->flush();
// return new Response('Saved an classes with the id of '.$classes->getId());
// }
}
Index.html.twig is Location where I will need to locate the list filter
{% extends 'base.html.twig' %}
{% block title %}Classes{% endblock %}
{% block body %}
<br>
<h1>Classes:</h1>
Create
<br>
{% if classes %}
<div class="alignleft">
<table id="classes" class="table table-striped" style="width:70%">
<thead>
<tr>
<th>Class</th>
<th>Details </th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{% for classes in classes %}
<tr>
<td> {{ classes.title }}</td>
<td>
Show Class Details
</td>
<td>
Edit
</td>
<td>
X
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div>
<form method="GET" action="search" style = "position:absolute; left:1100px; top:150px; height:100px; width:100px">
<input type="text" name="q" placeholder="Search Query...">
<select name="column" style = "position:absolute; left:40px; top:30px; width:100px ">
<option value="classes.Title" >Class</option>
</select>
<input type="submit" class="btn btn-warning" value="Find" style = "position:absolute; left:40px; top:56px; width:100px ">
</form>
</div>
{% else %}
<p>No Classes Available</p>
{% endif %}
{% endblock %}
{% block javascripts %}
<script src="/js/classmain.js"></script>
{% endblock %}
I don't understand the behavior you expect from the filter but I hope it will help you..
In your ClassesRepository.php
// if has not $classTitle and $query it will find all
public function getSearchClasses($classTitle = null , $query=null){
$qb = $this->createQueryBuilder('c')
->orderBy('c.Title', 'DESC');
if($classTitle && $classTitle !== '') {
$qb->andWhere('c.Title LIKE :classTitle')
->setParameter('classTitle', '%' . classTitle . '%');
}
if($query && $query !== '') {
// doSomethings with query input
}
return $qb->getQuery()->getResult();
}
In your classesController:
/**
* #Route("custom/classes", name="classes_list")
*/
public function index(Request $request)
{
$classTitle = $request->query->get('classTitle',null);
$query = $request->query->get('query',null);
// if has not $classTitle and $query it will find all
$classes = $this->getDoctrine()->getRepository(classes::class)->getSearchClasses($classTitle,$query);
return $this->render('classes/index.html.twig', [
'classes' => $classes
]);
}
In your index.html.twig
// redirect to the same route that render this template ..
<form method="GET" action="{{ path('classes_list') }}">
<input type="text" name="query" placeholder="Search Query...">
<select name="classTitle">
{% for class in classes%}
<option value="{{class.title}" >{{class.title}}</option>
{% endfor %}
</select>
<input type="submit" class="btn btn-warning" value="Find">
</form>
We have a strange error in our Symfony 2 project. We use Symfony forms, and we don't have any problems in our development environment, but do receive messages of an error in production. An error we can't replicate, and never had. Everything works fine when we test (both in prod & dev) but we do receive notifications of this error happening.
We are notified of the error:
"exception":"[object] (Symfony\Component\Debug\Exception\FatalThrowableError(code: 0): Type error: Argument 1 passed to Symfony\Component\Form\FormRenderer::renderBlock() must be an instance of Symfony\Component\Form\FormView, null given
Most important code (Stripped for compactness & readability )
Formtype:
class WishlistType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('rank', HiddenType::class)
->add('description', TextType::class)
// Image is deprecated and will be removed.
->add('image');
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
'data_class' => Item::class,
]
);
}
}
Controller:
public function showAction(Request $request, $url)
{
/** #var Participant $participant */
$participant = $this->get('participant_repository')->findOneByUrl($url);
if ($participant === null) {
throw new NotFoundHttpException();
}
$wishlistForm = $this->createForm(
WishlistType::class,
$participant,
[
'action' => $this->generateUrl(
'wishlist_update',
['url' => $participant->getUrl()]
),
]
);
if (!$request->isXmlHttpRequest()) {
return [
'entry' => $participant,
'wishlistForm' => $wishlistForm->createView(),
];
}
}
Twig template:
{{ form_start(wishlistForm, {'attr': {'id': 'add_item_to_wishlist_form'}}) }}
{{ form_row(wishlistForm._token) }}
<table>
<!-- ADD SOMETHING TO YOUR WISHLIST -->
<thead>
<tr>
<th>#</th>
<th>{{ 'entry_show_valid.label.description'|trans }}</th>
<th>
<button type="button" class="btn btn-mini btn-success add-new-entry">
{{ 'entry_show_valid.btn.add_wishlist'|trans }}
</button>
</th>
</tr>
</thead>
<!-- OVERVIEW OF ITEMS IN WISHLIST, AND POSSIBILITY TO REMOVE SINGLE ITEMS-->
<tbody>
{% for item in wishlistForm.wishlistItems %}
<tr>
<td>{{ form_widget(item.rank) }}
<span>{{ item.rank.vars.value }}</span>
</td>
<td>
{{ form_widget(item.description, {'attr': {'class': 'wishlistitem-description'} }) }}
</td>
<td>
<button type="submit" >
<span>{{ 'entry_show_valid.btn.update_item'|trans }}</span>
</button>
<button type="button">
<span>{{ 'entry_show_valid.btn.remove_item'|trans }}</span>
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ form_end(wishlistForm, {'render_rest': false}) }}
Form handling is done over Ajax, but request is handled as regular symfony form ($wishlistForm->handleRequest($request); etc...).
I don't understand how you can do this :
{% for item in wishlistForm.wishlistItems %}
because I don't see any 'wishlistItems' in your form declaration.
For me, this code has to fail at this line...
The question is how to pass a json to twig to render a template. I've tried to pass a json with JsonResponse object but I did not find the way to render the template.
TarifasController.php
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien#symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace AppBundle\Controller\Admin;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use AppBundle\Entity\Tarifa;
/**
*
* #Route("/tarifas")
*/
class TarifasController extends Controller
{
/**
* #Route("/", name="tarifa_index")
*/
public function indexAction()
{
$entityManager = $this->getDoctrine()->getManager();
$tarifas = $entityManager->getRepository('AppBundle:Tarifa')->findAll();
return $this->render('admin/tarifas/index.html.twig', array('tarifas' => $tarifas));
//return new JsonResponse(array('json_tarifas' => json_encode($tarifas)));
}
}
index.html.twig
{% extends 'admin/layout.html.twig' %}
{% block body_id 'admin_post_show' %}
{% block main %}
<h1>{{ 'label.project_list'|trans }}</h1>
<table id="tarifas_index" class="table table-striped">
<thead>
<tr>
<th>{{ 'Id' }}</th>
<th><i class="fa fa-user"></i> {{ 'label.title'|trans }}</th>
<th><i class="fa fa-calendar"></i> {{ 'label.summary'|trans }}</th>
<th><i class="fa fa-calendar"></i> {{ 'label.content'|trans }}</th>
<th><i class="fa fa-cogs"></i> {{ 'label.actions'|trans }}</th>
</tr>
</thead>
<tbody>
{% for tarifa in tarifas %}
<tr>
<td>{{ tarifa.id }}</td>
<td>{{ tarifa.codigo }}</td>
<td>{{ tarifa.nombre }}</td>
<td>{{ tarifa.razon }}</td>
<td>
<div class="item-actions">
<a href="{{ path('project_detail', { id: tarifa.id }) }}" class="btn btn-sm btn-default">
{{ 'action.show'|trans }}
</a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<script>
$(document).ready( function () {
$('#tarifas_index').DataTable({
data: tarifas
});
} );
</script>
{% endblock %}
How can I pass a json from the controller to use it in the DataTable (in twig template) but mantaining the render in this controller. Please, can you help me?
You can render like this,
return $this->render('admin/tarifas/index.html.twig', array(
'tarifas' => $tarifas
'json_tarifas' => json_encode($tarifas)
));
and retrieve like this in twig,
<script type="text/javascript">
$(document).ready( function () {
$('#tarifas_index').DataTable({
data: $.parseJSON('{{ json_tarifas | raw }}')
});
} );
</script>
I don't understand what you are trying to achieve but you can simply send json encoded and normal data to your twig, to use it how you want
return $this->render('admin/tarifas/index.html.twig', array(
'tarifas' => $tarifas
'json_tarifas' => json_encode($tarifas)
));
I'm building a Symfony application and when I work on it, it is too slow. I have wondering what can cause this so I went in the profiler timeline to see what is going on but I was amazed that all those classes have very big data 10 MB, 22 MB and so on. See the picture:
This is my Object bundle. The yellow is my own class with my twigs. I do not understand what is this delay and what is this big data.... Can someone explain to me what is going on and how can be optimized this because on a production if it is like now it is too slow... Total time 3962 ms
Here is the controller - nothing fancy generate from the console with minor changes:
<?php
namespace George\ObjectsBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use George\ObjectsBundle\Entity\Object;
use George\ObjectsBundle\Form\ObjectType;
/**
* Object controller.
*
* #Route("/admin/object")
*/
class ObjectController extends Controller
{
/**
* Lists all Object entities.
*
* #Route("/", name="object")
* #Method("GET")
* #Template()
*/
public function indexAction(Request $request)
{
$session = $request->getSession();
$locale = $request->getLocale();
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('ObjectsBundle:Object')->findAll();
// echo $locale;
/*
$category = new Object();
$category->translate('bg')->setTitle('Chaussures');
$category->translate('en')->setTitle('Shoes');
$category->translate('bg')->setDescription('Chaussures');
$category->translate('en')->setDescription('Shoes');
$category->translate('bg')->setAddress('Chaussures');
$category->translate('en')->setAddress('Shoes');
$category->setMode('a');
$category->setLat('12');
$category->setLongt('12');
echo $category->translate('bg')->getTitle();
$category->mergeNewTranslations(); $em->persist($category);
$em->flush();
*/
return array(
'entities' => $entities,
);
}
/**
* Creates a new Object entity.
*
* #Route("/", name="object_create")
* #Method("POST")
* #Template("ObjectsBundle:Object:new.html.twig")
*/
public function createAction(Request $request)
{
$entity = new Object();
$form = $this->createCreateForm($entity);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('object'));
}
return array(
'entity' => $entity,
'form' => $form->createView(),
);
}
/**
* Creates a form to create a Object entity.
*
* #param Object $entity The entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createCreateForm(Object $entity)
{
$form = $this->createForm(new ObjectType(), $entity, array(
'action' => $this->generateUrl('object_create'),
'method' => 'POST',
));
$form->add('submit', 'submit', array('label' => 'Create'));
return $form;
}
/**
* Displays a form to create a new Object entity.
*
* #Route("/new", name="object_new")
* #Method("GET")
* #Template()
*/
public function newAction()
{
$entity = new Object();
$form = $this->createCreateForm($entity);
return array(
'entity' => $entity,
'form' => $form->createView(),
);
}
/**
* Finds and displays a Object entity.
*
* #Route("/{id}", name="object_show")
* #Method("GET")
* #Template()
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ObjectsBundle:Object')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Object entity.');
}
$deleteForm = $this->createDeleteForm($id);
return array(
'entity' => $entity,
'delete_form' => $deleteForm->createView(),
);
}
/**
* Displays a form to edit an existing Object entity.
*
* #Route("/{id}/edit", name="object_edit")
* #Method("GET")
* #Template()
*/
public function editAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ObjectsBundle:Object')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Object entity.');
}
$editForm = $this->createEditForm($entity);
$deleteForm = $this->createDeleteForm($id);
return array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
);
}
/**
* Creates a form to edit a Object entity.
*
* #param Object $entity The entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createEditForm(Object $entity)
{
$form = $this->createForm(new ObjectType(), $entity, array(
'action' => $this->generateUrl('object_update', array('id' => $entity->getId())),
'method' => 'PUT',
));
$form->add('submit', 'submit', array('label' => 'Update'));
return $form;
}
/**
* Edits an existing Object entity.
*
* #Route("/{id}", name="object_update")
* #Method("PUT")
* #Template("ObjectsBundle:Object:edit.html.twig")
*/
public function updateAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ObjectsBundle:Object')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Object entity.');
}
$deleteForm = $this->createDeleteForm($id);
$editForm = $this->createEditForm($entity);
$editForm->handleRequest($request);
if ($editForm->isValid()) {
$em->flush();
return $this->redirect($this->generateUrl('object_edit', array('id' => $id)));
}
return array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
);
}
/**
* Deletes a Object entity.
*
* #Route("/{id}", name="object_delete")
* #Method("DELETE")
*/
public function deleteAction(Request $request, $id)
{
$form = $this->createDeleteForm($id);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ObjectsBundle:Object')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Object entity.');
}
$em->remove($entity);
$em->flush();
}
return $this->redirect($this->generateUrl('object'));
}
/**
* Creates a form to delete a Object entity by id.
*
* #param mixed $id The entity id
*
* #return \Symfony\Component\Form\Form The form
*/
private function createDeleteForm($id)
{
return $this->createFormBuilder()
->setAction($this->generateUrl('object_delete', array('id' => $id)))
->setMethod('DELETE')
->add('submit', 'submit', array('label' => 'Delete'))
->getForm();
}
}
The main twig for the admin:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
{% block title -%}<title>Admin</title>{% endblock %}
{% block stylesheets %}
{% stylesheets
'#CoreBundle/Resources/public/css/*' %}
<link href="{{ asset(asset_url) }}" rel="stylesheet">
{% endstylesheets %}
{% endblock %}
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
</head>
<body>
{% block menu -%} {% endblock %}
{% block body -%} {% endblock %}
{% block javascripts -%}
{% javascripts
'#CoreBundle/Resources/public/js/jquery-1.11.3.min.js'
'#CoreBundle/Resources/public/js/bootstrap.min.js'
'#CoreBundle/Resources/public/js/fine-uploader.min.js'
'#CoreBundle/Resources/public/js/jquery-ui.min.js'
'#CoreBundle/Resources/public/js/datatables.min.js'
'#CoreBundle/Resources/public/js/Buttons-1.1.0/js/dataTables.buttons.min.js'
'#CoreBundle/Resources/public/js/Buttons-1.1.0/js/buttons.html5.js'
'#CoreBundle/Resources/public/js/Buttons-1.1.0/js/buttons.bootstrap.min.js'
'#CoreBundle/Resources/public/js/JSZip-2.5.0/jszip.min.js'
'#CoreBundle/Resources/public/js/RowReorder-1.1.0/js/dataTables.rowReorder.min.js'
%}
<script src="{{ asset(asset_url) }}" type="text/javascript"></script>
{% endjavascripts %}
{% endblock %}
{% block readyjs -%}
{{ tinymce_init() }}
<script type="text/javascript" >
function post_order ( ord, url)
{
$.ajax({
method: "POST",
url: url,
data: { elem: ord }
})
.done(function( msg ) {
// alert( msg );
});
}
$(document).ready(function () {
var optionsDatatables = {
dom: 'Bfrtip',
buttons: [
'copyHtml5', 'excelHtml5', 'csvHtml5'
]
}
if($('#dattab').hasClass('allow-order'))
{
//if we want more properties
// optionsDatatables.rowReorder = {
//selector: 'tr',
// update: true,
// dataSrc: '.ord-id'
// }
optionsDatatables.rowReorder = true;
}
var table = $('#dattab').DataTable(optionsDatatables);
var order;
if($('#dattab').hasClass('allow-order')) {
$('#dattab').on('draw.dt', function () {
var rows = table.rows().data();
var ord = new Array();
for (var i = 0, ien = rows.length; i < ien; i++) {
ord[i] = rows[i].DT_RowId;
}
order = ord;
$('#save_sort').fadeIn();
});
}
$('#save_sort').click(function(){
console.log(order);
post_order(order,$('#dattab').data('url'));
$(this).fadeOut();
});
});
</script>
{% endblock %}
</body>
</html>
The index which extends the base
{% extends "CoreBundle::admin_inner.html.twig" %}
{% block body -%}
<div class="container">
<div class="row">
<div class="col-xs-12">
{#{{ app.request.locale }}#}
<h1>Object list</h1>
{% for locale in ['en', 'bg'] %}
<li>
<a href="{{ path(app.request.get('_route'), app.request.get('_route_params')| merge({'_locale' : locale})) }}">
{{ locale }}
</a>
</li>
{% endfor %}
{{ app.session.get('_locale') }}{#
{{ app.request.locale }}#}
<div class="table-responsive">
<table class="table table-hover table-bordered" id="dattab">
<thead>
<tr>
<th>Id</th>
<th>Title</th>
<th>Description</th>
<th>Mode</th>
<th>Lat</th>
<th>Longt</th>
<th>Address</th>
<th>Created</th>
<th>Updated</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for entity in entities %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ entity.translate(app.session.get('_locale')).title }} </td>
<td>{{ entity.translate(app.session.get('_locale')).description }} </td>
<td>{{ entity.mode }}</td>
<td>{{ entity.lat }}</td>
<td>{{ entity.longt }}</td>
<td>{{ entity.translate(app.session.get('_locale')).address }}</td>
<td>{% if entity.created %}{{ entity.created|date('Y-m-d H:i:s') }}{% endif %}</td>
<td>{% if entity.updated %}{{ entity.updated|date('Y-m-d H:i:s') }}{% endif %}</td>
<td>
<a href="{{ path('object_edit', { 'id': entity.id }) }}"
class="btn btn-primary"> <span class="glyphicon glyphicon-edit"
aria-hidden="true"></span> Edit</a>
<a href="{{ path('admin_floor', { 'id': entity.id }) }}"
class="btn btn-info"> <span class="glyphicon glyphicon-edit"
aria-hidden="true"></span> Floors</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<ul>
<li>
<a href="{{ path('object_new') }}">
Create a new entry
</a>
</li>
</ul>
</div>
</div>
</div>
{% endblock %}
And the inner with the menu:
{% extends "CoreBundle::admin_base.html.twig" %}
{% block menu %}
{{ include('CoreBundle::menu.html.twig') }}
{% endblock %}
I would first check whether all your frontend resources are loading correctly (scripts, images, css).
This can considerably slow down you app.
You can check it in firebug or developer console.
I have a basic but functional search mechanism in my Symfony2 project.This will query and display back to the user the data using Doctrine2 LIKE expression.But I want to make more 'dynamic' and more 'user-friendly' by adding Ajax functionality.I added some Ajax code in my controller, but I don't know how to make it work.The image loader is just 'spinning' without displaying the results.
//controller
public function searcAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$query = $this->getRequest()->get('query');
if(!$query) {
if(!$request->isXmlHttpRequest()) {
return $this->redirect($this->generateUrl('voters_list'));
} else {
return new Response('No results.');
}
}
$city = $em->getRepository('DuterteBundle:City')->findCity($query);
if($request->isXmlHttpRequest()) {
if('*' == $query || !$city || $query == '') {
return new Response('No results.');
}
//display a another page
return $this->render('DuterteBundle:City:list1.html.twig', array('city' => $city));
}
return $this->render('DuterteBundle:City:search.html.twig', array('city' => $city));
}
// routing
search:
path: /search
defaults: { _controller:DuterteBundle:City:Searc }
requirements:
//search.html.twig
{% extends '::base.html.twig' %}
{% block body %}
<div id="city">
{% include 'DuterteBundle:City:list1.html.twig' with {'city': city} %}
</div>
{% endblock %}
//list1.html.twig
{% block body %}
<div class="page-header">
<h4>City/Municipality/Town and Its Corresponding Numbers of Voters</h4>
</div>
<table class="table table-hover table-bordered table-condensed">
<thead>
<tr>
<th>City</th>
<th>Votes</th>
<th>Percent</th>
</tr>
</thead>
<tbody>
{% for city in city %}
<tr>
<td>{{ city }}</td>
<td>{{ number_votes_city(city.id) }}</td>
<td></td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
My search form is embedded in navbar in the main layout.
<div class="col-sm-3 col-md-3" id="search">
<form class="navbar-form" role="search" action ="{{ path('search')}}" method ="post">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search city/town" name="query" value="{{ app.request.get('query') }}" id="search_keywords">
<div class="input-group-btn">
<button class="btn btn-default" type="submit"><i class="fa fa-search"></i></button>
<img id="loader" src="{{ asset('bundles/duterte/images/loader.gif') }}" style="vertical-align: middle; display: none" />
</div>
</div>
</form>
//repository
public function findCity($city)
{
return $this
->createQueryBuilder('c')
->select('c')
->where('c.name LIKE :name_city')
->setParameter('name_city', '%'.$city.'%')
->orderBy('c.name', 'ASC')
->getQuery()
->getResult()
;
}
and finally the js file
$(document).ready(function()
{
$('.search input[type="submit"]').hide();
$('#search_keywords').keyup(function(key)
{
if(this.value.length >= 3 || this.value == '') {
$('#loader').show();
$('#city').load(
$(this).parent('form').attr('action'),
{ query: this.value ? this.value + '*' : this.value },
function() {
$('#loader').hide();
}
);
}
});
});
Any help is appreciated
The same functionality, but a different approach. Listen to the keyup event on the search box
and then make ajax calls to a controller that returns the list of matched results as json. Check the response and
based on the status of the response, hide the existing listing and replace its contents with the markup returned in the
json response for the AJAX call.
Here, the example is for search in user listing.
Table markup on the twig file
<div id="user-list-div">
<table class="records_list" id="user-list">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Username</th>
<th>Password</th>
<th>Salt</th>
<th>Email</th>
<th>Isactive</th>
<th>Createdat</th>
<th>Updatedat</th>
<th>Isbillableuser</th>
<th>Isdeleted</th>
<th>Actions</th>
</tr>
</thead>
<tbody id = "user-table">
{% for entity in entities %}
<tr>
<td>{{ entity.id }}</td>
<td>{{ entity.name }}</td>
<td>{{ entity.username }}</td>
<td>{{ entity.password }}</td>
<td>{{ entity.salt }}</td>
<td>{{ entity.email }}</td>
<td>{{ entity.isActive }}</td>
<td>{% if entity.createdAt %}{{ entity.createdAt|date('Y-m-d H:i:s') }}{% endif %}</td>
<td>{% if entity.updatedAt %}{{ entity.updatedAt|date('Y-m-d H:i:s') }}{% endif %}</td>
<td>{{ entity.isBillableUser }}</td>
<td>{{ entity.isDeleted }}</td>
<td>
<ul>
<li>
show
</li>
<li>
edit
</li>
</ul>
</td>
</tr>
{% endfor %}
</tbody>
Search form markup
<div class="col-lg-6">
<div class="input-group">
<input type="text" class="form-control" id="search-field">
<span class="input-group-btn">
<button class="btn btn-default" type="button">Go!</button>
</span>
</div>
</div>
javascript part
<script>
$(function(){
console.log('desperate for');
var searchField = $('#search-field');
var userTable = $('#user-table');
var userListDiv = $('#user-list-div');
searchField.keyup(function(evt){
console.log($(this).val());
$.ajax({
url: '{{ path('admin_user_search') }}',
method: "POST",
data: "id=" + $(this).val() ,
dataType: 'html',
success: function(result, request) {
var parsedData =JSON.parse(result);
console.log(parsedData);
if(parsedData.status ==='success'){
console.log('hete');
userListDiv.empty();
userListDiv.html(parsedData.data);
}else{
//handle no result case
}
}
});
});
});
</script>
ajax_template.html.twig file
The same table markup as given above
controller action
public function searchuserAction(){
$em = $this->getDoctrine()->getManager();
$request = $this->get('request');
$searchParameter = $request->request->get('id');
//call repository function
$entities = $em->getRepository('LBCoreBundle:User')->findUsersForname($searchParameter);
$status = 'error';
$html = '';
if($entities){
$data = $this->render('LBCoreBundle:User:ajax_template.html.twig', array(
'entities' => $entities,
));
$status = 'success';
$html = $data->getContent();
}
$jsonArray = array(
'status' => $status,
'data' => $html,
);
$response = new Response(json_encode($jsonArray));
$response->headers->set('Content-Type', 'application/json; charset=utf-8');
return $response;
}
Respository function
public function findUsersForname($name){
$em = $this->getEntityManager();
$query = $em->createQuery("SELECT e FROM LBCoreBundle:User e
WHERE e.username LIKE '%$name%'");
$entities = $query->getResult();
return $entities;
}