Fullcalendar updateEvent doesn't rerender - javascript

I want to add events to my DB via fullcalendar. So I want to add an event and set its id to the id it gets in my DB.
function addCalEvent(event) {
var jEvent = {};
jEvent['startTime'] = moment(event.start).unix();
jEvent['worker']="GUZ"
jEvent['title']=event.title;
if (event.end) {
jEvent['endTime'] = moment(event.end).unix();
}
$.ajax({
url: 'dux.html',
type: 'POST',
data: {
type: 'addNewEvents',
event: jEvent,
REQUEST_TOKEN: "REQUEST_TOKEN>",
},
datatype: 'json',
success: function(data) {
event.id=data;
event.title="NEW";
$('#calendar').fullCalendar('updateEvent', event);
},
});
}
The ajax retrieves the id of the added event and the id and title do get changed, but the 'updateEvent' method doesn't seem to be called, because there is no change to the rendered events title or id.

Ok,
apperently if you make a asynchronous ajax call the order in which commands are executed isn't the order you write it.
I need to add async: false to make this work.

You can manually call rerender events with $('#calendar').fullCalendar( ‘rerenderEvents’ )
Link to docs here

Related

How to avoid ajax async when using jQuery events

I have an input field with ajax call (filling some other input fields) on blur and buttons with click events (some of the click events set input fields to an empty string).
For example,
$("#input_field1").on('blur', function () {
$.ajax({
//async:false,
method: "GET",
url: "my_ajax.php",
cache: false,
dataType: "json",
data: { data1: $("#input_field1").val()},
success: function(result){
$("#some_other_input").val(result.data2);
}
})
});
$("#button1").on('click', function () {
$("#input_field1").attr("readonly", true);
var form = $("#my_form");
form.validate().resetForm();
form[0].reset();//form contains #some_other_input
});
When that input field is focused and then user clicks on any button, blur event is triggered and of course, appropriate click event after it.
If I don't use async:false, ajax will fill those input fields after click event is processed and other inputs will be filled instead of being empty.
Reading about how async:false should be avoided always, I need a way for my click events to wait until ajax is done, if there is an ajax call at that moment.
You need a concurrency check for your cases. On your blur action; check and set a value to prevent reentering the other calls.
Also during an ajax request, you need to prevent clicking the buttons.
One more thing, what if just after bluring your input field, user re-focuses and re-focusouts your input? In this case, your action will be triggered twice.
As a result, you need to handle concurrency. There are also some javascript libraries to handle concurrency, you can either use them or handle by your own.
Anyway to handle your case, here is a sample code:
let hasCall = false;
$("#input_field1").on('blur', function () {
if(hasCall){
return; //there is an active call...
}else{
hasCall = true;
$("#button1").prop('disabled', true);//prevent clicking on button
}
$.ajax({
//async:false,
method: "GET",
url: "my_ajax.php",
cache: false,
dataType: "json",
data: { data1: $("#input_field1").val()},
success: function(result){
$("#some_other_input").val(result.data2);
}
}).always(()=>{
//reset the state:
hasCall=false;
$("#button1").prop('disabled', false);
});
});
$("#button1").on('click', function () {
$("#input_field1").attr("readonly", true);
var form = $("#my_form");
form.validate().resetForm();
form[0].reset();//form contains #some_other_input
});

jQuery Click Event CheckBox Changed Ajax Call

I have three checkboxes that who have checked/unchecked values populated from a model. I'm using an Ajax post on button click event to call controller actions for each checkbox changed event in order to update the DB.
Here is the code for one of the checkboxes (apart from the selector ID, they are all the same):
$(document).ready(function () {
//document.getElementById('UpdateButton').onclick = function () {
$("UpdateButton").click = function () {
$('#NatAm').change(function () {
// if ($('#NatAm').is(':checked')) {
$.ajax({
//url: '#Url.Action("NativeUpdate", "Transactions")',
url: '/Transactions/NativeUpdate',
//data: { isNativeUp: true },
type: 'POST',
dataType: "json"
});
//}
});
Edit (HTML/View Code):
#Html.CheckBox("NatAm", (bool)#ViewBag.NativeAm)
<input name="UpdateButton" id="UpdateButton" type="submit" value="Update" style="margin-left: 15px; margin-top: 3px;" class="btn btn-success" />
I cannot get this to work. Before adding the button, the ajax post was working fine. Thank you for your help!
Your click handler isn't right. You need to pass in the id of the button and use jQuery click handler. You also need not to nest the handlers:
$(document).ready(function() {
$("#UpdateButton").click(update);
$('#NatAm').change(update);
});
function update() {
$.ajax({
url: '/Transactions/NativeUpdate',
type: 'POST',
dataType: 'json'
});
}
JSFiddle Demo: https://jsfiddle.net/vLzwuwdo/
You're telling JQuery to look for 'UpdateButton' tags which in your case does not exist. You're missing the # which indicates an ID in your button.
Try this
$(document).ready(function () {
//document.getElementById('UpdateButton').onclick = function () {
$("#UpdateButton").click(function () {
$('#NatAm').change(function () {
// if ($('#NatAm').is(':checked')) {
$.ajax({
//url: '#Url.Action("NativeUpdate", "Transactions")',
url: '/Transactions/NativeUpdate',
//data: { isNativeUp: true },
type: 'POST',
dataType: "json"
});
//}
}));
id should be unique in same document (NatAm and UpdateButton), replace the duplicate ones by global classes will solve the first problem.
You should not define event inside another since every time you trigger the first it will create new event for the element, in your case every time you click new change event will be created and attached to the first element with NatAm.
Hope this helps.

Running code in callback of Vue js $set method

I have a v-for that generates a list of flights. When user clicks on "flight details" button I send an AJAX request to server, and append the new info to the results array. In order to update the view, I use $set method:
this.results.displayed.$set(key, _.extend({}, row, detail.items));
Where key is $index of array object, row is the object, and detail.items is the new data (price details).
I need to change some classes after the view updates. I searched on internet and found this solution:
this.$nextTick(function () {
$(el.target).toggleClass('load');
});
Where el.target is the clicked button.
The problem is that toggleClass executes before view update and I need it to run after view updates.
Here is the complete AJAX call:
$.ajax({
method: 'POST',
dataType: 'json',
url: this.base_info.url + 'getpricedetail?token=' + this.token,
data: {price_id : price_id},
beforeSend: function () {
$(el.target).addClass('load');
}.bind(this),
success: function (detail) {
this.results.displayed.$set(key, _.extend({}, row, detail.items));
this.$nextTick(function () {
$(el.target).siblings('.prices').addClass('open');
});
}.bind(this),
error: function () {
data.vars.loading = false;
}.bind(this)
});
It's probably a problem with the asyncronicity of the AJAX call.
Where do you call the $nextTick ? in the callback of the AJAX call?
We need some moe code to solve this probably.

Can't access object made by ajax call

I have this ajax request:
$.ajax({
type: "POST",
dataType: "json",
data: dataString,
url: "app/changeQuantity",
success: function(data) {
$('#table').append('<tr><td><a id="uid">click</a></td></tr>');
});
as you can see it makes new row in #table. But this new objects made by ajax are not accessible from next functions. Result from ajax is not a regullar part of DOM, or what is the reason for this strange behavior?
$('#uid').on('click', function () {
alert('ok');
});
Use event delegation:
$(document).on('click','#uid', function () {
alert('ok');
});
Note that ajax calls are asynchronous. So whatever you do with the data you need to do it in a callback within the success function (that is the callback which is called when the ajax call returns successfully).
Jquery on doesn't work like that. Use have to give a parent which not loaded by ajax, and the specify ajax load element like this
$('#table').on('click','#uid' ,function () {
// what ever code you like
});
Is simple and complex at the same time. Simple to solve but complex if you are getting started with javascript...
Your event handler - onclick is being fired and bound to an object that doesnt yet exist.
So when you append the object to the #table, you need to set up your click handler as the object now exists.
So in your success part of the ajax return add the click handler event there.
success: function(data) {
$('#table').append('<tr><td><a id="uid">click</a></td></tr>');
$('#uid').on('click', function () {
alert('ok');
});
});
Or how about you make it dynamic and create a function to do it for you.
function bindClick(id) {
$('#' + id).click(function() {
//Do stuff here
console.log('I made it here' + id);
});
}
Then:
success: function(data) {
$('#table').append('<tr><td><a id="uid">click</a></td></tr>');
bindClick(uid);
});
}
This is a super contrived example but you get the idea you just need to make the rest of it dynamic as well. for example some name and counter generated id number: id1, id2, id3...
Try it like this, add this $('#uid').on('click', function () { into the success
$.ajax({
type: "POST",
dataType: "json",
data: dataString,
url: "app/changeQuantity",
success: function(data) {
$('#table').append('<tr><td><a id="uid">click</a></td></tr>');
$('#uid').on('click', function () {
alert('ok');
});
});
});

jQuery plugin bsmSelect doesn't update its values when it is called again and its select options have changed

I'm using bsmSelect jQuery plugin. Basically, what it does is changing the way a select-multiple is rendered to make easier to pick up the options. It hides the select element and shows a list instead.
So, first of all I'm applying the plugin function to my select-multiple element:
$(document).ready(function() {
...
$('#my_select_multiple').bsmSelect({
plugins: [$.bsmSelect.plugins.sortable()],
title: 'Add',
removeLabel: 'Remove'
});
...
});
On the other way, I have another select element (this one is simple) which has an ajax request bind to its change event. This ajax request get new #my_select_multiple options depending on the select simple value. Ajax response is the new HTML for #my_select_multiple options. So I have:
function getNewOptions(val) {
var r = $.ajax({
type: 'GET',
url: /*My URL*/
}).responseText;
return r;
}
...
$(document).ready(function() {
...
$('#my_select_simple').change() {
$('#my_select_multiple').html(getNewOptions($(this).val()));
}
...
});
AJAX is working as expected. New options are got correctly and they are inserted into #my_select_multiple (which is hidden by bsmSelect plugin, but I can check it with Firebug). But bsmSelect didn't realize new changes and doesn't get updated.
So, I think what I want is to reapply $('#my_select_multiple').bsmSelect(); with its new options.
I've been looking around a little bit and here is what I have tried.
1. I've tried to call again the funcion with the success and complete (one at time) of the AJAX request. Didn't work:
function getNewOptions(val) {
var r = $.ajax({
type: 'GET',
url: /*My URL*/,
success: function() { $('#my_select_multiple').bsmSelect(); }
}).responseText;
return r;
}
2. I've tried to bind the function with the on jQuery function. Didn't work:
$('#my_select_simple').on('change', function() {
$('#my_select_multiple').bsmSelect();
});
3. I've tried 1 and 2 removing previosly the HTML generated by bsmSelect. Didn't work.
Thank you very much.
UPDATE: The exact code
First I have a global.js file which apply bsmSelect plugin to some select multiples (.quizzes):
$('.quizzes').bsmSelect({
plugins: [$.bsmSelect.plugins.sortable()],
title: 'Add',
removeLabel: 'Remove'
});
And then, in the php file I define the updateQuizzes function and bind it to the select simple (project_id) change event:
<script type="text/javascript">
function updateQuizzes(project_id) {
var r = $.ajax({
type: 'GET',
url: '<?php echo url_for('event/updateQuizzes')?>'+'<?php echo ($form->getObject()->isNew()?'':'?id='.$form->getObject()->getId()).($form->getObject()->isNew()?'?project_id=':'&project_id=')?>'+project_id,
success: function() { $('.quizzes').bsmSelect({
plugins: [$.bsmSelect.plugins.sortable()],
title: 'Add',
removeLabel: 'Remove'
}); }
}).responseText;
return r;
}
$('#project_id').change(function(){
$('.quizzes').html(updateQuizzes($(this).val()));
});
</script>
As I told, the AJAX request works without problems, but not the calling bsmSelect the second time...
Not sure if this is what the problem is, but you could try
$('#my_select_simple').change() {
$('#my_select_multiple').html(getNewOptions($(this).val())).trigger('change');
}
This triggers a change event on select_multiple, and might fire bsmSelect. I'm not sure what the problem here is exactly, but that's the best I can come up with.
I think you want to set your HTML in the success of the Ajax call, something like:
function loadNewOptions(val) {
$.ajax({
type: 'GET',
url: /*My URL*/,
success: function(data) {
$('#my_select_multiple').html(data).bsmSelect();
}
});
}
And then calling like:
$('#my_select_simple').change() {
loadNewOptions($(this).val());
}
$(document).ready(function() {
$('#my_select_simple').change() {
$('#my_select_multiple').load("your Url", function(){
$('#my_select_multiple').bsmSelect();
});
}
});
something like this should work.
.load will put whatever your url returns into #my_select_multiple
the first parameter is the url to load, and the 2nd is a function to call when it is done. which is where you need to set up your fancy selector.
Ok, I opened a ticket and bsmSelect developer has answered me in minutes. Great!
To let bsmSelect know about its select changes, you have to trigger a change event on the select. There is no need to call bsmSelect again.
So it can be that way:
function loadNewOptions(val) {
var r = $.ajax({
type: 'GET',
url: /*My URL*/,
success: function(data) {
$('#my_select_multiple').html(data).trigger('change');
}
}).responseText;
return r;
}
$('#my_select_simple').change(function() {
loadNewOptions($(this).val());
});

Categories