Yii2 active form, please wait message while submitting with ajax - php

I'm using Yii2's advanced template, and looking for a way to display a dialog with 'Please wait...' message while sending an login form to the server.
Here is my active form code:
<?php $form = ActiveForm::begin([
'id' => $model->formName(),
'enableAjaxValidation' => true,
]); ?>
<fieldset>
<?= $form->field($model, 'username', [
'inputOptions' => [
'placeholder' => $model->getAttributeLabel('username'),
],
])->label(false); ?>
<?= $form->field($model, 'password', [
'inputOptions' => [
'placeholder' => $model->getAttributeLabel('password'),
],
])->label(false)->passwordInput() ?>
<?= $form->field($model, 'rememberMe')->checkbox() ?>
<?= Html::submitButton('Login', ['class' => 'btn btn-lg btn-success btn-block', 'name' => 'login-button']) ?>
</fieldset>
<?php ActiveForm::end(); ?>
And my server side action:
public function actionLogin()
{
if (!\Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new LoginForm();
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
if ($model->load(Yii::$app->request->post()) && $model->login()) {
return $this->goBack();
} else {
return $this->render('login', [
'model' => $model,
]);
}
}
I'm successfully validating the inputs / sending the form, but need to display a dialog, so if the connection is slow the user will get an idea that the form is actually sending and needs more time to complete.

For ActiveForm you need to use according events. Currently it's managed with Javascript (see official upgrade info).
$('#myform').on('ajaxBeforeSend', function (event, jqXHR, settings) {
// Activate waiting label
}).on('ajaxComplete', function (event, jqXHR, textStatus) {
// Deactivate waiting label
});
Here is more detailed info about these two events.
ajaxBeforeSend:
ajaxBeforeSend event is triggered before sending an AJAX request for
AJAX-based validation.
The signature of the event handler should be:
function (event, jqXHR, settings)
where
event: an Event object.
jqXHR: a jqXHR object
settings: the settings for the AJAX request
ajaxComplete:
ajaxComplete event is triggered after completing an AJAX request for
AJAX-based validation. The signature of the event handler should be:
function (event, jqXHR, textStatus)
where
event: an Event object.
jqXHR: a jqXHR object
textStatus: the status of the request ("success", "notmodified", "error", "timeout", "abort", or "parsererror").
Also check this extension, maybe it will be useful for this purpose.

Please use the following javascript solution to listen to 'before submit'
$('body').on('beforeSubmit', 'form#yourFormId', function() {
$('#loading').show(); //show the loading div
var form = $(this);
$.ajax({
url: form.attr('action'),
type: 'post',
data: form.serialize(),
success: function(data) {
// do processing of data
$('#loading').hide(); //hide it
}
});
return false;
});
You will need to add a div with id loading and use suitable css for that
<div id='loading'> Loading ... </div>
Adding a maunal close button to this div is also recommended for cases with network fluctuations

Related

Yii2 AJAX form not validating

I'm migrating my site from Yii to Yii2 and trying to make a basic loan calculator. was reading the documentation and some answers on stack that suggested to use validationUrl.
Below is my code i've done so far. but i can't get my form validation to work. It allows me to submit an empty form. and doesn't show any errors?
Also where do i put my calculations, in actionloanValidate() or actionIndex() ?
<?php
$form = ActiveForm::begin([
'id' => $model->formName(),
'enableAjaxValidation' => true,
'validationUrl' => Url::toRoute(['calculator/default/loan-validate'])
]);
?>
<?= $form->field($model, 'price') ?>
<?= $form->field($model, 'downpayment') ?>
<?= $form->field($model, 'rate') ?>
<?= $form->field($model,'yearloan')->dropDownList(
['1' => '1 (12 months)', '2' => '2 (24 months)');
?>
<?= Html::submitButton('Submit', ['class' => 'btn btn-primary btn-block', 'tabindex' => '3']) ?>
<?php ActiveForm::end(); ?>
<script>
$(document).ready(function () {
var $form = $("#<?= $model->formName() ?>");
$form.on("beforeSubmit", function (event, messages) {
event.preventDefault();
$.ajax({
"type":"POST",
"url":$form.attr('action'),
"data":$form.serialize(),
"beforeSend":function( xhr ) {},
"dataType":"json",
"cache": true,
"success":function(data){
$("#totalLoanAmount").html(data.totalLoanAmount);
$("#monthlyInstallment").html(data.monthlyInstallment);
$("#loanCalcTable").html(data.loanCalcTable);
},
});
return false;
});
});
</script>
in my controller i have this
public function actionIndex() {
$model=new calculatorForm;
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
//DO CALCULATION HERE!!
}
return $this->render('loan-calculator', [
'model' => $model,
]);
}
public function actionloanValidate()
{
$model=new calculatorForm;
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
else {
return $this->renderAjax('loan-calculator', [
'model' => $model,
]);
}
}
my model rules are
public function rules() {
return [
//loan-calculator validation
[['price', 'downpayment', 'rate', 'yearloan'], 'required']
];
}
You are overriding the validation check by defining beforeSubmit in your javascript. You are also likely getting a cancelled ajax request as you need to call event.stopPropagation() after event.preventDefault()
If you are truly trying to achieve only required validation, don't use ajaxValidation.
On beforeSubmit validate the form
event.preventDefault();
event.stopPropagation(); //stops going to submit which will cancel your ajax
//a trick added to ensure validation is triggered on untouched fields
data = $form.data("yiiActiveForm");
$.each(data.attributes, function() {
this.status = 3;
});
$form.yiiActiveForm("validate");
if ($("#form").find(".has-error").length) {
return false;
}
$.ajax({
"type":"POST",
"url":$form.attr('action'),
"data":$form.serialize(),
"beforeSend":function( xhr ) {},
"dataType":"json",
"cache": true,
"success":function(data){
$("#totalLoanAmount").html(data.totalLoanAmount);
$("#monthlyInstallment").html(data.monthlyInstallment);
$("#loanCalcTable").html(data.loanCalcTable);
},
});
As well, the calculcation should be done in the actionIndex (the action of the form)

Yii2 ajax render image after call

So basically I have a controller that handles files (images & videos) and on the "view" view I have a button that's called "view content". That button is using the controller actionContent($id) and I want it when pressed to run the AJAX call to the action & render in-page in a div the image that's located in the model with id == $id. How can I handle the AJAX request and return the image displayed in the div?
public function actionContent($id)
{
$model = $this->findModel($id);
switch (substr($model->mime, 0, strpos($model->mime, '/'))) {
case 'image' :
return $this->renderAjax('_image', [
'img' => $model->getFullPath(),
]);
break;
default:
break;
}
}
And the view:
<span class="pull-right">
<?= Html::a('View Content', ['content', 'id' => $model->id], [
'class' => 'btn btn-default',
'id' => 'content'
]); ?>
</span>
With the script I already tried:
$(document).ready(function () {
$('#content').click(function () {
$(this).preventDefault();
$.ajax({
type: "GET",
url: $(this).href,
contentType: "<?= $model->mime?>",
success: function (response) {
('.show-content').html('<img src="data:image/png;base64,' + response + '" />');
}
})
})
})

Reload only gridview in yii2

How can I, reload only grid-view on on change event of drop-down in Yii2?
I know that it can be done via pjax but not sure where and how to use the code.
I am using Ajax request for communicating with controller. Here is the ajax code:-
function loadGrid(level) {
alert(level);
$.ajax({
type: 'GET',
url: 'index.php?r=villagedata/level',
data: {level:level},
success: function(data)
{
alert("Success");
$.pjax({container: '#myview'});
}
});
}
I wan't my grid to reload when the Ajax Request returns success message.
Thank You.
Exactly, using Pjax.
use yii\grid\GridView;
use yii\widgets\Pjax;
<?php Pjax::begin(['id' => 'pjax-grid-view']); ?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
'...'
],
]); ?>
<?php Pjax::end(); ?>
and jQuery to detect drop down change.
If dropdown has "dropdown" id,
$('#dropdown').on('change', function(ev) {
$.pjax({container: '#pjax-grid-view'})
});
Try
$("#idyourgrid").yiiGridView("applyFilter");

Save to database in yii2

I am trying to save to a database in yii2 using ajax but I am getting errors. I just want to insert the value or rate which is "up" into the database and I don't want to use a form, just on-click of a button.
This is my controller
public function actionThumbs()
{
$thumbs = new Thumbs;
$thumbs->user = Yii::$app->user->identity->email;
$thumbs->topic_id = Yii::$app->getRequest()->getQueryParam('id');
$thumbs->rate = $_POST["rate"];
if ($thumbs->load(Yii::$app->request->post()) ) {
$thumbs->load($_POST);
$thumbs->save();
return $this->redirect(['blog', 'id' => Yii::$app->getRequest()->getQueryParam('id')]);
}
return $this->redirect(['blog','id' => Yii::$app->getRequest()->getQueryParam('id')]);
}
This is my this is my ajax file
$("#mys").click(function() {
var rate = "up";
$.ajax({
type: 'POST',
url: 'vot/frontend/web/index.php?r=site%2Fthumbs',
data: 'rate='+rate,
success: function (rate) {
alert("test");
},
error: function (exception) {
alert(exception);
}
});
});
the view
<div>
<?= Html::Button('ups', ['class' => 'btn btn-primary', 'name' => 'mys' ,'id'=>'mys']) ?>
</div>
I get this alert error
The page at localhost says":
"[object Object]"
By default Yii2 controller doesn't accept POST request without _csrf protection, so there are 2 ways here:
1 - disable csrf:
public function actionThumbs() {
$this->enableCsrfValidation = false;
//your code here
}
2 - Send post request via ajax with _csrf token:
In your layout/main.php file, put this: <?= Html::csrfMetaTags() ?>
Before your "ajax" code, call this:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')
}
});
//Your ajax code here

how to save data using ajax in yii2

I don't want to submit a form but i want to get the value of a input field and send it to controller via ajax to be save in database.
I have this below JS code to help me get the content of the input field and send to the server side after 3 second of user input
<?php
$script = <<< JS
$(document).ready(function(){
//setup before functions
var typingTimer;
var doneTypingInterval = 3000;
var \$TitleInput = $('#product-product_title');
//on keyup, start the countdown
\$TitleInput.on('keyup input change paste',function(){
clearTimeout(typingTimer);
if (\$TitleInput.val()) {
typingTimer = setTimeout(doneTyping, doneTypingInterval);
}
});
//user is "finished typing," do something
function doneTyping () {
data = \$TitleInput.val();
$.ajax({
url: '/trobay/draft/create',
type: 'POST',
data: data,
success: function (data) {
alert(data)
},
error: function(jqXHR, errMsg) {
// handle error
alert(errMsg);
}
});
}
});
JS;
$this->registerJs($script);
?>
in my controller i have this
public function actionCreate()
{
$model = new Draft();
if ($model->load(Yii::$app->request->post())) {
$model->created_at = \time();
if($model->save()){
echo draftId;
}else{
echo '0';
}
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
I want to echo back the draftid if the title was draft was save successfully
how to make this work plase any help on this
below is my view
<?php $form = ActiveForm::begin([
'id' => $model->formName(),
'enableClientValidation' => true,
'fieldConfig' => ['template' => '{label}{input}{hint}']
]); ?>
<div class="row">
<div class="col-md-12">
<?= $form->field($model, 'product_title')->textInput([
'class' => 'title-input',
'placeholder' => 'Give us a title for your items(include size,brand,color,material. e.t.c)',
])->label(false) ?>
</div>
<div class="col-md-12 text-muted">E.g Men's blue addidas glide running shoes size 11 </div>
</div>
<?= $form->field($model, 'user_id')->textInput() ?>
<?= $form->field($model, 'product_name')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'product_description')->textarea(['rows' => 6]) ?>
<?= $form->field($model, 'category_id')->textInput() ?>
i have this in my view but i would like to only save the value of the first input field after 3 second that user entered there value
Try this JS, but change $('#form') on your ID form
$(document).ready(function(){
//setup before functions
var typingTimer;
var doneTypingInterval = 3000;
var $form = $('#form');
//on keyup, start the countdown
$form.find('input[type="text"]').on('keyup input change paste',function(){
clearTimeout(typingTimer);
if ($(this).val()) {
typingTimer = setTimeout(doneTyping, doneTypingInterval);
}
});
//user is "finished typing," do something
function doneTyping () {
$.ajax({
url: '/trobay/draft/create',
type: 'POST',
data: $form.serialize(),
success: function (data) {
alert(data)
},
error: function(jqXHR, errMsg) {
// handle error
alert(errMsg);
}
});
}
});

Categories