Search code examples
javascriptphplaravelx-editable

Change dynamic status with x-editable in laravel


I have select button where I choose status for my entries. This status comes from statuses table and it's not a column in each table (it's general option). What I want to do is to change status_id column in my tables with help of x-editable but I don't know how to get my dynamic data in JavaScript.

Here is my current form to show statuses in index page of my reviews for example:

 <form action="{{route('updatebyajax', $rating->id)}}" method="post">
    {{csrf_field()}}
       <td class="text-center" style="width:100px;">
          <select class="form-control status" name="status_id">
            @foreach($statuses as $status)
              <option id="rating" class="rating" data-url="{{ route('updateratebyajax', $rating->id) }}" data-pk="{{ $rating->id }}" data-type="select" data-placement="right" data-title="Edit Rate" value="{{$status->id}}">{{$status->title}}</option>
           @endforeach
        </select>
    </td>
 </form>

So what I need is basically get info out of statuses table and change by select.

dropdown

Update

As requested here is my table screenshot:

table image

PS: here is default sample of select button: sample link

<a href="#" id="status" data-type="select" data-pk="1" data-url="/post" data-title="Select status"></a>
<script>
$(function(){
    $('#status').editable({
        value: 2,    
        source: [
              {value: 1, text: 'Active'},
              {value: 2, text: 'Blocked'},
              {value: 3, text: 'Deleted'}
           ]
    });
});
</script>

Update 2

Review Database reviews

Status Table status

Update 3

I just add my controller method and route in case

controller

public function updatebyajax(Request $request, $id)
  {
    return Rating::find($id)->update([
      'status_id' => $request->get('status_id'),
    ]);
  }

route

Route::post('/updatebyajax/{id}', 'RatingController@updatebyajax')->name('updatebyajax');

UPDATE 4

I mixed several solutions on internet till I finally get status 200 OK in my network but still nothing changes in my database, here is my current codes:

controller

public function updatebyajax(Request $request, $id)
  {
    if (request()->ajax())
        {
            $ratings = DB::table('ratings')->select('status_id','id')->where('status_id', '=', $id)->get();
            return Response::json( $ratings );
        }
  }

AJAX

<script type="text/javascript">
$(".status").change(function() {
    $.ajax({
        type: "post", // for edit function in laravel
        url: "{{url('admin/updatebyajax')}}" + '/' + $(this).val(), // getting the id of the data
        data: {_token: "{{ csrf_token() }}",status: this.value }, //passing the value of the chosen status
        dataType: 'JSON',
        success: function (data) {
            console.log('success');
        },
        error: function (data) {
            console.log('error');
        }
    });
});
</script>

FORM

<form action="{{route('updatebyajax', $rating->id)}}" method="post">
                             {{csrf_field()}}
                              <td class="text-center" style="width:100px;">
                                <select id="{{ $rating->id }}" class="form-control status" name="status_id">
                                  @foreach($statuses as $status)
                                    <option value="{{$status->id}}">{{$status->title}}</option>
                                  @endforeach
                                </select>
                              </td>
                          </form>

UPDATE 5

Regarding to leih answer currently I have this:

Controller

public function updatebyajax(Request $request, $id)
  {
    // Note: should probably use a $request->has() wrapper to make sure everything present

    try {
        // you can also use the ID as a parameter, but always supplied by x-editable anyway
        $id = $request->input('pk');
        $field = $request->input('name');
        $value = $request->input('value');

        $rating = Rating::findOrFail($id);
        $rating->{$field} = $value;
        $rating->save();
    } catch (Exception $e) {
        return response($e->getMessage(), 400);
    }
  }

Route

Route::post('/updatebyajax', 'RatingController@updatebyajax')->name('updatebyajax');

Blade

//Select
<a
  href="#"
  class="status"
  data-type="select"
  data-pk="{{ $rating->id }}"
  data-value="{{ $rating->status_id }}"
  data-title="Select status"
  data-url="{{ route('updatebyajax') }}"
></a>

//JS

<script type="text/javascript">

$.ajaxSetup({
      headers: {
          'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
      }
  });

$(function() {
    $('.status').editable({
      type:"select",
        source: [
            @foreach($statuses as $status)
                { value: {{ $status->id }}, text: {{ $status->title }} }
            @endforeach
        ],
    });
});
</script>

And here is the result I get:

screenshot5

PS: If I don't use $.ajaxSetup({ headers: {.... and use java code in answer I will get this error

Parse error: syntax error, unexpected ','

Any idea??


Solution

  • When using X-edtiable with a <select> option, it's good to look at the documentation, but better to look at official examples and check the FAQ for what the back end needs. You don't need to make your own forms or write your own AJAX requests with X-editable (that's the whole point). Based on what you're asking, it sounds like the code should look similar to this:

    RatingController

    public function UpdateByAjax(Request $request)
    {
        // Note: should probably use a $request->has() wrapper to make sure everything present
    
        try {
            // you can also use the ID as a parameter, but always supplied by x-editable anyway
            $id = $request->input('pk');
            $field = $request->input('name');
            $value = $request->input('value');
    
            $rating = Rating::findOrFail($id);
            $rating->{$field} = $value;
            $rating->save();
        } catch (Exception $e) {
            return response($e->getMessage(), 400);
        }
    
        return response('', 200);
    }
    

    Route

    Route::post('/updatebyajax', 'RatingController@UpdateByAjax')->name('updatebyajax');
    

    View

    Note: I'm not setting the CSRF token below as it should already be set globally for X-editable (e.g. for text fields in screenshot) if required, or via some other mechanism.

    <a
      href="#"
      class="status"
      data-type="select"
      data-pk="{{ $rating->id }}"
      data-name="status_id"
      data-value="{{ $rating->status_id }}"
      data-title="Select status"
      data-url="{{ route('updatebyajax') }}"
    ></a>
    <script>
    $(function() {
        // using class not id, since likely used with multiple records
        $('.status').editable({
            // Note: cleaner to format in the controller and render using the @json directive
            source: [
                @foreach($statuses as $status)
                    { value: '{{ $status->id }}', text: '{{ $status->title }}' }
                    @unless ($loop->last)
                        ,
                    @endunless
                @endforeach
            ]
        });
    });
    </script>
    

    Additional reference: see 'Rendering JSON' in the Displaying Data blade documentation