Maximum call stack exceeded when adding data to select2 - jquery-select2

When trying to add data to a select 2 element after receiving it back from an ajax function I get this error on the console.
The data I get back from the server looks like this
[
{
"id":"55785510-2c64-447d-953d-01ce16ed9843",
"text":"Room 100"
},
{
"id":"55785516-3da4-4791-98d5-01cd16ed9843",
"text":"Room 110"
},
...
]
It has a hand full of these items in the returned json.
Here I am trying to add the data to a select2 element that has been initialized already with no options added.
success: (data) ->
console.log data
$('select.building-select').select2
data: data
As soon as I try to do that is when I get the call stack error
Here is the stack trace
Uncaught RangeError: Maximum call stack size exceeded
jQuery.extend.isPlainObject # jquery.js:1
jQuery.extend.jQuery.fn.extend # jquery.js:218
jQuery.extend.jQuery.fn.extend # jquery.js:228
...
The thrid line repeats many times.
This error only happens when I attempt to add the data to the select on the success callback of the ajax function.
For reference here is the ajax function
$('#MeetingAddForm').find('input, select').change ->
# If required inputs and selects for finding a meeting room are valid
MeetingAttendants = $('#MeetingAttendants')
MeetingDate = $('#MeetingDate')
MeetingStartTime = $('#MeetingStartTime')
MeetingEndTime = $('#MeetingEndTime')
if MeetingAttendants.parsley().isValid() and MeetingDate.parsley().isValid() and MeetingStartTime.parsley().isValid() and MeetingEndTime.parsley().isValid()
# All inputs are valid so lets get the available Room
$.ajax
url: $('#MeetingAddForm').data 'meetingrooms-ajax-url'
data:
attendants: MeetingAttendants.val()
date: MeetingDate.siblings('input[type=hidden]').val()
start_time: MeetingStartTime.siblings('input[type=hidden]').val()
end_time: MeetingEndTime.siblings('input[type=hidden]').val()
success: (data) ->
console.log data
$('select.building-select').select2
data: data
else
console.log 'false'
When I take the returned json and add it to a variable and attempt to assign the data to the select on page load, everything works fine.

Related

How can I persist newly saved values across components? Pulling original values from DOM

I have 3 different components with buttons to navigate across them. All of the default form values are pulled from the DOM and set into the data beforeMount. The reason I'm doing it this way is that the values are coming from my Rails database.
When I edit a form and save it successfully (via ajax), everything is good but once I switch components using the navigation, those values in the inputs are reset back to the original/old values since the beforeMount is running again and the DOM was not updated with the new value (due to no refresh yet).
I tried changing the original values in the DOM with jQuery upon every update but that didn't work. It would work once but further updates didn't change.
Here is how I'm setting the data inside of the beforeMount:
const element = document.getElementById('setting');
const setting = JSON.parse(element.dataset.setting)
this.discountType = setting.discount_type;
Then, upon every ajax request I tried to edit those original values in the DOM which didn't work:
outerThis = this;
Rails.ajax({
url: '/update-settings',
type: 'POST',
data: data,
dataType: 'json',
success: (data) => {
ShopifyApp.flashNotice('Successfully updated')
var settings = $('#setting').data('setting')
settings.discount_type = outerThis.discountType
},
error: (err) => {
ShopifyApp.flashError('There was an error')
}
})
What's the recommended way to go about this issue?

Dynamic dropdown (select_tag) with Ruby on Rails

I've been trying to create 3 dynamic dropdown, wich the first change the content of the sencond and the second change the content of the thrid.
I haven't found an example for doing that, I found an example in which you send all the information to the client and there it is filtered, but it is not what I want.
I want it to interact with the server every time the select has a change.
If somebody has a tutorial or could give a brief example, I would really appreciate that
Thanks
You need 3 things for it to work:
1- Javascript on change event on your select:
// This will monitor your select control and start the process after its content has changed
$('select#my_select_control').change( select_has_changed(this) );
2- Javascript Ajax controller function:
// This will send the selected value to your Rails server
function select_has_changed(obj)
{
// We get the selected value
var value = $(obj).val();
// It's a good idea here to verify the value.
// For example if the value is empty we can empty the content
// of the target select control and do not go through ajax
// We make the ajax call to the rails controller
$.ajax({url: '/path/to/controller/action',
data: {value: value},
// We are requesting for json response, but you can use html if you like
dataType: "json",
// Get method, or other is you like, you just have to
// define it accordingly in your routes
method: 'get'
// This is the function to call when ajax succeed
success: function (data) { fill_up_form(data, obj) }
});
}
// This is called when Ajax was successful , and it will
// fill up your target select control
function fill_up_form(data, obj)
{
content = ... // Here you loop through your json data to create
// a set of OPTION tags
// Or if you used html as dataType, the rails server had it done
// so you can inject directly in your select target control
$('select#my_target_control').html(content);
}
3- Rails controller method
# The action method that receive the ajax call
# you must have set-up your routes accordingly
def get_my_ajax_data
# This fetches the data from the database
# Note that we are using `params` with the same index as
# we used in the `data` hash of the ajax call
# which, in my example is `value`
records = Model.where(field: params[:value])
# For a json request we return a collection of [id, text]
# that can be used to populate your target select control
# As an alternative we could have render a template if
# we was requesting for html content
render json: records.collect{ |r| {id: r.id, text: r.name} }
end

Confused about passing parameters from JavaScript Ajax call back to controller to render a form

Scenario: I click on some objects,table rows,etc on my page and I get their IDs for example I click on Providers list and get provider_id. And then I click on a button on the page:
Now I have a service that accepts those parameters and passes back to me a JSON which I want to show it in a Table form in my next page. So this button click is responsible for that.
So the page I am gonna show that Table in it is Pharmacy/Patients so I have a
PatientsController#index method.
Now in JS side I am doing an Ajax call like this:
// provider_id is global var and coming from the clicks on other parts of the page.
//so we have some value like 234 for it.
$('.personlistbtn').click(function(e) {
$.ajax({
type: 'GET',
data : { 'provider' : provider_id, 'therapeutic_class' : 'all' },
url: '/pharmacy/patients',
async: false,
success: function (data) {
// not sure what to write in here really.
},
error: function () {
// show some oops error
}
}
});
});
So that makes the call to /pharmacy/patients
Now I am confused how to handle it from there?
PatientsController: Maybe something like this?
def index
if request.xhr?
#my_json = MyNetHTTPFunction.getMeBackJSON(params)
end
end
MyNetHTTPFunction.getMeBackJSON(params) is just a method I have written that accepts the query params I am passing to it ( which hopefully are coming from Ajax call right? and queries the web-service and returns me back the JSON I need to use in my View.

Rails: Upon Successful AJAX POST, Return ID

I'm using the following code to create new instances of the Impressions model:
var id;
$.ajax({
type: 'POST',
url: '/impressions',
data: {'impression[content]':tags[i].book.impression, 'impression[user_id]':current_user},
success: function(){id="<%= #impression.id %>";},
dataType: 'html',
});
alert(id);
Upon success, I want it to return the id number of the new instance, but the current function causes a runtime error stating that #impression.id is nil--which, upon reflection, of course it's nil at runtime. How else can I pull the id from the database, though?
One way of doing this would be for your controller code to render json. For example if your create code simply did
render :json => #impression
(possibly inside a responds_to block) then that data will get passed to you success function. If you declare that as
function(data){
...
}
and set the dataType to json, then data will be the json object you rendered and you'll be able to get at all of the impression's properties, including its id. Of course you can render whatever json you want - you don't have to turn the whole object into json.

How to create a method query that works for an Infinite Scroll loading behavior

I'm creating a page that outputs a list of 1000-3000 records. The current flow is:
User loads a page
jQuery hits the server for all the records and injects them into the page.
Problem here is that those records for some users can take 3+ seconds to return which is a horrible UX.
What I would like to do is the following:
1. User loads a page
2. jQuery hits the server and gets at most 100 records. Then keeps hitting the server in a loop until the records loaded equal the max records.
Idea here is the user gets to see records quickly and doesn't think something broke.
So it's not really an infinite scroll as I don't care about the scroll position but it seems like a similar flow.
How in jQuery can I the the server in a loop? And how in rails can I query taking into account a offset and limit?
Thank you
You can simply query the server for a batch of data over and over again.
There are numerous APIs you can implement. Like:
client: GET request /url/
server: {
data: [ ... ]
rest: resturl
}
client GET request resturl
repeat.
Or you can get the client to pass in parameters saying you want resource 1-100, then 101-200 and do this in a loop.
All the while you will render the data as it comes in.
Your server either needs to let you pass in parameters saying you want record i to i + n.
Or your server needs to get all the data. Store it somewhere then return a chunk of the data along with some kind unique id or url to request another chunk of data and repeat this.
// pseudo jquery code
function next(data) {
render(data.records);
$.when(getData(data.uniqueId)).then(next);
}
function getData(id) {
return $.ajax({
type: "GET",
url: ...
data {
// when id is undefined get server to load all data
// when id is defined get server to send subset of data stored # id.
id: id
},
...
});
}
$.when(getData()).then(next);

Resources