Yii2 activeform ajax submit and validation - javascript

Currently to achieve ajax submit and validation at the same time. I'm using custom function like:
$('.edit_form').submit(function (e) {
e.preventDefault();
var form = $(this);
var formData = $(this).serialize();
if (form.find('.has-error').length) {
return false;
}
$.ajax({
url: form.attr("action"),
type: form.attr("method"),
data: formData,
success: function (data) {
...
},
error: function () {
alert("Something went wrong");
}
});
});
And here is php side, for validation my config looks like that:
$form = ActiveForm::begin([
'id' => "some_form",
'action' => ['user/edit'],
'options' => ['class' => 'edit_form'],
'enableAjaxValidation' => false,
'enableClientValidation' => true,
]); ?>
I'm sure that It's not the best way to achieve what I need. Especially this part that I use for preventing for submission in case of validation error:
if (form.find('.has-error').length) {
return false;
}
Any suggestions? How to achieve ajax submission and validation properly using Yii 2's inbuilt settings?

Use beforeSubmit event instead of submit, the beforeSubmit will only be triggered once the form passes the validation.
$('form').on('beforeSubmit', function(e) {
var form = $(this);
var formData = form.serialize();
$.ajax({
url: form.attr("action"),
type: form.attr("method"),
data: formData,
success: function (data) {
...
},
error: function () {
alert("Something went wrong");
}
});
}).on('submit', function(e){
e.preventDefault();
});

you can use AjaxSubmitButton.
Your form should b
$form = ActiveForm::begin([
'id' => "some_form",
'action' => 'javascript:void(0)',
'options' => ['class' => 'edit_form'],
]);
use AjaxSubmitButton here
AjaxSubmitButton::begin([
'label' => 'Submit',
'id' => 'some_form',
'ajaxOptions' => [
'type' => 'POST',
'url' => \yii\helpers\Url::to(['/user/edit']),
'success' => new \yii\web\JsExpression(
'function(data){
if(data=="success")
{
}else{
$.each(data, function(key, val) {
$("#"+key).after("<div class=\"help-block\">"+val+"</div>");
$("#"+key).closest(".form-group").addClass("has-error");
});
}
}'
),
],
'options' => ['class' => 'btn btn-success', 'type' => 'submit'],
]);
AjaxSubmitButton::end();
In your controller
public function actionEdit()
{
$model = new User;
if($model->save())
{
$result = 'success';
Yii::$app->response->format = trim(Response::FORMAT_JSON);
return $result;
}else{
$error = \yii\widgets\ActiveForm::validate($model);
Yii::$app->response->format = trim(Response::FORMAT_JSON);
return $error;
}
}

Here I've find some interesting javascript-side validation tricks
So, a javascript submit button can be as:
$('body').on('click', '#submit', function(e) {
e.preventDefault();
var yiiform = $('#my-form');
$.ajax({
type: yiiform.attr('method'),
url: yiiform.attr('action'),
data: yiiform.serializeArray(),
success: function(data) {
if(data.success == 'true') {
window.location.href = 'http://my.success.page';
} else {
// here there is (maybe) the right way to trigger errors
$.each(data, function(key, val) {
yiiform.yiiActiveForm('updateAttribute', key, [val]);
});
}
}
});
}
triggered by:
<?= Button::widget([
'label' => Yii::t('app', 'Submit'),
'options' => [
'id'=>'submit',
'class' => 'btn btn-primary pull-right',
]]);?>
And the action controller will reply with:
...
if ($model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
if($model->save()) {
return ['success'=>'true'];
} else {
return ActiveForm::validate($model);
}
}
...
Details about ActiveForm::validate() can be found here

Related

Unable to pass ajax to controller function

I am trying to update my database using ajax in laravel. When i click the button (toggle button) it should update the database enable column from 1 to 0.
Here is the script written in the view
$(".toggle-btn").change(function() {
var id = $(this).attr('name'); // $(this) refers to button that was clicked
$.ajax({
url: '/adminpanel/dviulaan/stt',
method: "post",
data: {'id' : id} ,
dataType: "json",
});
});
Here is my route
Route::post('adminpanel/dviulaan/stt', 'AdminDvAnnouncement#status');
And here is the controller function
public function status()
{
$id = Input::all();
if (Request::ajax()) {
DvAnnouncement::where('announcement_id', $id)->update(
[
'enable' => '0',
'user_updated' => Auth::user()->id,
'updated_at' => new DateTime,
]);
}
$response = array(
'status' => 'success',
'msg' => 'Option created successfully',
);
return Response::json( $response );
}
When i click the button it shows the following error in the consol
POST http://localhost/adminpanel/dviulaan/stt 500 (Internal Server Error)
Please help me to find the error.
I have even changed the controller method as below
public function status(Request $request)
{
$id = Input::get('id');
if (Request::ajax()) {
DvAnnouncement::where('announcement_id', $id)->update(
[
'enable' => '0',
'user_updated' => Auth::user()->id,
'updated_at' => new DateTime,
]);
}
$response = array(
'status' => 'success',
'msg' => 'Option created successfully',
);
return Response::json( $response );
}
$id = Input::all(); => $id = Input::get('id');
UPD after logs
include in head
<meta name="csrf-token" content="{!! csrf_token() !!}" />
then change in function
$(".toggle-btn").change(function() {
var id = $(this).attr('name'); // $(this) refers to button that was clicked
$.ajax({
url: '/adminpanel/dviulaan/stt',
method: "post",
data: {'id' : id, '_token': $('meta[name="csrf-token"]').attr('content')} ,
dataType: "json",
});
});

javascript code to get multiple checked values from listbox php

I have two dependent select box in my form for selecting country and state.
i have a multi select checkbox dropdown for selecting country,
and i want to fetch state of selected country
but i cannot understand how to pass multiple checked id in my function from javascript.
below is my html select list box code
<?php
echo $this->Form->input('UserLogDetail.service_area_category_id', array(
'id' => 'shipping_type',
'required' => false,
'multiple' =>'multiple',
'type' => 'select',
'class' => 'form-control drop-arrow',
'label' => false,
'options' => $serviceCategory,
'empty' => '--Select--'
));
?>
<?php
echo $this->Form->input('UserLogDetail.skills', array(
'class' => 'form-control',
'required' => false,
'id' => 'skill',
'label' => false,
'options' => '$states',
'empty' => '--Select--'
));
?>
javascript function
<script type="text/javascript">
$(document).ready(function() {
$("#shipping_type").on('change', function() {
var id = $(this).val();
if (id) {
var dataString = 'id=' + id;
$.ajax({
type: "POST",
url: '<?php echo Router::url(array("controller" => "Profiles", "action" => "loadSkills"),true); ?>',
data: dataString,
dataType: 'JSON',
cache: false,
success: function(html) {
$("#skill").html("");
$.each(html, function(key, value) {
$('<option>').val('').text('select');
$('<option>').val(key).text(value).appendTo($("#skill"));
});
$('#skill').selectpicker('refresh');
}
});
}
});
});
</script>
controlller function
public function loadSkills() {
$this->loadModel('Skill');
$states = array();
if (isset($this->request['data']['id'])) {
$states = $this->Skill->find('list', array('fields' => array('Skill.id','Skill.skill_name'),'conditions' => array(
'Skill.service_area_category_id IN' => explode(",",$this->request['data']['id']))));
}
echo json_encode($states);
exit();
}
try to call ajax below way
javascript :
$("#shipping_type").change(function() {
$.ajax({
type: "POST",
url: '<?php echo Router::url(array("controller" => "Profiles", "action" => "loadSkills"),true); ?>',
//passing data to php
data: { id:$(this).val() },
dataType: 'JSON',
cache: false,
success: function(html) {
$("#skill").html("");
$.each(html, function(key, value) {
$('<option>').val('').text('select');
$('<option>').val(key).text(value).appendTo($("#skill"));
});
$('#skill').selectpicker('refresh');
}
});
});
php
public function loadSkills() {
$this->loadModel('Skill');
$states = array();
//Getting post id
if (isset($this->request['id'])) {
$states = $this->Skill->find('list', array('fields' => array('Skill.id','Skill.skill_name'),'conditions' => array(
'Skill.service_area_category_id IN' => explode(",",$this->request['data']['id']))));
}
echo json_encode($states);
exit();
}
public function loadSkills() {
$this->getServiceArea();
$this->loadModel('Skill');
$skills = array();
if (isset($this->request['data']['id'])) {
$ids = explode(",",$this->request['data']['id']);
if(count($ids)>1){
$skills = $this->Skill->find('list', array('fields' => array('Skill.id','Skill.skill_name'),'conditions' => array(
'Skill.service_area_category_id IN' => $ids)));
} else {
$skills = $this->Skill->find('list', array('fields' => array('Skill.id','Skill.skill_name'),'conditions' => array(
'Skill.service_area_category_id' => $ids)));
}
}
echo json_encode($skills);
exit();
}

Multiselect dropdown listbox code using cakephp

i have two dependent select box in my form for selecting country and state.
when i select country India then it should populate its dependent state.upto this my code working fine...
bit i want to make this multiselect listbox.
Ex - if i select two countries from county dropdown then it populates states from two countries....not of single selected country.
below is my code...
HTML Select list box code
<?php
echo $this->Form->input('service_area_category_id', array(
'id' => 'shipping_type',
'required' => false,
'multiple' => 'multiple',
'type' => 'select',
'class' => 'form-control drop-arrow',
'label' => false,
'options' => $serviceCategory,
'empty' => '--Select--'
));
?>
<?php
echo $this->Form->input('ship_category', array(
'class' => 'form-control drop-arrow',
'required' => false,
'id' => 'state',
'label' => false,
'options' => '$states',
'empty' => '--Select--'
));
?>
Controller function
public function getServiceArea(){
$this->loadModel('ServiceAreaCategory');
$serviceCategory = $this->ServiceAreaCategory->find('list', array(
'conditions' => array(
'is_active' => 1
),
'fields' => array(
'ServiceAreaCategory.id',
'ServiceAreaCategory.name'
),
'order' => 'name ASC'
));
$this->set('serviceCategory', $serviceCategory);
}
public function loadSkills() {
$this->loadModel('Skill');
$states = array();
if (isset($this->request['data']['id'])) {
$states = $this->Skill->find('list', array(
'fields' => array(
'Skill.id',
'Skill.skill_name'
),
'conditions' => array(
'Skill.service_area_category_id' => $this->request['data']['id']
)
));
}
echo json_encode($states);
exit();
}
Ajax Script
<script type="text/javascript">
$(document).ready(function() {
$("#shipping_type").on('change', function() {
var id = $(this).val();
if (id) {
var dataString = 'id=' + id;
$.ajax({
type: "POST",
url: '<?php echo Router::url(array("controller" => "Profiles", "action" => "loadSkills")); ?>',
data: dataString,
dataType: 'JSON',
cache: false,
beforeSend: function() {
$('.spinicon').show();
},
complete: function() {
$('.spinicon').hide();
},
success: function(html) {
$("#loding1").hide();
$.each(html, function(key, value) {
$('<option>').val('').text('select');
$('<option>').val(key).text(value).appendTo($("#state"));
});
$('#state').selectpicker('refresh');
}
});
}
});
});
</script>
in your cakephp side function should be
public function loadSkills() {
$exploded_ids=explode(",",$this->request['data']['country_ids']);
$ids= "IN ('".implode(",",$exploded_ids).")";
$this->loadModel('Skill');
$states = array();
if (isset($this->request['data']['id'])) {
$states = $this->Skill->find('list', array('fields' => array('Skill.id','Skill.skill_name'),'conditions' => array(
'Skill.service_area_category_id '.$ids )));
}
echo json_encode($states);
exit();
}
And your Javascript and AJAX code Should be
<script type="text/javascript">
$(document).ready(function() {
$("#shipping_type").on('change', function() {
var ids = $(this).val();
if (id) {
$.ajax({
type: "POST",
url: '<?php echo Router::url(array("controller" => "Profiles", "action" => "loadSkills"),true); ?>',
data: {country_ids: ids}
dataType: 'JSON',
cache: false,
beforeSend: function() {
$('.spinicon').show();
},
complete: function() {
$('.spinicon').hide();
},
success: function(html) {
$("#loding1").hide();
$("#state").html("");
$.each(html, function(key, value) {
$('<option>').val('').text('select');
$('<option>').val(key).text(value).appendTo($("#state"));
});
$('#state').selectpicker('refresh');
}
});
}
});
});
</script>

How to submit form ajax in symfony2?

I am about to submit my form Using Ajax,i have successfully submit my form using POST but don't know how to use Ajax with Symfony
builform
$builder->add('name', 'text', array('constraints' => array(new NotBlank()), 'attr' => array('placeholder' => 'Name')))
->add('gender', 'choice', array('empty_value' => 'Select Gender', 'constraints' => array(new NotBlank()), 'choices' => \AppBundle\Entity\Records::$gender_list, "required" => true))
->add('dateOfBirth', 'birthday', array('label' => 'Date Of Birth','required'=>true))
->add('image_path', 'file', array('label' => ' ','required'=>false, 'data_class' => null, 'constraints'=>array(new Assert\File( array('mimeTypes'=>$mime_types, 'maxSize'=>'2048k' )))))
->add('country_of_birth', 'entity', array('empty_value' => 'Country of Birth',
'class' => 'AppBundle\Entity\Location',
'property' => 'country',
'label' => 'Country of Birth'
))
->add('religion', 'entity', array('empty_value' => 'Select Religion',
'class' => 'AppBundle\Entity\Religion',
'property' => 'name',
'label' => 'Religion'
));
Action
$success = false;
$record_rep = new \AppBundle\Entity\Records();
$form = $this->createForm(new \AppBundle\Form\AddPersonType(), $record_rep);
if ($this->getRequest()->getMethod() == 'POST') {
$form->submit($request);
if ($form->isValid()) {
$data = $form->getData();
$file = $data->getImagePath();
$image = $file->getClientOriginalName();
$new_image_name = $this->hanldeUpload($image, $file);
$this->savetoDB($data, $record_rep, $new_image_name);
$success = true;
}
}
return $this->render('AppBundle:Homepage:add_person_form.html.twig', array('form' => $form->createView(), 'success'=>$success ));
}
With jQuery, use serialize() the form and post it to your route.
$('#form').submit(function(e) {
e.preventDefault();
var url = "{{ path('YOUR_PATH') }}";
var formSerialize = $(this).serialize();
$.post(url, formSerialize, function(response) {
//your callback here
alert(response);
}, 'JSON');
});
In your action
if ($form->isSubmitted() && $form->isValid()) {
....
// or return new JsonResponse($anyData);
return new Response(json_encode(['status'=>'success']));
}
it must be ok like this. but you can add some parameters like the format, methods etc... in your routing.
For the Ajax:
$("#person").submit(function(e){
var formURL = "{{ path('form') }}";
var formData = new FormData(this);
$.ajax({
url: formURL,
type: 'POST',
data: formData,
mimeType:"multipart/form-data",
contentType: false,
cache: false,
processData:false,
success: function(data, textStatus, jqXHR)
{
},
error: function(jqXHR, textStatus, errorThrown)
{
}
});
e.preventDefault(); //Prevent Default action.
e.unbind();
});
$("#person").submit();
And for Action
if ($request->isXmlHttpRequest()) {
....
return new Response(json_encode(array('status'=>'success')));
}

CActioveform enableClientValidation doesn't work

I have one form with activated clientValidation, but the JS code to validate the form has not been registered by Yii.
My form code is here:
$form = $this->beginWidget('bootstrap.widgets.TbActiveForm', array(
'id' => 'login-form',
'enableClientValidation' => true,
'clientOptions' => array(
'validateOnSubmit' => true,
'afterValidate' => 'js:function(form, data, hasError) {
if (!hasError){
str = $("#login-form").serialize() + "&ajax=login-form";
$.ajax({
type: "POST",
url: "' . Yii::app()->createUrl('/') . '",
data: str,
dataType: "json",
beforeSend : function() {
$("#login").attr("disabled",true);
},
success: function(data, status) {
if (data.authenticated) {
window.location = data.redirectUrl;
} else {
$.each(data, function(key, value) {
var div = "#"+key+"_em_";
$(div).text(value);
$(div).show();
});
$("#login").attr("disabled",false);
}
},
});
return false;
}
}',
),
));
echo $form->textField($model, 'username');
echo $form->passwordField($model, 'password');
echo TbHtml::submitButton('Login', ['id' => 'login']);
$this->endWidget();
The registered JS code is only this:
<script type="text/javascript">
/*<![CDATA[*/
jQuery('body').popover({'selector':'a[rel=popover]'});
jQuery('body').tooltip({'selector':'a[rel=tooltip]'});
/*]]>*/
</script>
I don't see, why its not working. Please help me to find the bug.
The code is from this blog post: http://tahiryasin.wordpress.com/2013/05/23/ajax-based-yii-login-form/

Categories