Nick Price
Nick Price

Reputation: 963

Symfony2 how to filter query

UPDATE

Think I may have gone off course here, but I still get the same result with the whole page being displayed in the table.

So I am doing this for both the view and status pages. View is the default page which shows all active alerts. Status is the page that will display the filtered alerts. So each of these pages has a controller

public function viewAction()
{
    $repository = $this
        ->getDoctrine()
        ->getManager()
        ->getRepository('NickAlertBundle:Alert');

    $alerts = $repository->getAllActiveAlerts();

    return $this->render('NickAlertBundle:Page:view.html.twig', array(
        'alerts' => $alerts,
    ));
}

public function getActivatedAction(Request $request)
{
    $alertStatus = $request->request->get('status', 'active');
    $alerts = $this->getDoctrine()->getRepository('NickAlertBundle:Alert')->getAlertByStatus($alertStatus);

    return $this->render('NickAlertBundle:Page:status.html.twig', array("alerts"=>$alerts));
}

Each of these pages then has a route

NickAlertBundle_view:
    pattern:  /view-alerts
    defaults: { _controller: NickAlertBundle:Alert:view }
    requirements:
       _method:  GET

NickAlertBundle_status:
    pattern:  /view-alerts
    defaults: { _controller: NickAlertBundle:Alert:getActivated }
    requirements:
       _method:  POST

NickAlertBundle_view calls the view action and renders the page with all active alerts. NickAlertBundle_status calls the getActivated action.

Both of these views are the same, their content is as follows

{% extends 'NickAlertBundle::layout.html.twig' %}

{% block main %}

    <div class="col-md-12">

<section class="panel panel-default">
    <header class="panel-heading">
        <h3 class="panel-title">View Alerts</h3>
        <select name="alerts" id="alerts" data-url="{{ path('NickAlertBundle_status') }}">
            <option value="active">Active</option>
            <option value="inactive">Inactive</option>
        </select>
    </header>
    <div class="panel-body">

        <div class="row" id="alert-container">
            <table width="100%" cellpadding="0" cellspacing="0" border="0" id="datatable" class="table">
                <thead>
                <tr>
                    <th>Id</th>
                    <th>Search Command</th>
                    <th>Flight Number</th>
                    <th>Booking Class</th>
                    <th>Alert Pseudo</th>
                    <th>Alert Status</th>
                </tr>
                </thead>
                <tbody>
                    {% for alert in alerts %}
                        <tr>
                            <td>{{ alert[0].id }}</td>
                            <td>{{ alert[0].searchCommand }}</td>
                            <td>{{ alert.flight_number }}</td>
                            <td>{{ alert.classes }}</td>
                            <td>{{ alert.pseudos }}</td>
                            <td>{{ alert[0].alertStatus }}</td>
                        </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
</section>
    </div>

{% endblock %}

So the data url should call the status route. Both of the views have this because they should always be able to change the select on either page.

And then the javascript is pretty much the same as you have shown me.

Upvotes: 1

Views: 460

Answers (3)

Matias Pierobon
Matias Pierobon

Reputation: 86

To solve the url problem you should put:

NickAlertBundle_view:
    pattern:  /view-alerts
    defaults: { _controller: NickAlertBundle:Alert:view }
    methods:  [GET]

NickAlertBundle_status:
    pattern:  /view-alerts
    defaults: { _controller: NickAlertBundle:Alert:getActivated }
    methods:  [POST]

Upvotes: 0

Matias Pierobon
Matias Pierobon

Reputation: 86

The $('#alert-container table tbody').html(data); line will set the contento of your tbody table from the response that the server return, so you have to have two different files

{% NickAlertBundle:Page:view.html.twig %}
{% extends 'NickAlertBundle::layout.html.twig' %}

{% block main %}

    <div class="col-md-12">

<section class="panel panel-default">
    <header class="panel-heading">
        <h3 class="panel-title">View Alerts</h3>
        <select name="alerts" id="alerts" data-url="{{ path('NickAlertBundle_status') }}">
            <option value="active">Active</option>
            <option value="inactive">Inactive</option>
        </select>
    </header>
    <div class="panel-body">

        <div class="row" id="alert-container">
            <table width="100%" cellpadding="0" cellspacing="0" border="0" id="datatable" class="table">
                <thead>
                <tr>
                    <th>Id</th>
                    <th>Search Command</th>
                    <th>Flight Number</th>
                    <th>Booking Class</th>
                    <th>Alert Pseudo</th>
                    <th>Alert Status</th>
                </tr>
                </thead>
                <tbody>
                    {% for alert in alerts %}
                        <tr>
                            <td>{{ alert[0].id }}</td>
                            <td>{{ alert[0].searchCommand }}</td>
                            <td>{{ alert.flight_number }}</td>
                            <td>{{ alert.classes }}</td>
                            <td>{{ alert.pseudos }}</td>
                            <td>{{ alert[0].alertStatus }}</td>
                        </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
</section>
    </div>

{% endblock %}

and

{# NickAlertBundle:Page:status.html.twig #}
{% for alert in alerts %}
    <tr>
        <td>{{ alert[0].id }}</td>
        <td>{{ alert[0].searchCommand }}</td>
        <td>{{ alert.flight_number }}</td>
        <td>{{ alert.classes }}</td>
        <td>{{ alert.pseudos }}</td>
        <td>{{ alert[0].alertStatus }}</td>
    </tr>
{% endfor %}

Upvotes: 1

Matias Pierobon
Matias Pierobon

Reputation: 86


UPDATED


The problem is basicaly that you are embedding the html response from viewAction when you actually have to put the code for the alerts, for example:

public function getActivatedAction(Request $request)
{
    $alertStatus = $request->request->get('status', 'active');
    $alerts = $this->getDoctrine()->getRepository('NickAlertBundle:Alert')->findAllByStatus($alertStatus);

    return $this->render('NickAlertBundle:Alerts:show.html.twig', array("alerts"=>$alerts));
}

on the NickAlertBundle:Alerts:show.html.twig

{# NickAlertBundle:Alerts:show.html.twig #}
{% for alert in alerts %}
    <tr>
        <td>{{ alert[0].id }}</td>
        <td>{{ alert[0].searchCommand }}</td>
        <td>{{ alert.flight_number }}</td>
        <td>{{ alert.classes }}</td>
        <td>{{ alert.pseudos }}</td>
        <td>{{ alert[0].alertStatus }}</td>
    </tr>
{% endfor %}

So then in your NickAlertBundle:Page:view.html.twig :

$('#alerts').change(function(){
    $.ajax({
        type: "POST",
        url: $('#alerts').attr('data-url'), # getActivatedAction route
        data:{ status: $(this).val() },
        success: function(data){
            $('#alert-container table tbody').html(data);
        }
    });
});


You can add a methond in your Enity Repository File:

# src/Package/AppBundle/Entity/AlertRepository.php
<?php

namespace Package\AppBundle\Entity;

use Doctrine\ORM\EntityRepository;

/**
 * AlertRepository
 *
 * This class was generated by the Doctrine ORM. Add your own custom
 * repository methods below.
 */
class AlertRepository extends EntityRepository
{
  public function findAllByStatus($status = "active")
  {
    $qb = $this->createQueryBuilder('a');
    $query = $qb
        ->where(
          $qb->expr()->eq('a.alertStatus', $status)
        )
        ->orderBy('a.id', 'DESC')
        ->getQuery();
    return $query->getResult();
  }

}

and then in your controller, you can pass a json with the data or html:

<?php
...
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
...

public function getActivatedAction(Request $request)
{
    $alertStatus = $request->request->get('status', 'active');
    $alerts = $this->getDoctrine()->getRepository('AppBundle:Alert')->findAllByStatus($alertStatus);

    // With JSON
    $json = alerts->toJson() // your own method

    $response = new JsonResponse();
    $response->setData($json);

    // With HTML
    return $this->render('AppBundle:Alerts:show.html.twig', array("alerts"=>$alerts));
}

Now in yor html file you can use ajax to request the alerts:

<select name="alerts" id="alerts">
  <option value="active">Actives</option>
  <option value="inactive">Inactive</option>
</select>
<div id="alertsList"></div>

<script>
  $('#alerts').change(function(){
    $.ajax({
      type: "POST",
      url: "{{ path('alerts_getActivated') }}",
      data:{ status: $(this).val() },
      success: function(data){
          $('#alertsList').html(data); //Using the html response. With json you have to create the style and html here
      }
    });
  });
</script>

If I didn't miss anything it should work.

If I get you wrong, please let me know, and I hope this will help you.

Upvotes: 2

Related Questions