We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

How can i call a controller action directly from a javascript function

Hi, i need call a controller action directly from javascript. I want connect charts of canvas.js and mysql ( https://canvasjs.com/forums/topic/how-can-i-use-php-mysql-dynamic-data/ ).

View:

<html><body><div id="chartContainer" style="width: 800px; height: 380px;"></div></body></html>

<script type="text/javascript">

 $(document).ready(function () {
     $.getJSON("data.php", function (result) {
         var chart = new CanvasJS.Chart("chartContainer", {
             data: [
                 {
                     dataPoints: result
                 }
             ]
         });

         chart.render();
     });
 });

</script>

Controller:

public function initialize()
{
    $this->tag->setTitle('Estadisticas');
    parent::initialize();
    $this->assets
        ->collection('footer')->addJs('js/jquery.canvasjs.min.js');
}

public function indexAction()
{
    $data_points = array();
    $consulta = "SELECT COUNT(RE.reservacion_id) AS cantidad,RE.reservacion_nombre
                    FROM encuesta AS ENCUESTA, reservacion AS RE WHERE ENCUESTA.reservacion_id=RE.reservacion_id group by RE.reservacion_id";
    $estadistica = $this->modelsManager->executeQuery($consulta);

    foreach($estadistica as $p)
    {

        $point = array("label" => $p->reservacion_nombre , "y" => $p->cantidad);

        array_push($data_points, $point);
    }
    echo json_encode($data_points, JSON_NUMERIC_CHECK);
}

how call to action rather File data.php

Like any other action, by it's registered URL in the Router ;]

If you haven't set up any routing, it would work like this:

ChartController::indexAction()

public function initialize()
{
    $this->tag->setTitle('Estadisticas');
    parent::initialize();
    $this->assets
        ->collection('footer')->addJs('js/jquery.canvasjs.min.js');
}

public function indexAction()
{
    $data_points = array();
    $consulta = "SELECT COUNT(RE.reservacion_id) AS cantidad,RE.reservacion_nombre
                    FROM encuesta AS ENCUESTA, reservacion AS RE WHERE ENCUESTA.reservacion_id=RE.reservacion_id group by RE.reservacion_id";
    $estadistica = $this->modelsManager->executeQuery($consulta);

    foreach($estadistica as $p)
    {

        $point = array("label" => $p->reservacion_nombre , "y" => $p->cantidad);

        array_push($data_points, $point);
    }
    echo json_encode($data_points, JSON_NUMERIC_CHECK);
    exit; // IMPORTANT!
}
$(document).ready(function () {
     $.getJSON("/chart/index", function (result) {
         var chart = new CanvasJS.Chart("chartContainer", {
             data: [
                 {
                     dataPoints: result
                 }
             ]
         });

         chart.render();
     });
 });
edited Sep '15

One things that Lajos Bencz might be missing depending on the rest of your setup is turning off the content response wrapping your json echo. IE if you are using any kind of templates you need to disable them and jsut send back the raw JSON. THat is down with the following inside of the controller action.

public function indexAction()
{
    $this->view->disable();
    [...]
    echo json_encode($response);
}

True, the nice example would look like this:

    public function afterExecuteRoute(Dispatcher $dispatcher)
    {
        if ($this->request->isAjax()) {
            $this->view->disable();
            $data = $this->view->getParamsToView();
            $json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
            $this->response
                ->setContentType('application/json', 'utf-8')
                ->setContent($json);
        }
        return $this->response->send();
    }

But that's why I added the exit; line to his example action :]

One things that Lajos Bencz might be missing depending on the rest of your setup is turning off the content response wrapping your json echo. IE if you are using any kind of templates you need to disable them and jsut send back the raw JSON. THat is down with the following inside of the controller action.

public function indexAction()
{
  $this->view->disable();
  [...]
  echo json_encode($response);
}

ah yes yours is much prettier. wasnt aware that isajax() was a request method. putting it into the dispatcher is also mich better.

also i missed your exit

True, the nice example would look like this:

  public function afterExecuteRoute(Dispatcher $dispatcher)
  {
      if ($this->request->isAjax()) {
          $this->view->disable();
          $data = $this->view->getParamsToView();
          $json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
          $this->response
              ->setContentType('application/json', 'utf-8')
              ->setContent($json);
      }
      return $this->response->send();
  }

But that's why I added the exit; line to his example action :]

One things that Lajos Bencz might be missing depending on the rest of your setup is turning off the content response wrapping your json echo. IE if you are using any kind of templates you need to disable them and jsut send back the raw JSON. THat is down with the following inside of the controller action.

public function indexAction()
{
 $this->view->disable();
 [...]
 echo json_encode($response);
}