4

I have problem to returning json data and sort them in laravel, they just appear randomly.

What I did so far

  1. I tried to return data by their id from database and help of JavaScript like:

    result.sort(function(a,b) { return (a.id > b.id) ? 1 : ((b.id > a.id) ? -1 : 0); }); Result was random order (sort)

  2. I added sort column to my database and tried to get my data base on numbers I provided there (result was random order)

  3. I tried to add ->orderByRaw('set_specification.sort') in my function code and get orders by that (result was random order)

Logic

  1. I select a set
  2. Set child's will appear on blade by sort column order which I provide numbers in it.

Code

controller

public function selectset($id){
      $selectsets = DB::table('sets')
        ->where('sets.id', '=', $id)
        ->join('set_specification', 'sets.id', '=', 'set_specification.set_id')
        ->join('specifications', 'set_specification.spec_id', '=', 'specifications.id')
        ->orderByRaw('set_specification.sort')
        ->get();
      return response()->json($selectsets);
    }

JavaScript

$(document).ready(function() {
    $('select[name="selectset"]').on('change', function() {
      var id = $(this).val();
      if(id) {
      $.ajax({
        url: '{{ url('admin/selectset') }}/'+encodeURI(id),
        type: "GET",
        dataType: "json",
        success:function(result) {


          result.sort(function(a,b) {
            return (a.id > b.id) ? 1 : ((b.id > a.id) ? -1 : 0);
          });

          console.log(result);

//rest of code..
}

Issues

Even when I return my data by help of ajax sort (as you see in my code) in console it returns correctly but in blade it appears as it wish!

screenone

in case image above won't work here it is again

Question

  1. How can I fix this sorting issue?

Update

I changed my ajax code to:

result.sort(function(a,b) {
  return (a.sort > b.sort) ? 1 : ((b.sort > a.sort) ? -1 : 0);
});

and result is the same screenshot

24
  • What is the type of your sort column in the database? I'm guessing it's not an integer. And if you're sorting by id, you need to specify the table, because you're joining multiple different tables. Commented Aug 29, 2018 at 0:59
  • no is varchar :) Commented Aug 29, 2018 at 1:00
  • 1
    Change it to an integer. Commented Aug 29, 2018 at 1:00
  • i'll try....... Commented Aug 29, 2018 at 1:00
  • 1
    @Erubiel, I think the screenshot is ordered by id, whereas the code suggests OP wants to ordered by sort, which appears to be a string, not an int. Commented Aug 29, 2018 at 1:05

2 Answers 2

3

According to the link you provided in the comments: https://www.codepile.net/pile/RlQoa6Dk

You are appending the data to the html on the ajax response, remember that ajax is asynchronous, so although your ajax requests are made in order, the responses might not happen in that order.

Thats why you always get random orders...

You should:

  1. Do the first ajax call
  2. foreach element in the response, make the second ajax call
  3. append the calculated html for each element in the response
  4. Once every ajax call is terminated, or at least the multiple ajax calls to calculate the html, order the original response which by now has the html.
  5. foreach element in the response, append the calculated html

Edit

Just appending the row before doing the ajax call worked.

<script defer>
$(document).ready(function() {
    $('select[name="selectset"]').on('change', function() {
        var id = $(this).val();
        if(id) {
            $.ajax({
                url: '{{ url('admin/selectset') }}/'+encodeURI(id),
                type: "GET",
                dataType: "json",
                success:function(result) {
                    $('div#dataaamsg').empty();
                    $('div#dataaamsg').append('Use <kbd>CTRL</kbd> or <kbd>SHIFT</kbd> button to select multiple options');
                    result.sort(function(a,b) {
                        return (a.sort > b.sort) ? 1 : ((b.sort > a.sort) ? -1 : 0);
                    });

                    $.each(result, function(key1, value1) {

                        var vvvid = value1.id;

                        if(value1['type'] == 'textfield'){
                            var my_row = $('<div class="row mt-20 ccin">');
                            $('div#dataaa').append(my_row);
                        }else if(value1['type'] == 'textareafield'){
                            var my_row = $('<div class="row mt-20 ccin">');
                            $('div#dataaa').append(my_row);
                        }else{
                            var my_row = $('<div class="row mt-20">');
                            $('div#dataaa').append(my_row);
                        }

                        // second data
                        $.ajax({
                            url: '{{ url('admin/findsubspecification') }}/'+value1['id'],
                            type: "GET",
                            dataType: "json",
                            success:function(data) {
                                // Check result isnt empty
                                var helpers = '';
                                $.each(data, function(key, value) {
                                    helpers += '<option value="'+value.id+'">'+value.title+'</option>';
                                });

                                if(value1['type'] == 'textfield'){
                                    var my_html = '{{ Form::open() }}<input name="product_id" id="product_id" type="hidden" value="{{$product->id}}"><input name="specification_id" id="specification_id" type="hidden" value="'+vvvid+'"><div class="col-md-4">'+value1.title+'</div>';
                                    my_html += '<div class="col-md-6"><input id="text_dec" name="text_dec[]" placeholder="text field" class="text_dec form-control"></div>';
                                    my_html += '<div class="col-md-2"><button type="button" id="custmodalsavee" class="custmodalsavee btn btn-xs btn-success">Save</button>{{Form::close()}}</div>';
                                    my_row.html(my_html);
                                }else if(value1['type'] == 'textareafield'){
                                    var my_html = '{{ Form::open() }}<input name="product_id" id="product_id" type="hidden" value="{{$product->id}}"><input name="specification_id" id="specification_id" type="hidden" value="'+vvvid+'"><div class="col-md-4">'+value1.title+'</div>';
                                    my_html += '<div class="col-md-6"><textarea id="longtext_dec" name="longtext_dec[]" placeholder="text area field" class="longtext_dec form-control"></textarea></div>';
                                    my_html += '<div class="col-md-2"><button type="button" id="custmodalsavee" class="custmodalsavee btn btn-xs btn-success">Save</button>{{Form::close()}}</div>';
                                    my_row.html(my_html);
                                }else{
                                    var my_html = '{{ Form::open() }}<input name="product_id" id="product_id" type="hidden" value="{{$product->id}}"><div class="col-md-4">'+value1.title+'</div>';
                                    my_html += '<div class="col-md-6"><select class="subspecifications form-control tagsselector" id="subspecifications" name="subspecifications[]" multiple="multiple">'+helpers+'</select></div>';
                                    my_html += '<div class="col-md-2"><button type="button" id="sendspacsdatato" class="sendspacsdatato btn btn-xs btn-success">Save</button>{{Form::close()}}</div>';
                                    my_row.html(my_html);
                                }


                            }
                        });
                        // second data

                    });
                }
            });
        }else{
            $('div#dataaa').empty();
        }
    });
});
</script>
Sign up to request clarification or add additional context in comments.

13 Comments

I've tried that it didn't work, (worked as i explained in issue section) so i decided to share original code.
@mafortis im 100% sure this is the problem with the code.
it stops rendering my data in blade (i just get white space)
Weird, is there any error logged in the console / devTools ? This is the problem with your original code, you do understand the problem right?
If you don't understand the problem, you can go to devTools, open the network tab and refresh the page, see how your request are done and how they complete... you may trigger request 1,2,3,4,5 but server can respond 5,2,1,3,4... or any other order, thats why they call it asynchronous... and thats why your html is appended wrongly
|
0

Update Your code in controller like below

add one function

public function cmp($a, $b)
{
    return strcmp($a['sort'], $b['sort']);
}

Update Your selectset function like below

public function selectset($id){
$selectsets = DB::table('sets')
    ->where('sets.id', '=', $id)
    ->join('set_specification', 'sets.id', '=', 'set_specification.set_id')
    ->join('specifications', 'set_specification.spec_id', '=', 'specifications.id')
    ->orderByRaw('set_specification.sort')
    ->get();
usort($selectsets, array($this, "cmp"));
return response()->json($selectsets);
}

4 Comments

hi, are you sure about usort? shouldn't have $ anything?
Okay try it once
i am getting SyntaxError: unexpected token: keyword 'function'[Learn More]
that was full error and here is detail of itpublic function cmp($a, $b) { return strcmp($a->sort, $b->sort); }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.