lukmicsch
lukmicsch

Reputation: 53

jquery autocomplete returns json error

I'm calling a keyup function to get a json array from the server to autocomplete my searchinput. This works fine when I'm doing it the first time. However, when I use the autocomplete, load the same view with the new data and try to do the same procedure again, I'm getting an error. I already tried to fix it with an $(document).ajaxSuccess(function(){}); additional to my .ready function but that doesn't work. Someone pointed out to me that I can't use an eventhandler inside another eventhandler, but as I said it works fine the first time. I read about the error and found out that it means im parsing json twice. But if that was true than it wouldn't work the first time as well right? Hope someone can help.

jquery:

/**
 * for searching the uni
 */
$("#keyworduni").keyup(function(){
    var keyword = $("#keyworduni").val();
    $.get( "searchuni", { search: keyword })
        .done(function( data ) {

            $('#resultsuni').show();

            $('#resultsuni').html('');

            var results = jQuery.parseJSON(data);

            $(results).each(function(key, value) {
                $('#resultsuni').append('<div class="itemuni">' + value + '</div>');
            });
            console.log(data);

            $('.itemuni').click(function() {
                var text = $(this).html();
                $('#keyworduni').val(text);
            });

            if($('#keyworduni').val() == ''){
                $('#resultsuni').hide();
            }

        });
}); 

calling this route:

Route::get('/searchuni', [
'uses' => 'UniController@searchUni',
'as' => 'user.searchuni'

]);

within my UniController:

/**
 * get the data from db from keyword for uni
 */
public function searchUni(Request $request){

    if($request->ajax()) {

        $keyword = $request->search;

        //query user model
        $unis = DB::table('unis')->where([
            ['name', 'LIKE', '%' .$keyword. '%'],
        ])->limit(3)->get();

        $json = array();

        foreach ($unis as $uni) {
            array_push($json, $uni->name);
        }

        return json_encode($json);

    }

}

the error:

Uncaught SyntaxError: Unexpected token o in JSON at position 1
at JSON.parse (<anonymous>)
at Function.n.parseJSON (jquery-1.12.4.min.js:4)
at Object.<anonymous> (feed.js:177)
at i (jquery-1.12.4.min.js:2)
at Object.fireWith [as resolveWith] (jquery-1.12.4.min.js:2)
at y (jquery-1.12.4.min.js:4)
at XMLHttpRequest.c (jquery-1.12.4.min.js:4)

json sample:

["TU - Berlin"]

EDIT:

I discovered that its not about using the function a second time, but that it has to have something to do with the way I'am "reloading" the view with the new data and then trying to use the function again. So here is what the HTML looks like and the way I'm calling the route to get the view again, plus logic on how I get the new data.

HTML:

<form action="{{ route('shop.changeto', ['kind' => 'uni']) }}" method="get">
                            <li class="dick" style="margin-bottom: 20px;"><input type="text" class="search" id="keyworduni" name="searchuni" value="" placeholder="Search" autocomplete="off">
                                <input type="submit" value="Search" id="Batton1"></li>
                            <li class="dick">
                                <div id="resultsuni">
                                    <div class="itemuni">abc</div>
                                    <div class="itemuni">def</div>
                                    <div class="itemuni">hij</div>
                                </div>
                            </li>
                            {{ csrf_field() }}
                        </form>

the called route:

Route::get('/changeto/{kind}', [
'uses' => 'ProductController@changeTo',
'as' => 'shop.changeto'

]);

the called function:

public function changeTo(Request $request, $kind){

    if($kind == 'uni'){
        $route = "shop.feeduni";
        $argument = "'". "uni" . "'";
        $argumentequals = $request->input('searchuni');
    } else if($kind == 'school'){
        $route = "shop.feedschool";
        $argument = "'". "school" . "'";
        $argumentequals = $request->input('searchschool');
    }

    return redirect()->route($route, [$argument => $argumentequals]);

}

the next route (when I'am searching for the uni):

Route::get('/feeduni/{uni}', [
'uses' => 'ProductController@getFeedUni',
'as' => 'shop.feeduni'

]);

and the called function:

public function getFeedUni(Request $request, $uni){

    if($uni == ' '){
        $uni = $request->input('searchuni');
    }

    $posts = DB::table('products')->where([
        ['sold', '=', 'n'],
        ['uni', '=', $uni],
    ])->latest()->paginate(2);

    //returns the index page from shop folder and attach Product Data
    // the string products can then be used as $products in shop.index -> have all the products

    if($request->ajax()){

        return [
            'posts' => view('shop.feedajax')->with(compact('posts'))->render(), //gibt uns feedajax mit neuen posts
            'next_page' => $posts->nextPageUrl() //setzt den wert für html nextpage element
        ];
    }

    /**
     * now returning the view and the posts
     */
    return view('shop.feed')->with(compact('posts'));
}

Now I'm on the same view as before and I'm trying to use the jquery-function again with the error as outcome.
Maybe someone can find my mistake(s).

Upvotes: 1

Views: 944

Answers (1)

Rory McCrossan
Rory McCrossan

Reputation: 337580

The issue is because data has already been deserialised for you. Attempting to deserialize an object again causes the error you're seeing. Simply remove the $.parseJSON() call from your code. Also note that data will be an object, so yu'll need to use $.each to iterate over it, not $().each(). Try this:

$.get("searchuni", { search: keyword }).done(function(data) {
    $('#resultsuni').html('').show();

    $.each(data, function(key, value) {
        $('#resultsuni').append('<div class="itemuni">' + value + '</div>');
    });

    // I'd also suggest making this a single delegated event handler
    $('.itemuni').click(function() {
        var text = $(this).html();
        $('#keyworduni').val(text);
    });

    if ($('#keyworduni').val() == ''){
        $('#resultsuni').hide();
    }
});

Upvotes: 1

Related Questions