Wait for ajax response using a yii2 form - javascript

I am implementing a form that request a process with ajax to sync 2 databases and I need to wait until the process finish.
In my form I have the flowing code to send the db credentials:
<div class="col-lg-offset-1 col-lg-11">
<?=
Html::a('Sync Databases', ['runsync'], [
'class' => 'btn btn-primary',
'id' => 'ajax_link_02',
'data-on-done' => 'linkFormDone',
'data-form-id' => 'syncdb_form',]
)
?>
and I also register the js with the ajax
function handleAjaxLink(e) {
e.preventDefault();
var
$link = $(e.target),
callUrl = $link.attr('href'),
formId = $link.data('formId'),
onDone = $link.data('onDone'),
onFail = $link.data('onFail'),
onAlways = $link.data('onAlways'),
ajaxRequest;
$("#show_msg").html("Loading.... please wait...");
ajaxRequest = $.ajax({
type: "post",
dataType: 'json',
url: callUrl,
data: (typeof formId === "string" ? $('#' + formId).serializeArray() : null)
});
// Assign done handler
if (typeof onDone === "string" && ajaxCallbacks.hasOwnProperty(onDone)) {
ajaxRequest.done(ajaxCallbacks[onDone]);
}
// Assign fail handler
if (typeof onFail === "string" && ajaxCallbacks.hasOwnProperty(onFail)) {
ajaxRequest.fail(ajaxCallbacks[onFail]);
}
// Assign always handler
if (typeof onAlways === "string" && ajaxCallbacks.hasOwnProperty(onAlways)) {
ajaxRequest.always(ajaxCallbacks[onAlways]);
}
}
var ajaxCallbacks = {
'linkFormDone': function (response) {
$('#show_msg').html(response.body);
}
}
The ajax call works fine and call the controller:
public function actionRunsync() {
if (Yii::$app->request->isAjax) {
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$model = new \app\modules\admin\models\syncdb();
$response = $model->runSyncDb($_POST);
$res = array(
'body' => $response,
'success' => true,
);
return $res;
}
}
But is not waiting to the process
$model->runSyncDb($_POST)
to finish. If I comment the process and add a text it works fine but not if the process takes long.
What am I doing wrong?

I just added async false to the ajax request:
async: false,
so now the ajax is like this:
ajaxRequest = $.ajax({
type: "post",
async: false,
dataType: 'json',
url: callUrl,
data: (typeof formId === "string" ? $('#' + formId).serializeArray() : null)
});
Not sure the best way but works perfectly...

Related

Calling another function while long polling

I see that there is a question about this, but I don't know how I would implement it in my case (since I'm not using multiple sessions). Also, I must say that the long-polling itself works, but nothing else does while it runs.
There is javascript file which sets the method, and chat.php file which on this basis either receives messages (starts polling) or sends them. The issue is I can't send the messages if I include the "while" function. Here it is:
from chat.js:
chat.fetchMessages = function ()
{
if(localStorage.getItem("amInQueue") != 1)
{
$.ajax({
url: '../ajax/chat.php',
type: 'post',
data: { method: 'fetch' },
async: true,
cache: false,
timeout: 50000,
success: function(data)
{
if(data!='')
{
chat.printMessages(data);
}
setTimeout(chat.fetchMessages, 1000);
}
});
}
}
chat.throwMessage = function (message, byuser)
{
if ($.trim(message).length != 0 && localStorage.getItem("amInQueue") != 1)
{
$.ajax({
url: '../ajax/chat.php',
type: 'post',
data: { method: 'throw', message: message, byuser:byuser },
success: function(data)
{
chat.entry.val('');
}
});
}
}
from chat.php:
<?php
require '../core/init.php';
if (isset($_POST['method']) === true && empty($_POST['method']) === false)
{
$chat = new Chat();
$method = trim($_POST['method']);
if($method === 'fetch' && $_SESSION['ses_amInQueue']==0)
{
$shouldStop=0;
$messageIDs = $chat->checkForLatestMessage($_SESSION['ses_myChat'], $_SESSION['ses_meInChat']);
while($messageIDs=='')
{
usleep(30000);
clearstatcache();
$messageIDs = $chat->checkForLatestMessage($_SESSION['ses_myChat'], $_SESSION['ses_meInChat']);
}
if($messageIDs!='')
{
$messageString=$chat->getNewMessages($_SESSION['ses_myChat'], $messageIDs);
$chat->deleteMessages($messageIDs);
echo $messageString;
}
}
else if($method === 'throw' && isset($_POST['message']) === true)
{
$message = trim($_POST['message']);
$byuser = trim($_POST['byuser']);
if (empty($message) === false)
{
$chat->throwMessage($byuser, $message, $_SESSION['ses_otherInChat'], $_SESSION['ses_myChat']);
}
}
I can't use "throw" method while the "while" loop is running. I tried checking the method on the end of "while" loop to see if it's "throw" and including it in "while"'s conditions, but that didn't work for some reason.
How do I pull this out? Both work independently, or if I remove "while" loop (but it is then no longer long-polling).

AJAX if JSON-response = X -> do action

I am working on a site and now I am at the point that I have to make the AJAX-forms. The code I have now does insert the params in the database, but now I get stuck at the following point. I want my code to hide the form after the status of JSON is success. Working in a MVC. This is my code:
(I have let the unimportant part of the code away)
AJAX:
$("#submitAssignment").on("click", function () {
$.ajax({
type: "POST",
url: "/set/new/ass",
async: true,
data: data,
success: function (data) {
console.log("Het item is toegevoegd");
var err = jQuery.parseJSON(data);
sendAlert.createAlert(err.return, err.type);
if (jsonObj.status == 'success') {
$("#submitAssignment").hide();
}
}
});
});
Controller:
else {
$UserModel = new UserModel();
if ($UserModel->placeAssignment($title, $uploadable, $level, $points, $description)) {
$err['data'] = array("status" => "success", "type" => "success", "return" => "De opdracht is toegevoegd! Joepie :D" );
} else {
$err['data'] = array("status" => "failed", "type" => "danger", "return" => "Er is iets misgegaan!");
}
}
exit( $err['endpoint'] = json_encode( $err['data'], $options = 0 ) );
The part I want to hide after status = succes, does not hide, so thats my problem. I have searched other questions, but aint got success with that. What am I doing wrong in this case?
The problem in this case is that I used the wrong call-back in the ajax-code. I used JSONobj.status, but it need to be: err.status because I am handling it at that way. #timothyGroote gave this answer and now it works.
My ajax-code now:
$.ajax({
type: "POST",
url: "/set/new/ass",
async: true,
data: data,
success: function (data) {
console.log("Het item is toegevoegd");
var err = jQuery.parseJSON(data);
sendAlert.createAlert(err.return, err.type);
if (err.status == 'success') {
$("#submitAssignment").hide();
}
}
});

Infinite scroll in Symfony using Ajax

I wanted to show products from db using infinite scroll.
Here is my Controller:
$start=0;
$limit= 6;
$query = $repository->createQueryBuilder('classified')
->join('classified.statusId','status')
->andWhere('status.name=:status')
->setParameter('status','active')
->setFirstResult($start)
->setMaxResults($limit)
->getQuery();
$results = $query->getResult();
if ($request->isXmlHttpRequest()){
$list = $this->renderView('search-result.html.twig', [
'results' => $results
]);
$response = new JsonResponse();
$response->setData(array('classifiedList' => $list));
return $response;
}
Ajax:
$(window).scroll(function () {
if($(window).scrollTop() + $(window).height()>= $(document).height()){
getmoredata();
}
})
function getmoredata() {
$.ajax({
type: "GET",
url: "{{ path('classified_list', {'type' : 'all'}) }}",
dataType: "json",
cache: false,
success: function (response) {
$('.card-deck').append(response.classifiedList);
$('#spinner').hide();
console.log(response);
},
error: function (response) {
console.log(response);
}
});
}
So now what is happening is the first 6 results is repeatedly showing when the scrolling is triggered. I know this is not correct and I don't expect this to work properly. But what I don't know is what is the next step.
So do I need to add paginator or something?
Any help would be appreciated,Thanks!
You need to track whether your ajax is requesting or not, so it will not do request multiple times when window reach the scroll limit. Also, you need to track the offset and whether you have more data to loads. e.g
window.__isFetching = false;
window.__offset = 0;
window.__hasMoreData = true;
$(window).scroll(function () {
if($(window).scrollTop() + $(window).height()>= $(document).height()){
if(!window.__isFetching && window.__hasMoreData) {
getmoredata();
}
}
})
function getmoredata() {
window.__isFetching = true;
$.ajax({
type: "GET",
// NOTE, you can pass current offset here in url
url: "{{ path('classified_list', {'type' : 'all', }) }}"+"&offset="+window.__offset,
dataType: "json",
cache: false,
success: function (response) {
$('.card-deck').append(response.classifiedList);
$('#spinner').hide();
console.log(response);
// Note that here, server side response must have next offset and hasMoreData attribut.
window.__isFetching = false;
window.__hasMoreData = response.hasMoreData;
window.__offset = response.offset
},
error: function (response) {
console.log(response);
}
});
}
in server side , which is symfony, you might want to do something like:
// Get offset from request query
$start= $request->query->get('offset');
$limit= 6;
$query = $repository->createQueryBuilder('classified')
->join('classified.statusId','status')
->andWhere('status.name=:status')
->setParameter('status','active')
->setFirstResult($start)
->setMaxResults($limit)
->getQuery();
$results = $query->getResult();
if ($request->isXmlHttpRequest()){
$list = $this->renderView('search-result.html.twig', [
'results' => $results
]);
$response = new JsonResponse();
// And add offset and hasMoreData fields in response
$response->setData(array(
'classifiedList' => $list,
'offset' => $start += 1
'hasMoreData' => count($list) < ($limit * &start)
)
);
return $response;

Passing custom error code to ajax error function

I'm trying to pass custom error code to the client-side to ajax error function.
In the server side:
$response = array();
if ( empty($post['parent_id']) ) {
$response = array('error' => true, 'status_code' => -2);
exit();
}
$is_valid_id = RC()->is_valid_id($post['parent_id']);
$row = RC()->get_row_data($post['parent_id']);
if ( ! $is_valid_id ) {
$response = array('error' => true, 'status_code' => -1);
} else if ( ! $row ) {
$response = array('error' => true, 'status_code' => 0);
} else {
$response = json_encode($row);
}
echo $response;
Then I want to check for this status code in my js script, but couldn't find a way to do this (found ways only without trigger the error event).
$.ajax({
url: ajax_url,
data: {
'action': 'rc_parent_sign_in',
'form_data': $('#parent-sign-in-form').serialize(),
'security': security_nonce
},
type: "post",
dataType: "json",
cache: false,
success: function (response) {
var query_vars = $.param(response);
window.location.replace('http://localhost/renecassin/user-registration/?' + query_vars);
},
error: function (response) {
$('.form-control-feedback').addClass('hide');
/* Looking for something like this */
switch ( response.status_code) {
case -2 :
parent_id_form_group.addClass('has-danger').children('#empty-field').
removeClass('hide');
prent_id_input.addClass('form-control-danger');
break;
case -1 :
parent_id_form_group.addClass('has-danger').children('#not-valid-id-feedback').
removeClass('hide');
prent_id_input.addClass('form-control-danger');
break;
default :
parent_id_form_group.addClass('has-danger').children('#id-not-exists-feedback').
removeClass('hide');
prent_id_input.addClass('form-control-danger');
}
}
});
Any help will be appreciate.
It's because the response will go to your response callback, you are successfully returning an object.
The error callback will only be called if the request itself failed (timeout,404 etc..)
You need to handle your internal error codes in your success callback

php file_put_contents take file longer than script executes

If I don't use sleep(3). Page refresh and take old file. Or I use timer in js before reload it's help. But I think it's wrong way. I don't understand how return $ajax success after file_put_contents finished finally.
class OrderparamController extends FrontEndController
{
public function actionIndex($typeproduct = OrderService::TypePrintBannerCloth) {
$forms = $this->requireFile('order-forms.php');
$tplParams=array(
'id_order' => $typeproduct,
'forms' => $forms
);
$this->render('form',$tplParams);
}
/**
* Require file
*/
protected function requireFile($file_name){
$configFile = YiiBase::getPathOfAlias('application.cache').'/'.$file_name;
$handle = fopen($configFile, "r");
fclose($handle);
require $configFile;
return $forms;
}
/*
* Удалить параметр
*/
public function actionDeleteparamoption() {
$configFile='order-forms.php';
$forms=$this->requireFile($configFile);
$keyfield = $_POST['keyfield'];
$id_order = (int)$_POST['id_order'];
$numoption = $_POST['numoption'];
unset($forms[$id_order]['fields'][$keyfield]['options'][$numoption]);
if ($this->writeFile($forms,$configFile)) {
$answer=array(
'ok' => true,
);
} else {
$answer=array(
'ok' => false,
);
}
**sleep(3);**
echo json_encode($answer);
}
}
I use js for sending ajax
$('.js-btn-delete').on('click',function(){
var request ={
keyfield : $(this).data('keyfield'),
id_order : Var.id_order,
label : $(this).data('label'),
numoption : $(this).data('option'),
}
$.ajax({
url: '/orderparam/deleteparamoption',
type: 'POST',
data: request,
dataType: 'json',
async: true,
success: deleteOrderParamResult
})
});
function deleteOrderParamResult(data){
if (data.ok) {
var num=intVal($('.param-option').index($('.param-option:visible')));
document.cookie = "viewOption="+num;
location.reload();
} else {
alert('ошибка');
}
}

Categories