0

I want to create an AJAX search with Laravel. I'm stuck at the part of displaying the results (posts) returned by the controller. So far I have this:

Search form (home.blade.php)

//The search form
{{ Form::open(array('id' => 'search', 'url' => ' ')) }}
    {{ Form::text('query', Input::old('query'), array('placeholder' => 'Search for posts..')) }}
    {{ Form::hidden('sort_col', Input::old('sort_col')) }}
    {{ Form::hidden('sort_dir', Input::old('sort_dir')) }}
    {{ Form::button('<i class="fa fa-search"></i>', array('type' => 'submit', 'name' => 'submit', 'title' => 'Zoeken')) }}
{{ Form::close() }}

Displaying the posts (home.blade.php)

<!-- Posts !-->
<div id="posts">
@if (!$posts->count())
    <div class="content">No posts found!</div>
@else
    @foreach ($posts as $post)
        <div class="list-item clearfix">
            <div class="content">
                <img src="{{ URL::to($post->thumbnail) }}" alt="" />
                <h1>{{{ $post->title }}}</h1>
                <div class="tags">
                @foreach ($post->tags as $tag)
                    <abbr title="{{{ $tag->description }}}">{{{ $tag->title }}}</abbr>
                @endforeach
                </div>
            </div>
            <div class="score">
                {{ $post->rating }}
            </div>
        </div>
    @endforeach
@endif
</div>
<!-- /Posts !-->

HomeController.php

public function postSearch()
{
    if (!Request::ajax()) {
        return null;
    }

    $input = array(
        'query'    => Input::get('query'),
        'sort_col' => Input::get('sort_col'),
        'sort_dir' => Input::get('sort_dir'),
    );

    $posts = new Post;
    $posts = $posts->select(...)->where(...)->orderBy(...); //Search query here

    Input::flash();

    return $posts;
}

The postSearch() method is being called when the search for is submitted.

The jQuery (home.blade.php)

$('#search').submit(function(e) {
    e.preventDefault();

    var form = $(this);

    $.post(form.attr('action'), form.serialize(), function(data) {
        $('#posts').html(data);
        console.log(data);
    });
});

Everything works fine and data is being returned. It looks like this when I log the data into the console:

returned data in the console

The objects within the red box are the posts. How do I display those posts in the #posts div? I've been strugling a while now but I just can't figure it out.

JasonK
  • 5,214
  • 9
  • 33
  • 61
  • Hey you are expecting HTML from your controller but your controller is returning back JSON data. So you need to either parse the JSON using jQuery or change your controller so it returns the generated html and you inject it into the DOM. – Imran Khan Nov 02 '14 at 22:11

1 Answers1

1

You will have to loop through the array of posts and create the necessary jquery elements.
This should give you the idea:

for(var i=0; i<data.length; i++){
    var post = data[i];
    var listItem = $('<div></div>').addClass('list-item clearfix');
    var content = $('<div></div>').addClass('content');
    var img = $('<img/>').attr('src', post.thumbnail);
    var h1 = $('<h1></h1>').text(post.title);
    // etc

    content.append(img).append(h1);
    listItem.append(content);
    $('#posts').append(listItem);
}

Update

For your image urls I you do something like this in your controller:

public function postSearch()
{
    // ... code omitted

    foreach($posts as $post){
        $post->thumbnail = URL::to($post->thumbnail);
    }

    return $posts;
}

This replaces the thumbnail property with a generated full url that you can use on the client.

lukasgeiter
  • 147,337
  • 26
  • 332
  • 270
  • Thanks, I managed to get it working with some adjustments. But there are two problems. 1: The pagination isnt working. 2: How can I produce this HTML with jQuery ``?. – JasonK Nov 02 '14 at 22:42
  • 1: since you append items with javascript, laravels server side pagination won't work anymore. I suggest you do the pagination with jquery as well (im sure there are plugins for that) – lukasgeiter Nov 02 '14 at 22:52
  • 2: You could generate the full url in your controller. By looping through all posts and storing the img url generated with URL::to – lukasgeiter Nov 02 '14 at 22:55
  • I will figure out the first problem myself, it isn't really related to this quesion. 2: But then I should produce all the HTML in the HomeController and return it to display. Isn't this bad practice? I also figured out that this works `var html = ''`, but I can't get a javascript variable to replace 'image'. – JasonK Nov 03 '14 at 13:45
  • 1
    No i wouldn't consider it bad practice. Client side rendering brings some advantages though. For example you could animate the adding of a list item more easily... I personally prefer communication using json. Regarding the "image problem" i'll update my answer later... – lukasgeiter Nov 03 '14 at 15:01
  • Ah I got it now, override the variables :) Thanks – JasonK Nov 03 '14 at 18:53
  • Yep, you could also store it in a new one and call it `thumbnailUrl`.. doesn't really matter ;) – lukasgeiter Nov 03 '14 at 18:54
  • I know I can be pretty irritating, but do you mind looking at my other (pagination) problem as well (http://stackoverflow.com/questions/26758059/ajax-pagination-with-laravel)? – JasonK Nov 05 '14 at 16:17