Reputation: 672
I'm learning Yii2 by trying to make a project using it.
I've got a form with some lists. I would like to implement a function of adding new list options on the go.
Currently clicking "Add new option" button calls pop-up form. After submiting it Yii takes me to this new option's page. Here's why:
public function actionCreate()
{
$model = new Request();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
'manager' => Stuff::find()->all(),
'movercompany' => MoverCompany::find()->all(),
'worktype' => Worktype::find()->all(),
'customer' => Customer::find()->all(),
]);
}
}
What I want after submittimg is only to refresh updated list and select new option.
How can I do this?
_form.php:
<?php
use yii\helpers\Html;
use yii\helpers\ArrayHelper;
use yii\helpers\Url;
use yii\widgets\ActiveForm;
use kartik\select2\Select2;
use yii\bootstrap\Modal;
/* @var $this yii\web\View */
/* @var $model app\models\Request */
/* @var $form yii\widgets\ActiveForm */
?>
<div class="request-form">
<?php
$form = ActiveForm::begin();
date_default_timezone_set("Europe/Moscow");
$model->request_date = date('Y-m-d');
$model->request_time = date('H:i');
?>
<?= $form->field($model, 'request_date')->widget(\yii\jui\DatePicker::classname(), [
'language' => 'ru',
'dateFormat' => 'yyyy-MM-dd',
]) ?>
<?= $form->field($model, 'request_time')->textInput(['style' => 'width: 70px;']) ?>
<?= $form->field($model, 'customer_id')->widget(Select2::classname(), [
'data' => ArrayHelper::map($customer, 'id', 'fullInfo'),
'language' => 'ru',
'options' => ['placeholder' => 'Выбрать клиента...'],
'pluginOptions' => [
'allowClear' => true
],
]);?>
<?= $form->field($model, 'KP_id')->textInput() ?>
<?= $form->field($model, 'quantity')->input('number', ['style' => 'width: 75px;']) ?>
<div>
<?= $form->field($model, 'request_type')->dropDownList(
ArrayHelper::map($worktype, 'id', 'title'),
array('prompt' => 'Выберите вид работ:', 'style' => 'width: 200px;')
) ?>
<?= Html::button('+', ['value' => Url::to('index.php?r=worktype/create'), 'class' => 'btn btn-success', 'id' => 'modalButton']) ?>
</div>
<?php
Modal::begin([
'header' => '<h4>Виды работ</h4>',
'id' => 'modal',
'size' => 'modal-lg',
]);
echo "<div id='modalContent'></div>";
Modal::end();
?>
<?= $form->field($model, 'payment_type')->dropDownList(
[
'0' => 'Нал',
'1' => 'Безнал'
],
['style' => 'width: 80px;'])
?>
<?= $form->field($model, 'address')->textarea(['rows' => 2]) ?>
<?= $form->field($model, 'minimal_payment')->input('number', ['style' => 'width: 100px;']) ?>
<?= $form->field($model, 'mover_company_id')->dropDownList(
ArrayHelper::map($movercompany, 'id', 'name'),
array('prompt' => 'Выберите компанию:', 'style' => 'width: 200px;')
) ?>
<?= $form->field($model, 'manager_id')->dropDownList(
ArrayHelper::map($manager, 'id', 'name'),
array('prompt' => 'Выберите менеджера:', 'style' => 'width: 200px;')
) ?>
<?= $form->field($model, 'workers_number')->input('number', ['style' => 'width: 100px;']) ?>
<?= $form->field($model, 'workhours')->input('number', ['style' => 'width: 100px;']) ?>
<?= $form->field($model, 'payment_additional')->input('number', ['style' => 'width: 100px;']) ?>
<?= $form->field($model, 'payment_car')->input('number', ['style' => 'width: 100px;']) ?>
<?= $form->field($model, 'payment_sum')->input('number', ['style' => 'width: 100px;']) ?>
<?= $form->field($model, 'status')->dropDownList(
[
'0' => 'Открыт',
'1' => 'Закрыт'
],
['style' => 'width: 200px;']
) ?>
<?= $form->field($model, 'comment')->textarea(['rows' => 2]) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Создать' : 'Обновить', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
Upvotes: 4
Views: 1977
Reputation: 672
I've implemented this using next techniques.
I needed to dynamically add an option to Company List on Request Form page.
So firstly we create new action in Company Controller. It differs form actionCreate by renderAjax instead of render and returns 1 instead of taking you to new company page:
public function actionAdd() { $model = new Company();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
echo 1;
} else {
return $this->renderAjax('create', [
'model' => $model,
]);
};
}
Add button to the _form.php of the view that contains company list:
Url::to('index.php?r=company/add'), 'class' => 'btn btn-success', 'id' => 'modalButton']) ?>Add pop-up window that would contain form for creating new company.
3.1. Modal window in _form.php:
use yii\bootstrap\Modal;
use yii\widgets\Pjax;
<?php
Modal::begin([
'header' => '<h4>Company<h4>',
'id' => 'modal',
'size' => 'modal-lg',
]);
echo "<div id='modalContent'></div>";
Modal::end();
?>
3.2. Apply pjax to the company list:
<?php Pjax::begin(['id' => 'companyList']); ?>
...
<?php Pjax::end(); ?>
3.3. Edit assets/AppAsset.php:
public $js = [
'js/main.js'
];
3.4. Create folder and js file web/js/main.js:
$(function(){
$('#modalButton').click(function(){
$('#modal').modal('show')
.find('#modalContent')
.load($(this).attr('value'));
});
});
3.5. Add script to company view _form.php:
<?php
$script = <<< JS
$('form#{$model->formName()}').on('beforeSubmit', function(e)
{
var \$form = $(this);
$.post(
\$form.attr("action"), // serialize yii2 form
\$form.serialize()
)
.done(function(result) {
if(result == 1)
{
$(document).find('#modal').modal('hide');
$.pjax.reload({container:'#companyList'});
$(document).on('pjax:complete', function() {
$('#customer-company_id option:last-child').attr('selected', true);
})
}else
{
$(\$form).trigger("reset");
$("#message").html(result.message);
}
}).fail(function()
{
console.log("server error");
});
return false;
});
JS;
$this->registerJs($script);
?>
Here's what we have: pressing Add button pops-up a form with new option attributes. Submitting this form closes pop-up window, refreshes company list and selects new option which is the last one. Pretty rude, but it works.
Upvotes: 1