Validation in checkbox form in yii2 - php

I have two models in a form.
One model is a master, and one model is representated as junction table (model).
Desc :
request_table : $model,
link_req_tipe : $modelLinkReqTipe;
My goal is,
I save the $model, then I get the $model->id
I batch insert to link_req_item
id_request = $model->id and id_tipe = modelLinkReqTipe->id_tipe
Here it is the php :
_form.php (just example, because a lot of many input form)
<?= $form->field($model, 'karyawan_id')->dropDownList(
ArrayHelper::map(Karyawan::find()->all(), 'id', 'first_name'), ['prompt' => 'Select Karyawan'])
?>
<?= $form->field($modelLinkReqTipe, 'id_tipe')->checkBoxList(ArrayHelper::map(TipeRequest::find()->all(), 'id', 'nama_tipe'));
?>
RequestController
if ($model->load($request->post()) && $modelLinkReqTipe->load(Yii::$app->request->post())) {
$valid = $model->validate();
$valid = $modelLinkReqTipe->validate() && $valid;
if ($valid) { ## Check validate : true
$transaction = Yii::$app->db->beginTransaction();
try {
if ($flag = $model->save(false)) {
foreach ($modelLinkReqTipe as $index => $modelLinkReqTipe ) {
if ($flag === false) {
break;
}
$modelLinkReqTipe->id_request = $model->id;
if (!($flag = $modelLinkReqTipe->save(false))) {
break;
}
}
}
if ($flag) {
$transaction->commit();
} else {
$transaction->rollBack()
}
}
catch (\Exception $e) {
$transaction->rollBack();
}
return [
'forceReload' => '#crud-datatable-pjax',
'title' => "Create new Request",
'content' => '<h1 class="text-success">Success</h1>,
'footer' => Html::button('Close', ['class' => 'btn btn-default pull-left', 'data-dismiss' => "modal"]) .
Html::a('Create More', ['create'], ['class' => 'btn btn-primary', 'role' => 'modal-remote'])
];
}else{ ## Check validate : false
return [
'title' => "Create New Request",
'content' => $this->renderAjax('create', [
'model' => $model,
'modelLinkReqTipe' => (empty($modelLinkReqTipe)) ? new LinkReqTipe() : $modelLinkReqTipe,
'modelLinkReqItem' => (empty($modelLinkReqItem)) ? [new LinkReqItem] : $modelLinkReqItem,
]),
'footer' => Html::button('Close', ['class' => 'btn btn-default pull-left', 'data-dismiss' => "modal"]) .
Html::button('Save', ['class' => 'btn btn-primary', 'type' => "submit"])
];
}
Now, validation is in trouble,
it always return false in submit.
Please Advise.

There are many ways to resolve this issue. I think the best way to make sure that $modelLinkReqTipe's attribute id_request is not taken into account upon validation is to provide validate() function with array of attributes you want to validate: validate(['id_tipe'])

Related

Yii2 Implode beforeSave is not working

Basically, I have a model that I display to standard checkboxlist that have a value :
I got this from my model
echo $model->bundle_numbers;
Array
(
[0] => 1
[1] => 2
[2] => 3
)
So, In controller,
if ($model->load($request->post()) && $model->save()) {
return [
'forceReload' => '#crud-datatable-pjax',
'title' => "Create new OutgoingPipe",
'content' => '<span class="text-success">Create Outgoing Pipe success</span>',
'footer' => Html::button('Close', ['class' => 'btn btn-default pull-left', 'data-dismiss' => "modal"]) .
Html::a('Create More', ['create'], ['class' => 'btn btn-primary', 'role' => 'modal-remote'])
];
}
Now I wnat to change the array into string format :
So, use beforeSave :
public function beforeSave($insert){
$this->bundle_numbers = implode(",", $this->bundle_numbers);
return parent::beforeSave($insert); // TODO: Change the autogenerated stub
}
In rules, based Gii generator model, I remove string rules
[['bundle_numbers'], 'string', //deleted
But still not success to insert the data.
No errors displayed.
Please advise.
** update **
I can see all errors,
$model->save(false);
$model->getErrors();
Now, I can see, I have a lot of errors in another rule.
By the way, thanks for the help.
public function beforeSave($insert){
if (parent::beforeSave($insert)) {
$this->bundle_numbers = implode(",", $this->bundle_numbers);
return $this->bundle_numbers;
} else {
return false;
}
}
try this
Try if you have some error in load or validate
if ($model->load($request->post()) {
if ($model->save()){
return [
'forceReload' => '#crud-datatable-pjax',
'title' => "Create new OutgoingPipe",
'content' => '<span class="text-success">Create Outgoing Pipe success</span>',
'footer' => Html::button('Close', ['class' => 'btn btn-default pull-left', 'data-dismiss' => "modal"]) .
Html::a('Create More', ['create'], ['class' => 'btn btn-primary', 'role' => 'modal-remote'])
];
} else {
var_dump('save fail');
var_dump( $model->errors);
}
do like this
<?php
if ($model->load($request->post()) {
$model->bundle_numbers = implode(",", $model->bundle_numbers);
$model->save();
return //wherever you want return
}

Yii2 custom client validation with ajax rendering in modal

I have a model with a custom validation method. For testing it always returns an error message.
public function rules()
{
return [
...
['staff_ids', 'each', 'rule' => ['string']],
[['staff_ids'], 'validateStaffIds'],
...
];
}
public function validateStaffIds($attribute, $params, $validator) {
$this->addError($attribute, 'There is an error in the staff ids');
}
In the view.php is the modal element
<p>
<?= Html::button('Add Ensemble Staff',
['value' => Url::to(['ensemble/add', 'id' => $model->id]),
'title' => 'Adding New Ensemble Staff',
'class' => 'showModalButton btn btn-primary']);
?>
</p>
<?php
Modal::begin([
'closeButton' => [
'label' => 'x',
],
'headerOptions' => ['id' => 'modalHeader'],
'id' => 'modal',
'size' => 'modal-lg',
]);
echo "<div id='modalContent'></div>";
Modal::end();
?>
The js code which fires everything up...
$(function(){
$(document).on('click', '.showModalButton', function(){
if ($('#modal').data('bs.modal').isShown) {
$('#modal').find('#modalContent')
.load($(this).attr('value'));
} else {
//if modal isn't open; open it and load content
$('#modal').modal('show')
.find('#modalContent')
.load($(this).attr('value'));
}
//dynamiclly set the header for the modal
...
});
});
And the ensemble controller which handles the add action
public function actionAdd($id)
{
$model = $this->findModel($id);
// in the post ( 'ensembleStaff_ids' => [0 => '2']); where the id actually is staff_id
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $id]);
} else {
return $this->renderAjax('add', [
'model' => $model,
]);
}
}
And the form which is injected by the js into the model (Url::to(['ensemble/add', 'id' => $model->id]), )
<?php $form = ActiveForm::begin(['id' => 'add-theater-stuff-form']); ?>
<?= $form->field($model, 'staff_ids')->widget(Select2::className(), [
'model' => $model,
'data' => ArrayHelper::map(app\models\TheaterStaff::find()->where(['theater_id' => $model->theater_id])->all(), 'staff_id', 'staff.fullname'),
'options' => [
'multiple' => true,
'prompt' => 'Ensemble Staff',
],
'pluginOptions' => [
'tags' => true
]
]); ?>
<div class="form-group">
<?= Html::submitButton('Add', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
Clicking on the Add Ensemble Staff Button works fine and brings up the modal window. The form itself works fine so far; also the default validation works. Even the custom validation is called, but return $this->renderAjax(...) isn't load in the modal window anymore; it is separately.
A picture showing the modal loaded, the result after submit and a modal with default validation.
I found a similar problem here. But adding an id to the form, doesn't solve the problem. So how to get the default validation showing up properly in the modal window? Does anyone have a clue?
Solution
Thanks for the response. For me the solution was:
Enable ajax in the form
<?php $form = ActiveForm::begin(['id' => 'add-ensemble-stuff-form', 'enableAjaxValidation' => true]); ?>
And to add the following logic in the controller
public function actionAdd($id)
{
$model = $this->findModel($id);
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
} else {
// in the post ( 'ensembleStaff_ids' => [0 => '2']); where the id actually is staff_id
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $id]);
} else {
return $this->renderAjax('add', [
'model' => $model,
]);
}
}
}
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}else{/* your code */}
add this in controller use yii\web\Response

Filling the foreign key field in one form from another form of related models in yii2

I got two related tables(models) [Sub with primary key id] and [Case with foreign key sub_id]. I created Sub with id=4. I want to create data of Case model in view.php(form) of Sub model. I did a "Create Case" Button which refer to the actionCreate of Case model.
This is my "Create Case" button in sub/view.php:
<?= Html::a(Yii::t('app','Create Case'), ['/case/create', 'sub_id' => $model->id], ['class' => 'btn btn-primary']) ?>
It looks like in the
picture
This button referred me to the create form of Case model, where i should get the field sub_id = 4. Now my _form.php has
<?= $form->field($model, 'sub_id')->textInput() ?>
What should i change to get the automatically filled field sub_id with id of parent model?
UPDATE: I added relevant code from the appropriate view, controller files.
I didn't changed model files.
CaseController.php file looks like shown below
class CaseController extends Controller
{
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
public function actionIndex()
{
$searchModel = new CaseSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
public function actionCreate($sub_id)
{
$model = new Case();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
'parent' => $sub_id
]);
}
}
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
protected function findModel($id)
{
if (($model = Case::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}
sub/view.php file:
<?php
use yii\helpers\Html;
use yii\widgets\DetailView;
$this->title = $model->id . ": " . $model->fullname;
$this->params['breadcrumbs'][] = ['label' => Yii::t('app', 'Subs'), 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="sub-view">
<h3><?= Html::encode($this->title) ?></h3>
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'id',
'address_id',
'address.region.name',
[
'label' => 'address',
'value' => 'Street: ' . $model->address->street . ' House ' . $model->address->house . ' Flat ' . $model->address->flat
],
],
]) ?>
<p>
<?= Html::a(Yii::t('app', 'Create Case'), ['/case/create', 'sub_id'=>$model->id], ['class' => 'btn btn-success']) ?>
</p>
</div>
case/_form.php file:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
<div class="case-form">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'id')->textInput() ?>
<?php if($model->isNewRecord && isset($parent_id)) {
$model->sub_id = $parent_id;
} ?>
<?= $form->field($model, 'sub_id')->textInput(['readonly' => true, 'value' => $model->sub_id]) ?>
<?= $form->field($model, 'case_date')->textInput() ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? Yii::t('app', 'Create') : Yii::t('app', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
With lack of any further information, to the best of my understanding this is what you are asking -
Taking the example in your picture, if user clicks on Create Case button, then a new form (Create Case) will open. In that Create Case form, among other input fields, there is a field for sub_id and it should be populated by default with the value 4 (since in the picture the ID of the User Harry Potter is 4).
Based on the above you simply need to do the following -
In your action (within the CaseController) for create case, you pass the sub_id like below -
/* ** CaseController ** */
public function actionCreate($sub_id)
{
//....other code
return $this->render('create', ['model' => $model,'parent_id' => $sub_id]);
}
And then inside the _form.php where you are showing the Create Case form you simply do like this -
/* ** _form.php ** */
//... other code
//if you are using _form.php for Edit Form as well,
//this prevents the value from the DB being over-written
if($model->isNewRecord && isset($parent_id)) {
$model->sub_id = $parent_id;
}
<?= $form->field($model, 'sub_id')->textInput() ?>
//... other code
This should be enough to display the value passed from the parent form.

How can I get the selected data/item rows in CheckboxColumn Gridview - Yii2

I have a problem on getting all the selected values/data Yii2 Gridview using checkboxColumn.
I can only get one of the value in the grid using this code:
'class' => 'yii\grid\CheckboxColumn',
'checkboxOptions' => function($model, $key, $index, $widget) {
return ['value' => $model['item_id'] ];
},
Need some suggestions on how can I get all the values in the grid...
Here is my Code Code snippet Controller/View:
Controller:
public function actionBulk(){
$action=Yii::$app->request->post('action');
$selection=(array)Yii::$app->request->post('selection');
print_r($selection);
}
View:
<?=Html::beginForm(['transjournal/bulk'],'post');?>
<?=GridView::widget([
'dataProvider' => $dataProvider,
'bordered'=>true,
'striped'=>true,
'condensed'=>true,
'hover'=>true,
'export' => false,
'showOnEmpty' => false,
'panel'=>[
'after'=>Html::submitButton('<i class="glyphicon glyphicon-plus"></i> Posted', ['class' => 'btn btn-success']),
],
'columns' => [
[
'class' => 'yii\grid\CheckboxColumn',
'checkboxOptions' => function($model, $key, $index, $widget) {
return ['value' => $model['item_id'] ];
},
],
'item_id',
'description',
],
]);
?>
<?= Html::endForm();?>
Here is my attachment:
This is the GridView
This is the Result in the GridView (Selected Data only returns item_id)
How can I return both item_id and description?
Issue with your code 'checkboxOptions' =>, can you remove it?
<?=Html::beginForm(['controller/bulk'],'post');?>
<?=Html::dropDownList('action','',[''=>'Mark selected as: ','c'=>'Confirmed','nc'=>'No Confirmed'],['class'=>'dropdown',])?>
<?=Html::submitButton('Send', ['class' => 'btn btn-info',]);?>
<?=GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\CheckboxColumn'],
...
],
]); ?>
<?= Html::endForm();?>
In Controller:
public function actionBulk(){
$action=Yii::$app->request->post('action');
$selection=(array)Yii::$app->request->post('selection');//typecasting
foreach($selection as $id){
$model = Post::findOne((int)$id);//make a typecasting
//do your stuff
$model->save();
// or delete
}
}
basically, i am using yii's CheckboxColumn:
<?php
namespace common\grid;
class CheckboxColumn extends \yii\grid\CheckboxColumn {
public $headerOptions = ['class' => 'text-center', 'style' => 'width: 5em'];
public $contentOptions = ['class' => 'text-center'];
}
?>
then i wrote a jquery plugin for triggering operations with selected items, plus custom Actions and so on, here the relevant javascript code, where options.grid is the id/selector for your grid, e.g. '#grid':
var selection = [];
$(options.grid + ' input:checkbox[name="selection[]"]:checked').each(function() {
selection.push($(this).val());
});
so var selection contains an array with my item ids. length is:
selection.length

Uploading multiple files and saving them to DB using related model in Yii2

I'm learning Yii2 by making a project.
I have two models: Company and CompanyFile. I'm using both of them in one form to create a Company, to upload related files and save them in associated table.
The problem is that the Company is being created but without uploading files and creating rows in associated table.
Here's the piece of Company Controller:
public function actionCreate()
{
$model = new Company();
$file = new CompanyFile();
if ($model->load(Yii::$app->request->post()) && $file->load(Yii::$app->request->post())) {
$model->save();
$attachments = UploadedFile::getInstances($file, 'attachment[]');
foreach($attachments as $a){
if ($a->upload()){
$file->company_id = $model->id;
$file->attachment = $a;
$file->save();
}
else {
return $this->render('create', [
'model' => $model,
'file' => $file,
]);
}
}
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
'file' => $file,
]);
}
}
Here's the piece of CompanyFile model:
public function upload()
{
if ($this->validate()){
$nameToSave = 'uploads/' . $this->attachment->baseName . '.' . $this->attachment->extension;
$this->attachment->saveAs($nameToSave);
return $nameToSave;
}
else {
return false;
}
}
Here's the views/company/_form.php:
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
<?= $form->field($model, 'name')->textarea(['rows' => 1, 'style' => 'width: 400px;']) ?>
<?= $form->field($file, 'attachment[]')->fileInput(['multiple' => true]) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
After submitting form I'm redirected to newly created company page. No files uploaded. What may be wrong? I couldn't find any info about correct way of saving multiple files to another table in Yii2.
It needed to be
$attachments = UploadedFile::getInstances($file, 'attachment');
'attachment' without brackets.

Categories