YII2 gridview custom search with ajax - ajax

I am working with Yii2.0 search functionality,if we show the grid as its means the ajax search is working fine,but i have to changed the layout(see the screen below), from that right side form i have to do the search using ajax.
I also search with google but not get the related one.
Thanks in advance for your help.

I suggest you the use of a separated filter form like explain in this Yii2 guide
http://www.yiiframework.com/doc-2.0/guide-output-data-widgets.html#separate-filter-form
Using a partial view _search.php with (eg:) the following contents:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
?>
<div class="post-search">
<?php $form = ActiveForm::begin([
'action' => ['index'],
'method' => 'get',
]); ?>
<?= $form->field($model, 'title') ?>
<?= $form->field($model, 'creation_date') ?>
<div class="form-group">
<?= Html::submitButton('Search', ['class' => 'btn btn-primary']) ?>
<?= Html::submitButton('Reset', ['class' => 'btn btn-default']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
and include it in index.php view like so:
<?= $this->render('_search', ['model' => $searchModel]) ?>

Related

Yii2 ActiveForm: display Ajax validation response at the top of the form or in errorSummary()

I'm using ActiveForm and I would need to display the validation errors not close to the input fields but rather at the top of the form.
As shown in the sample code below, setting errorOptions I avoid to display the error message in the default position.
Ajax validation is working but the $form->errorSummary($model) doesn't show any message, even if here it seems like it should and in the documentation I could not find a clear answer.
Also, adding Html::error($model, 'username') does not help with Ajax validation.
<?php
$form = ActiveForm::begin([
'id' => 'test-form',
'options' => ['class' => 'form-horizontal'],
'enableAjaxValidation' => true,
'enableClientValidation' => true,
])
?>
<?= $form->errorSummary($model) ?>
<?= Html::error($model, 'username') ?>
<div class="form-row">
<div class="form-group col-md-3">
<?= $form->field($model, 'username', ['errorOptions' => ['tag' => false]])->textInput()->label("Username") ?>
</div>
</div>
<?php ActiveForm::end() ?>
In Yii1.1 the validation errors can be displayed in a more flexible way, since you could define label, input and error individually. Something like this:
<?php echo $form->labelEx($model,'username'); ?>
<?php echo $form->textField($model,'username'); ?>
<?php echo $form->error($model,'username'); ?>
In that case you can simply move $form->error($model,'username'); anywhere within the form.
How is it possible to obtain the same results with Yii2 without using the Javascript API?
Display the Ajax validation errors for individual input at the top of the form.
Display the Ajax validation errors with errorSummary()
Edit
I forgot to mention that I'm using Bootstrap4 through the extension yii2-bootstrap4. Part of the problems I'm having with the error display may be related to this bug.
Considering the answer from #serghei-leonenco I add here some complete minimal code to replicate the problem.
Model
namespace frontend\models;
use Yii;
use yii\base\Model;
class AjaxForm extends \yii\base\Model
{
public $demo;
public function rules()
{
return [
// define validation rules here
[['demo'], 'required'],
[['demo'], 'string', 'length' => [2, 4]],
];
}
}
View
<div class="row">
<div class="col-lg-6">
<?php $form = ActiveForm::begin(['id' => 'test-form',
'options' => [
'class' => 'form-horizontal'],
'enableAjaxValidation' => true,
'enableClientValidation' => false,]) ?>
<div class="form-row">
<div class="form-group col-md-3">
<?php echo $form->field($model, 'demo', ['template' => '{error}']); ?>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-3">
<?= $form->field($model, 'demo')->textInput()->label("Demo") ?>
<?php echo $form->field($model, 'demo', ['template' => '{error}']); ?>
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-1 col-lg-11">
<?= Html::submitButton('Submit 1', ['class' => 'btn btn-primary','name' => 'submit1']) ?>
</div>
</div>
<?php ActiveForm::end() ?>
</div>
</div>
Controller
public function actionTestajax()
{
$model = new AjaxForm();
// Ajax validation
if (Yii::$app->request->isAjax){
$model->load(Yii::$app->request->post());
Yii::$app->response->format = Response::FORMAT_JSON;
$ret = ActiveForm::validate($model);
Yii::info("Ajax validation: " . json_encode($ret));
return $ret;
}
// form submit
if ($model->load(Yii::$app->request->post())) {
if($model->validate()){
// valid data received in $model
//var_dump($model);
return $this->render('testajax_submit', ['model' => $model]);
} else {
return $this->render('testajax', ['model' => $model]);
}
}
return $this->render('testajax', ['model' => $model]);
}
Out of the three <div class="invalid-feedback">Demo cannot be blank.</div>, only one is shown, the other two maintain the style .invalid-feedback {display: none;}.
The $form->errorSummary($model):
after the validation is performed, returns this:
<div style="display:none">
<p>Please fix the following errors:</p>
<ul></ul>
</div>
after the form is submitted, returns this:
<div class="alert alert-danger" style="">
<p>Please fix the following errors:</p>
<ul>
<li>Demo cannot be blank.</li>
<li>Demo cannot be blank.</li>
<li>Demo cannot be blank.</li>
</ul>
</div>
I did tested out $form->errorSummary(); and it does shows the desired output, but in the form of:
Please fix the following errors:
Please enter Username.
Like an option, you can do it this way:
<?php $form = ActiveForm::begin([
'id' => 'test-form',
'options' => ['class' => 'form-horizontal'],
'enableAjaxValidation' => true,
'enableClientValidation' => true,
]); ?>
<div class="form-group col-md-3">
<div class="error-block text-center">
<?php
$error = $form->field($model, 'username');
$error->template = '{error}';
echo $error;
?>
</div>
<?php
$username = $form->field($model, 'username');
$username->template = "{input}";
echo $username->textInput(['autofocus' => true]);
?>
</div>
<?php ActiveForm::end() ?>
The output will be right above the form field will be the response with:
Please enter Username

Yii2 success modal window

In view I have a form:
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'name')->textInput(['maxlength' => true, 'placeholder' => 'Name'])->label(false) ?>
<?= $form->field($model, 'phone')->textInput(['maxlength' => true, 'placeholder' => 'Phone'])->label(false) ?>
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
<?php ActiveForm::end(); ?>
Controller is:
if ($model->load(Yii::$app->request->post()) && $model->save()) {
\Yii::$app->session->setFlash('success', 'Created');
}
return $this->redirect(Yii::$app->request->referrer);
Then in view I put a modal:
<?php if (Yii::$app->session->hasFlash('success')) :?>
<!-- <div class="container">
<?= Yii::$app->session->getFlash('success', null, true) ?>
</div> -->
<div class="modal hide fade" id="myModal">
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h3>Modal header</h3>
</div>
<div class="modal-body">
<p><?= Yii::$app->session->getFlash('success', null, true) ?></p>
</div>
<div class="modal-footer">
Close
Save changes
</div>
</div>
<?php endif ;?>
And JS code is:
$(window).load(function(){
$('#myModal').modal('show');
});
I want to open success modal window after clicking submit button. But now nothing happens. Just reloads the page. How to do that I want? And please explain how to do that without reloading the page.
This might be no the best decidion, but i use class myAjaxModalClass and a simple js code, that submit all form with that class via ajax and parse json result:
{result:0, data:'new modal content'}
That allows me to load form with validation erros without page reloading. Also you may add your result status to submit redirect. Expample:
{result: 2, url:'http://yoursite.net'}

Onchange in dropdown rendering partial a dynamic form yii2 using ajax

i have a create form, Which posts value to actionCreate() like
Form - dropdown
Dynamic form depending on the dropdown above
<?php $form = ActiveForm::begin(['id' => 'dynamic-form']);?>
<?=
$form->field($model, 'techpark_id')->dropDownList($techparks, ['prompt' => '- Choose a Techpark -',
'onchange' => '
$.get( "' . Yii::$app->urlManager->createUrl('campaign-request/techpark-details?id=') . '"+$(this).val(), function( data ) {
$( "#details" ).html( data );
});
']);
?>
<div id="details">
</div>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
Now the onchange event in the dropdown -> techpark_id will post id to campaign-request/teckpark-details
Yii::$app->urlManager->createUrl('campaign-request/techpark-details?id=7)
This actionTechparkDetails will renderPartial like this with values to dropdown list depending upon the value $id
public function actionTechparkDetails($id) {
$details = [new \app\models\CampaignRequestAdDetails];
$connection = Yii::$app->getDb();
$command = $connection->createCommand('
SELECT adspace_type_id,type,number_of_adspace,number_of_filled,adspace_value FROM `Techpark`
JOIN techpark_adspace ON techpark.id = techpark_id
JOIN adspace_type ON adspace_type_id = adspace_type.id
WHERE techpark.id=:id', [':id' => $id]);
$result = $command->queryAll();
$adspace_type_id = ArrayHelper::map($result, 'adspace_type_id', 'type');
return $this->renderAjax('_campaignDetails', [
'details' => (empty($details)) ? [new \app\models\CampaignRequestAdDetails] : $details,
'adspace_type_id' => $adspace_type_id
]);
}
campaignDetails has a dynamic form which populates the value depending on the selected dropdown() value ($id)
My _campaignDetails.php
<?php $form = ActiveForm::begin(['id' => 'dynamic-form']);?>
<div class="panel panel-default">
<div class="panel-heading"><h4><i class="glyphicon glyphicon-envelope"></i> Campaign details</h4></div>
<div class="panel-body">
<?php
DynamicFormWidget::begin([
'widgetContainer' => 'dynamicform_wrapper', // required: only alphanumeric characters plus "_" [A-Za-z0-9_]
'widgetBody' => '.container-items', // required: css class selector
'widgetItem' => '.item', // required: css class
'limit' => 20, // the maximum times, an element can be cloned (default 999)
'min' => 4, // 0 or 1 (default 1)
'insertButton' => '.add-item', // css class
'deleteButton' => '.remove-item', // css class
'model' => $details[0],
'formId' => 'dynamic-form',
'formFields' => [
'adspace_type_id',
'number_of_adspace',
],
]);
?>
<div class="container-items"><!-- widgetContainer -->
<?php foreach ($details as $i => $detail): ?>
<div class="item panel panel-default"><!-- widgetBody -->
<div class="panel-heading">
<div class="pull-right">
<button type="button" class="add-item btn btn-success btn-xs"><i class="glyphicon glyphicon-plus"></i></button>
<button type="button" class="remove-item btn btn-danger btn-xs"><i class="glyphicon glyphicon-minus"></i></button>
</div>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<?php
// necessary for update action.
if (!$detail->isNewRecord) {
echo Html::activeHiddenInput($detail, "[{$i}]id");
}
?>
<div class="row">
<div class="col-sm-4">
<?= $form->field($detail, "[{$i}]adspace_type_id")->dropDownList($adspace_type_id) ?>
</div>
<div class="col-sm-4">
<?= $form->field($detail, "[{$i}]number_of_adspace")->textInput() ?>
</div>
</div><!-- .row -->
</div>
</div>
<?php endforeach; ?>
</div>
<?php DynamicFormWidget::end(); ?>
</div>
Now when i fill up the form and submit, i am unable to get the values of form (_campaignDetails.php which was rendered partially), inside actionCreate().
And also the remove item is not working in the dynamic form. Which would perfectly working if rendered inside the same form(i have another form which works fine with add/remove item of dynamic form).
I am using widget to dynamic form github.com/wbraganca/yii2-dynamicform
OR tell me how can i achieve the above scenario in any other format/manner using differnt approach. If you donot get what i want to achieve is
Depending on a dropdown value, i want a dynamic form which collects input with respect to value selected.
Thanks

ajax calling another ajax in yii

I can access the registration form which appears in a model window via ajax on any page as coded in the menu layout .
I need some thing on click of submit button of registration form it should get display a thank you message which is also via ajaxin the same div as that of wherein the registration form appears
registratiincontrooler
if ($model->save()) {echo "thank you for registration";return; }
registration view
<?php
/* #var $this UserProfileController */
/* #var $model UserProfile */
$this->breadcrumbs=array(
'User Profiles'=>array('index'),
'Create',
);
?>
<div id="ajax101" >
<div class="form" >
<?php $form=$this->beginWidget('UActiveForm', array(
'id'=>'registration-form',
'enableAjaxValidation'=>true,
'disableAjaxValidationAttributes'=>array('RegistrationForm_verifyCode'),
'clientOptions'=>array(
'validateOnSubmit'=>true,
),
'htmlOptions' => array('enctype'=>'multipart/form-data'),
)); ?>
<p class="note"><?php echo UserModule::t('Fields with <span class="required">*</span> are required.'); ?></p>
<?php echo $form->errorSummary(array($model/*,$profile*/)); ?>
<div class="row">
<div class="rlabel">
<?php echo $form->labelEx($model,'username', array("style"=>"display:inline")); ?>
</div>
<div class="rtextfield">
<?php echo $form->textField($model,'username', array("style"=>"margin-left:43px")); ?>
</div>
<div class="rerror">
<?php echo $form->error($model,'username', array("style"=>"margin-left:113px")); ?>
</div>
</div>
<div class="row">
<?php echo $form->labelEx($model,'password', array("style"=>"display:inline")); ?>
<?php echo $form->passwordField($model,'password', array("style"=>"margin-left:43px")); ?>
<?php echo $form->error($model,'password', array("style"=>"margin-left:113px")); ?>
<p class="hint">
<?php echo UserModule::t("Minimal password length 4 symbols."); ?>
</p>
</div>
<div class="row">
<?php echo $form->labelEx($model,'verifyPassword', array("style"=>"display:inline")); ?>
<?php echo $form->passwordField($model,'verifyPassword'); ?>
<?php echo $form->error($model,'verifyPassword', array("style"=>"margin-left:113px")); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'email', array("style"=>"display:inline")); ?>
<?php echo $form->textField($model,'email', array("style"=>"margin-left:65px")); ?>
<?php echo $form->error($model,'email', array("style"=>"margin-left:113px")); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'user_type', array("style"=>"display:inline")); ?>
<?php echo $form->dropDownList($model,'user_type',$model->getUType()); ?>
<?php echo $form->error($model,'user_type', array("style"=>"margin-left:113px")); ?>
</div>
<?php if (UserModule::doCaptcha('registration')): ?>
<div class="row">
<?php echo $form->labelEx($model,'verifyCode'); ?>
<?php $this->widget('CCaptcha'); ?>
<?php echo $form->textField($model,'verifyCode'); ?>
<?php echo $form->error($model,'verifyCode'); ?>
<p class="hint"><?php echo UserModule::t("Please enter the letters as they are shown in the image above."); ?>
<br/><?php echo UserModule::t("Letters are not case-sensitive."); ?></p>
</div>
<?php endif; ?>
<div class="row submit">
<?php echo CHtml::ajaxSubmitButton(UserModule::t("Register"),array('/user/register'),array('update'=>'#ajax101')); ?>//div for form
</div>
<?php $this->endWidget(); ?>
</div>
</div><!-- form -->
<?php endif; ?>
I think the problem exists here
<?php echo CHtml::ajaxSubmitButton(UserModule::t("Register"),array('/user/register'),array('update'=>'form')); ?>//div for form
</div>
example if I have 3 menu items
home
aboutus
contact
suppose visited home when I click on register a model window with registration form appears and when i click on submit button model->save as well make another call using ajax to update that model window with thank you message
similarly with other items in menu
whats happening is it saves and redirects to /user/registration with thank you but i need same model window and not to be updated with thank message and not redirected thank message
I did try this but it did not save
<?php echo CHtml::ajaxSubmitButton(UserModule::t("Register"),'',array('update'=>'form-content')); ?>
I am calling ajax within ajax .
try with
<?php
echo CHtml::ajaxSubmitButton(signup , CHtml::normalizeUrl(array('<controller>/<action>', 'render' => true)), array(
'dataType' => 'json',
'type' => 'post',
'success' => 'function(data) {
}',
'beforeSend' => 'function(){
}','complete' => 'function(){
}',
), array('id' => 'signup', 'class' => ''));
?>
The problem is in your controller, you have to stop Yii, return; alone won't cut it.
if ($model->save()) {
if($this->isAjaxRequest)
{
ehco 'thank you for registration';
Yii::app()->end(); // to stop yii
}
else
{
// probably redirect
}
}

CActiveForm ajax validation error not displaying in the form

I have created a form using CActiveForm in yii. I am using ajax to submit the form using CHtml::ajaxSubmitButton. Form submission using ajax is working correctly and I am able to get the values in the control using $_POST['modelname']['fieldname']. But the ajax form validation is not working correctly. Below is the code
<?php
$form=$this->beginWidget('CActiveForm', array(
'id'=>'item-brand-form',
'enableAjaxValidation' => true,
'clientOptions'=>array(
'validateOnSubmit'=>true,
),
'htmlOptions'=>array(
'class'=>'form-horizontal',
),
)); ?>
<div class="form-group">
<?php echo $form->labelEx($model,'Brand Name',array('class'=>'control-label col-lg-4','for'=>'ItemBrand_brand_name')); ?>
<div class="col-lg-6">
<?php echo $form->textField($model,'brand_name',array('class'=>'form-control')); ?>
<?php echo $form->error($model,'brand_name'); ?>
</div>
<!-- End col-lg-6 -->
</div><!-- End Form Group -->
<div class="form-group">
<?php echo $form->labelEx($model,'Brand Code',array('class'=>'control-label col-lg-4','for'=>'ItemBrand_brand_code')); ?>
<div class="col-lg-6">
<?php echo $form->textField($model,'brand_code',array('class'=>'form-control')); ?>
</div>
<!-- End col-lg-6 -->
</div><!-- End Form Group -->
<div class="form-group">
<div class="col-lg-4"></div>
<div class="col-lg-2">
<?php echo CHtml::ajaxSubmitButton('Apply',array('class'=>'btn btn-lg btn-primary')); ?>
</div>
</div>
<?php $this->endWidget(); ?>
Also in the controller action following code is not working.
if(isset($_POST['ajax']) && $_POST['ajax']==='item-brand-form')
{
echo CActiveForm::validate($model);
Yii::app()->end();
}
so instead I am using
if(Yii::app()->getRequest()->getIsAjaxRequest())
{
echo CActiveForm::validate( array( $model));
Yii::app()->end();
}
While checking in the browser I am getting the response
{"ItemBrand_brand_name":["Brand Name cannot be blank."]}
But the error message is not displaying in the form. Also why the $_POST['ajax'] is not working ? Please help.
Thanks in advance.
I have solved this by using CHtml::submitButton instead of CHtml::ajaxSubmitButton and then submitting the form using jQuery $.ajax function in the form 'afterValidate' option. Please see the details here

Resources