Reputation: 747
I'm a bit stuck in implementing AJAX with JSON response. I have this Controller
class Common::DatatablesStatesController < ApplicationController
def update
datatables_state.update(datatable_states_params)
render json: datatables_state
end
def show
render json: datatables_state
end
private
def datatable_states_params
params.require(:common_datatable_state).permit(:user_id, :name, :state)
end
def datatables_state
@datatables_state ||= current_user.datatables_states
.where(name: params[:id]).first_or_create
end
end
which basically checks if record by param exists if yes, then update state
column, if no - creates new record (current_user ID, contname from JS below, state)
My Coffeescript at the moment looks like this:
$ ->
$('#data-table').DataTable
ajax: $('#data-table').data('source')
serverSide: true
stateSave: true
contname = $('#data-table').attr('data-controller-name')
'stateSaveCallback': (settings, data) ->
$.ajax
'url': '/common/datatables_states/' + contname + '.json'
'data':
'user_id': user_id
'name': contname
'state': data
'dataType': 'json'
'type': 'PATCH'
success: ->
return
'stateLoadCallback': (settings, callback) ->
$.ajax
'url': '/common/datatables_states/' + contname + '.json'
'data':
'name': contname
'state': data
'async': false
'dataType': 'json'
'type': 'GET'
'success': (json) ->
callback json
return
return
return
I'm pretty sure there is something wrong in my JS part as nothing is happening in my console, but don't know what it is. I'd be happy for any help. Thank you!
Update
My routes look like this:
namespace :common do
resources :datatables_states, only: [:update, :show]
end
rails routes
common_datatables_state GET (/:locale)/common/datatables_states/:id(.:format) common/datatables_states#show {:locale=>/en|lv/}
PATCH (/:locale)/common/datatables_states/:id(.:format) common/datatables_states#update {:locale=>/en|lv/}
PUT (/:locale)/common/datatables_states/:id(.:format) common/datatables_states#update {:locale=>/en|lv/}
Basically idea was to pass that data-controller-name
from view as ID.
Update2
I switched to vanila JS as I had suspicion something's not right with my Coffeescript. Here is what I put in my JS file:
jQuery(document).ready(function() {
$('#data-table').DataTable(
{
"processing": true,
"serverSide": true,
"ajax": $('#data-table').data('source'),
stateSave: true,
"stateSaveCallback": function (settings, data) {
// Send an Ajax request to the server with the state object
$.ajax( {
"url": "/common/datatables_states/campaigns_index.json", //Test link with :ID campaigns_index.json
"data": {"name":"campaigns_index", "state": data} ,
"dataType": "json",
"type": "PATCH",
"success": function () {}
} );
},
stateLoadCallback: function (settings, callback) {
$.ajax( {
url: '/common/datatables_states/campaigns_index.json',
async: false,
dataType: 'json',
type: 'GET',
success: function (json) {
callback( json );
}
} );
}
}
);
});
and this is what I see in my console now:
Started PATCH "/common/datatables_states/campaigns_index.json" for 10.0.2.2 at 2017-05-12 20:27:03 +0000
Processing by Common::DatatablesStatesController#update as JSON
Parameters: {"name"=>"campaigns_index", "state"=>{"time"=>"1494620823501", "start"=>"0", "length"=>"10", "order"=>{"0"=>["0", "asc"]}, "search"=>{"search"=>"", "smart"=>"true", "regex"=>"false", "caseInsensitive"=>"true"}, "columns"=>{"0"=>{"visible"=>"true", "search"=>{"search"=>"", "smart"=>"true", "regex"=>"false", "caseInsensitive"=>"true"}}, "1"=>{"visible"=>"true", "search"=>{"search"=>"", "smart"=>"true", "regex"=>"false", "caseInsensitive"=>"true"}}, "2"=>{"visible"=>"true", "search"=>{"search"=>"", "smart"=>"true", "regex"=>"false", "caseInsensitive"=>"true"}}}}, "id"=>"campaigns_index"}
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
Common::DatatableState Load (1.5ms) SELECT "common_datatable_states".* FROM "common_datatable_states" WHERE "common_datatable_states"."user_id" = $1 AND "common_datatable_states"."name" = $2 ORDER BY "common_datatable_states"."id" ASC LIMIT $3 [["user_id", 2], ["name", "campaigns_index"], ["LIMIT", 1]]
Completed 400 Bad Request in 15ms (ActiveRecord: 2.0ms)
ActionController::ParameterMissing (param is missing or the value is empty: common_datatable_state):
app/controllers/common/datatables_states_controller.rb:14:in `datatable_states_params'
app/controllers/common/datatables_states_controller.rb:4:in `update'
app/controllers/application_controller.rb:45:in `set_current_user'
Update 3
I'm trying to implement stateLoadCallback for my DataTables 1.10.13.
I changed my controller action to this so it selects state
only:
def show
state = current_user.datatables_states.where(name: params[:id]).select(:state)
render json: state
end
then in JS I do this, which is kind of according to docs:
stateLoadCallback: function (settings, callback) {
$.ajax( {
url: '/common/datatables_states/campaigns_index.json',
async: false,
dataType: 'json',
type: 'GET',
success: function (json) {
callback( json );
}
} );
}
however in terminal I do not get state
back:
Started GET "/common/datatables_states/campaigns_index.json" for 10.0.2.2 at 2017-05-14 10:02:03 +0000
Processing by Common::DatatablesStatesController#show as JSON
Parameters: {"id"=>"campaigns_index"}
User Load (0.9ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
Common::DatatableState Load (1.6ms) SELECT "common_datatable_states"."state" FROM "common_datatable_states" WHERE "common_datatable_states"."user_id" = $1 AND "common_datatable_states"."name" = $2 [["user_id", 2], ["name", "campaigns_index"]]
Completed 200 OK in 83ms (Views: 25.3ms | ActiveRecord: 9.6ms)
Type of my state
column is JSON and when I navigate to http://localhost:3000/en/common/datatables_states/campaigns_index.json
I see this:
[
{
"id": null,
"state": "{\"time\":\"1494761473541\",\"start\":\"0\",\"length\":\"10\",\"order\":{\"0\":[\"0\",\"asc\"]},\"search\":{\"search\":\"\",\"smart\":\"true\",\"regex\":\"false\",\"caseInsensitive\":\"true\"},\"columns\":{\"0\":{\"visible\":\"true\",\"search\":{\"search\":\"\",\"smart\":\"true\",\"regex\":\"false\",\"caseInsensitive\":\"true\"}},\"1\":{\"visible\":\"true\",\"search\":{\"search\":\"\",\"smart\":\"true\",\"regex\":\"false\",\"caseInsensitive\":\"true\"}},\"2\":{\"visible\":\"true\",\"search\":{\"search\":\"\",\"smart\":\"true\",\"regex\":\"false\",\"caseInsensitive\":\"true\"}}}}"
}
]
Update 3.1.
I added state = current_user.datatables_states.where(name: params[:id]).select(:state).first
and I have this now:
{
"id": null,
"state": "{\"time\":\"1494910215056\",\"start\":\"0\",\"length\":\"10\",\"order\":{\"0\":[\"0\",\"asc\"]},\"search\":{\"search\":\"\",\"smart\":\"true\",\"regex\":\"false\",\"caseInsensitive\":\"true\"},\"columns\":{\"0\":{\"visible\":\"true\",\"search\":{\"search\":\"\",\"smart\":\"true\",\"regex\":\"false\",\"caseInsensitive\":\"true\"}},\"1\":{\"visible\":\"true\",\"search\":{\"search\":\"\",\"smart\":\"true\",\"regex\":\"false\",\"caseInsensitive\":\"true\"}},\"2\":{\"visible\":\"true\",\"search\":{\"search\":\"\",\"smart\":\"true\",\"regex\":\"false\",\"caseInsensitive\":\"true\"}}}}"
}
When I change my show
to this:
def show
state = current_user.datatables_states.where(name: params[:id]).select(:state).first
my_hash = JSON.parse(state)
render json: JSON.pretty_generate(my_hash)
end
and get this error:
TypeError (no implicit conversion of nil into String):
app/controllers/common/datatables_states_controller.rb:10:in `show'
app/controllers/application_controller.rb:45:in `set_current_user'
What should I do to get my stateLoadCallback working?
Upvotes: 0
Views: 214
Reputation: 136
The error you added indicates that no common_datatable_state
parameter was passed, this is because of how you defined your strong parameters (datatable_state_params
method). Try changing the data
field in your ajax call like this:
"data": {"common_datatable_state":{"name":"campaigns_index", "state": data}}
Upvotes: 1
Reputation: 292
I think problem is here where(name: params[:id])
, could you check params here
Upvotes: 0