0

I'm trying to get data of events out of my database using jQuery and AJAX.
My database table:

TABLE `events` (
    `event_id` INT(11) unsigned NOT NULL AUTO_INCREMENT,
    `event_title` VARCHAR(255) NOT NULL,
    `event_desc` TEXT,
    `event_location` VARCHAR(255) NOT NULL,
    `event_requirements` TEXT DEFAULT NULL,
    `event_date` DATETIME NOT NULL,
 PRIMARY KEY (`event_id`)

My code (in a MVC architecture):
Controller:

function index()
    {
        $overview_model = $this->loadModel('Events');
        $this->view->events = $overview_model->getEventTypes();
        $this->view->render('events/index');
    }

Model:

public function getEventTypes()
{
    $sth = $this->db->prepare("SELECT * FROM events");
    $sth->execute();

    $events = array();

    foreach ($sth->fetchAll() as $event) {
        $events[$event->event_id] = new stdClass();
        $events[$event->event_id]->event_title = $event->event_title;
        $events[$event->event_id]->event_desc = $event->event_desc;
        $events[$event->event_id]->event_location = $event->event_location;
        $events[$event->event_id]->event_requirements = $event->event_requirements;
        $events[$event->event_id]->event_date = $event->event_date;
    }

    return $events;
}

View:

  <!-- start event type selection --> 
  <div class="event-selection">
    <label>Choose an event:</label>
    <select id="select-event-type">
        <?php foreach ($this->events as $event) {
            echo "<option value='" .$event->event_title. "'>" .$event->event_title."</option>";
        }?>
    </select>

    <!-- I NEED HELP WITH THIS PART -->
    <script>
        $(document).ready(function() {
            $('#select-event-type').change(function() {

                $.ajax({
                    type:'post',
                    url:'',
                    data:'',
                        success: function(data) 
                        {
                            $('#event-details').html(data);
                        }
                });
            });
        });
    </script>   

    <!-- Start event-details -> here the data is supposed to be displayed -->
    <div id="event-details"></div> <!-- /#event-details -->

  </div><!-- /.event-selection -->

My problem: I'm not sure what URL and data are in my case and I am unsure, if I have to use JSON or not. I am not getting any error messages. Everytime I change my selection in the drop down it loads the whole page into the #event-details div and not the desired database data.

I'm really new to this and I have never worked with AJAX before. Thank you so much for any kind of help.

UPDATE:
In the console all the event's data is shown now in json format (Thank you so so much for that!). But there is still nothing outputted and when I change the event in the selection the data in the console does not update!

Schwesi
  • 4,753
  • 8
  • 37
  • 62
  • Are you using the browser's debugging tools to observe where your code is breaking down? It's usually summoned via F12. – JoshNaro Nov 04 '14 at 15:38
  • Good point! Everytime I change my selection in the drop down it loads the whole page into the #event-details div. – Schwesi Nov 04 '14 at 15:41
  • You're hitting the current page with a post request. I'm guessing you don't actually have an api endpoint set up, so it's simply returning the view for the current page. You need to set up a route that expects a request (get, post, etc) and returns the data you need. – Shawn Erquhart Nov 04 '14 at 15:54
  • How would I set up an api endpoint? – Schwesi Nov 04 '14 at 15:56

2 Answers2

1

You're already passing details about all of the events to the template when you render it, so the AJAX call would be redundant and a waste of a request. Try something like this:

Controller

function index()
{
    $overview_model = $this->loadModel('Events');
    $this->view->events = $overview_model->getEventTypes();
    $this->view->render('events/index');
}

Model

public function getEventTypes()
{
    $sth = $this->db->prepare("SELECT * FROM events");
    $sth->execute();

    $events = array();

    foreach ($sth->fetchAll() as $event) {
        $events[$event->event_id] = new stdClass();
        $events[$event->event_id]->event_id = $event->event_id;
        $events[$event->event_id]->event_title = $event->event_title;
        $events[$event->event_id]->event_desc = $event->event_desc;
        $events[$event->event_id]->event_location = $event->event_location;
        $events[$event->event_id]->event_requirements = $event->event_requirements;
        $events[$event->event_id]->event_date = $event->event_date;
    }

    return $events;
}

View

<!-- start event type selection --> 
<div class="event-selection">
    <label>Choose an event:</label>
    <select id="select-event-type">
        <?php foreach ($this->events as $event) {
            // Using the event's ID as a value makes it easier for us to look up the selected event.
            echo "<option value='" .$event->event_id. "'>" .$event->event_title."</option>";
        }?>
    </select>

    <script>
        (function ($) {
            // Here we set the JavaScript variable 'events' to a JSON-encoded copy of the array we passed to the template, or null (if there are no events).
            var events = <?php echo (count($this.events) > 0) ? "JSON.parse(" .json_encode($this->events). ")" : "null"; ?>
            $(document).ready(function() {
                $('#select-event-type').change(function() {
                    if (events) {
                        // Now we can get the event details from the selected value.
                        var event = events[this.value];
                        $('#event-details').html(event.title);
                    }
                });
            });
        })($);
    </script>   

    <!-- Start event-details -->
    <div id="event-details"></div> <!-- /#event-details -->

  </div><!-- /.event-selection -->

I haven't tested it so I'm not sure if it works as is, but the basic idea is to pass the PHP array to the page as JSON, so your JavaScript can use the same data.

soulprovidr
  • 754
  • 3
  • 14
  • Thank you so much for your answer! I get a syntax error: Unexpected T_ECHO in this line: var events = 0 ? echo "JSON.parse(" .$this->events. ")" : echo "null"); ?> – Schwesi Nov 04 '14 at 16:02
  • 1
    @kringeltorte: I think I messed up PHP's ternary operator syntax. You can break it down into more than one line - all I was attempting to do is echo the events array if the length of the array is greater than 0. I'll try to fix it and edit my answer. – soulprovidr Nov 04 '14 at 16:05
  • @kringeltorte: I also just realized I was polluting the global scope with the naming of my JavaScript variables (event, events), so I wrapped the script in a [self-invoking function](http://esbueno.noahstokes.com/post/77292606977/self-executing-anonymous-functions-or-how-to-write). – soulprovidr Nov 04 '14 at 16:11
  • I am sure you meant to write 'controller' for the first code snippet, not 'model'. If so, then the code is still not working. The site breaks down after the select drop down (the footer, which is included later on does not show up) and nothing is happening. In the console nothing happens on changing the selection. I am not sure why, but thank you so so much for pointing me into the right direction!! – Schwesi Nov 04 '14 at 16:20
  • 1
    @kringeltorte: No problem. It's too bad I'm not at home - I'd be able to test the code rather than write it here and hope that it works! :) – soulprovidr Nov 04 '14 at 16:23
  • Well, thank you for your help! I will let you know, if I found a solution! – Schwesi Nov 04 '14 at 16:25
  • I still did not get it to work. But I found an error! The model does not seem to work anymore. **The error**:`Notice: Undefined property: stdClass::$event_id in /views/events/index.php` – Schwesi Nov 04 '14 at 17:49
  • 1
    I forgot to add: in your `getEventTypes()` function you need to add an `event_id` attribute to each event. `$events[$event->event_id]->event_id = $event->event_id;` – soulprovidr Nov 04 '14 at 18:38
  • Thank you so much! Now I get this error: `Failed to load resource: net::ERR_CACHE_MISS /events/index` – Schwesi Nov 04 '14 at 19:28
  • 1
    That seems to be a (harmless) Chrome error - see here: http://stackoverflow.com/questions/26408931/bizarre-error-in-chrome-developer-console-failed-to-load-resource-neterr-ca – soulprovidr Nov 04 '14 at 19:31
  • Great! Thank you!! It still does not work but there are no errors now. Thank you so so much for your help!! You definitely gave me a direction!! – Schwesi Nov 04 '14 at 19:52
  • Would you mind, if I would repost the question with your code? Probably a fresh pair of eyes would find a way to make it work. – Schwesi Nov 05 '14 at 18:40
  • @kringeltorte: Sure - that's totally fine by me. – soulprovidr Nov 05 '14 at 19:00
  • I found an error in the view!! `(function ($) { var events = Notice: Use of undefined constant events - assumed 'events' in /views/events/index.php` and `Catchable fatal error: Object of class View could not be converted to string in /views/events/index.php` – Schwesi Nov 05 '14 at 19:57
  • I spotted the error! I needed to change this `(count($this.events) > 0)` to this `(count($this->events) > 0)`. Now the functionality works (in the console) but the values are not displayed! – Schwesi Nov 05 '14 at 20:18
  • I updated the question! Thank you so so much for all of your time and effort! It helped me out tremendously! – Schwesi Nov 05 '14 at 20:35
  • 1
    Ah, I mixed up PHP/JS syntax (-_-). Take a look at the documentation for jQuery's `change` - there's an error in my code when getting the selected value of the ` – soulprovidr Nov 05 '14 at 20:44
1

As the URL you can try something like :

"/controller/action" e.g. "events/index" (the URL you would request by a normel page-request)

You should now get the hole HTML from your view in your data in the success-function and can load this in your div.

If you want to specify which events should be loaded you can post some date and evaluate this in your controller-function.

It could look like this (the second parameter of $.post is not needed):

$.post('/events/index', {data: {event_id : id}}).done(function(data){
   $('#event-details').html(data);
});

the data send to the controller as an array which looks like:

array(
   data => array(
     event_id => id
  )
)

I hope this will help you

empiric
  • 7,825
  • 7
  • 37
  • 48
  • Thank you for your help! I am not getting anything now, when I change the selection. I am not sure what the `{data: {event_id : id}}` part of your answer means? Do I have to put the data, I would like to be displayed here? So for example: `{data: {event_title : title}})` ? – Schwesi Nov 04 '14 at 16:09
  • 1
    Don't forget to wrap ypur change-event around my ajax-call. the data object is for data you want to send to your controller through the ajax-call, e.g an ID for a event you want to display. The displayed data has either defined in your view or if your view returns a json-object in the success-function for your ajax-call. – empiric Nov 04 '14 at 16:14
  • I am still not getting any output. When I change the selection, nothing happens on the page. Thank you so much for your effort. This is helping me a lot! – Schwesi Nov 04 '14 at 16:24
  • I am getting this error: `Uncaught ReferenceError: id is not defined` – Schwesi Nov 04 '14 at 16:27
  • If I change the data to, for example: `{data: {event_title : title}})` I get the same error: `Uncaught ReferenceError: title is not defined index:82(anonymous function) index:82x.event.dispatch jquery-2.0.3.min.js:5y.handle jquery-2.0.3.min.js:5` – Schwesi Nov 04 '14 at 16:29
  • 1
    so "title" here, has to be a variable in your javascript. If you dont want to send any data to your controller via ajax just leave the second paramater empty ($.post('/your/url').done()). – empiric Nov 05 '14 at 09:44