Can't delete selected image when update the form by using Yii kartik fileinput - yii2

I refer to this link https://github.com/jaradsee/faktharm/blob/master/controllers/PhotoLibraryController.php
to upload multiple images but when I try to delete the selected image in update form it showing me these error
(image1)
(image2)
For image 2, why the url link always give products%252Fdeletefile-ajax (give number 25)
Below is my code, please help me to check what's goes wrong, thank you!
Uploads.php
class Uploads extends \yii\db\ActiveRecord
{
/**
* {#inheritdoc}
*/
public static function tableName()
{
return 'uploads';
}
/**
* {#inheritdoc}
*/
public function rules()
{
return [
[['file_name'], 'required'],
[['upload_id'], 'integer'],
[['create_date'], 'safe'],
[['ref'], 'string', 'max' => 100],
[['file_name', 'real_filename'], 'string', 'max' => 150],
];
}
/**
* {#inheritdoc}
*/
public function attributeLabels()
{
return [
'upload_id' => 'Upload ID',
'ref' => 'Ref',
'file_name' => 'File Name',
'real_filename' => 'Real Filename',
'create_date' => 'Create Date',
];
}
}
Products.php
class Products extends \yii\db\ActiveRecord
{
/**
* {#inheritdoc}
*/
//public $file;
const UPLOAD_FOLDER='products';
public static function tableName()
{
return 'products';
}
/**
* {#inheritdoc}
*/
public function rules()
{
return [
[['productName', 'productDescription', 'productPrice', 'categoryId', 'brandId', 'productStatus'], 'required'],
[['productDescription', 'productStatus'], 'string'],
[['productPrice'], 'number'],
[['categoryId', 'brandId'], 'integer'],
[['productName','ref'], 'string', 'max' => 100],
[['brandId'], 'exist', 'skipOnError' => true, 'targetClass' => Brands::className(), 'targetAttribute' => ['brandId' => 'brandId']],
[['categoryId'], 'exist', 'skipOnError' => true, 'targetClass' => Categorys::className(), 'targetAttribute' => ['categoryId' => 'categoryId']],
[['ref'],'unique']
// ['productImage', 'file','maxFiles'=>5],
//[['file'],'productImage']
];
}
/**
* {#inheritdoc}
*/
public function attributeLabels()
{
return [
'productId' => 'Product ID',
'productName' => 'Product Name',
'productDescription' => 'Product Description',
'productPrice' => 'Product Price',
'ref' => 'Product Image',
'categoryId' => 'Category',
'brandId' => 'Brand',
'productStatus' => 'Product Status',
];
}
/**
* Gets query for [[Brand]].
*
* #return \yii\db\ActiveQuery
*/
public function getBrand()
{
return $this->hasOne(Brands::className(), ['brandId' => 'brandId']);
}
/**
* Gets query for [[Category]].
*
* #return \yii\db\ActiveQuery
*/
public function getCategory()
{
return $this->hasOne(Categorys::className(), ['categoryId' => 'categoryId']);
}
public function getImages()
{
return $this->hasMany(Images::className(), ['productId' => 'productId']);
}
public static function getUploadPath(){
return Yii::getAlias('#webroot').'/'.self::UPLOAD_FOLDER.'/';
}
public static function getUploadUrl(){
return Url::base(true).'/'.self::UPLOAD_FOLDER.'/';
}
public function getThumbnails($ref,$event_name){
$uploadFiles = Uploads::find()->where(['ref'=>$ref])->all();
$preview = [];
foreach ($uploadFiles as $file) {
$preview[] = [
'url'=>self::getUploadUrl(true).$ref.'/'.$file->real_filename,
'src'=>self::getUploadUrl(true).$ref.'/thumbnail/'.$file->real_filename,
'options' => ['title' => $event_name]
];
}
return $preview;
}
}
ProductsController.php
namespace backend\controllers;
use Yii;
use backend\models\Products;
use backend\models\Uploads;
use backend\models\ProductsSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
use yii\helpers\Json;
use yii\widgets\ActiveForm;
use yii\web\UploadedFile;
use yii\helpers\Url;
use yii\helpers\html;
use yii\helpers\BaseFileHelper;
use yii\helpers\ArrayHelper;
/**
* ProductsController implements the CRUD actions for Products model.
*/
class ProductsController extends Controller
{
/**
* {#inheritdoc}
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
// 'access' => [
// 'class' => AccessControl::className(),
// 'rules' => [
// [
// 'actions' => ['view','update','_form','index','_search','create','uploadAjax','createDir'],
// 'allow' => true,
// 'roles' => ['admin'],
// ],
// ],
// ],
];
}
/**
* Lists all Products models.
* #return mixed
*/
public function actionIndex($pageSize = 10)
{
$searchModel = new ProductsSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams, $pageSize);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'pageSize' => $pageSize,
]);
}
/**
* Displays a single Products model.
* #param integer $id
* #return mixed
* #throws NotFoundHttpException if the model cannot be found
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Products model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
/*public function actionCreate()
{
$model = new Products();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
$model->imageFiles = UploadedFile::getInstances($model, 'productImage');
return $this->redirect(['view', 'id' => $model->productId]);
}
return $this->render('create', [
'model' => $model,
]);
}*/
public function actionCreate()
{
$model = new Products();
if ($model->load(Yii::$app->request->post())) {
$this->Uploads(false);
if($model->save()){
return $this->redirect(['view', 'id' => $model->productId]);
}
}
else{
$model->ref = substr(Yii::$app->getSecurity()->generateRandomString(),10);
}
return $this->render('create', [
'model' => $model,
]);
}
/**
* Updates an existing Products model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param integer $id
* #return mixed
* #throws NotFoundHttpException if the model cannot be found
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
list($initialPreview,$initialPreviewConfig) = $this->getInitialPreview($model->ref);
if ($model->load(Yii::$app->request->post())) {
$this->Uploads(false);
if($model->save()){
return $this->redirect(['view', 'id' => $model->productId]);
}
}
return $this->render('update', [
'model' => $model,
'initialPreview'=>$initialPreview,
'initialPreviewConfig'=>$initialPreviewConfig
]);
}
/**
* Deletes an existing Products model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param integer $id
* #return mixed
* #throws NotFoundHttpException if the model cannot be found
*/
public function actionDelete($id)
{
//$model = new Products();
//$this->findModel($id)->delete();
$model->$this->findModel($id);
$this->removeUploadDir($model->ref);
Uploads::deleteAll(['ref'=>$model->ref]);
$model->delete();
return $this->redirect(['index']);
}
/**
* Finds the Products model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return Products the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Products::findOne($id)) !== null) {
return $model;
}
throw new NotFoundHttpException('The requested page does not exist.');
}
/*|*********************************************************************************|
|================================ Upload Ajax ====================================|
|*********************************************************************************|*/
public function actionUploadAjax(){
$this->Uploads(true);
}
private function CreateDir($folderName){
if($folderName != NULL){
$basePath = Products::getUploadPath();
if(BaseFileHelper::createDirectory($basePath.$folderName,0777)){
BaseFileHelper::createDirectory($basePath.$folderName.'/thumbnail',0777);
}
}
return;
}
private function removeUploadDir($dir){
BaseFileHelper::removeDirectory(Products::getUploadPath().$dir);
}
private function Uploads($isAjax=false) {
if (Yii::$app->request->isPost) {
$images = UploadedFile::getInstancesByName('upload_ajax');
if ($images) {
if($isAjax===true){
$ref =Yii::$app->request->post('ref');
}else{
$Products = Yii::$app->request->post('Products');
$ref = $Products['ref'];
}
$this->CreateDir($ref);
foreach ($images as $file){
$fileName = $file->baseName . '.' . $file->extension;
$realFileName = md5($file->baseName.time()) . '.' . $file->extension;
$savePath = Products::UPLOAD_FOLDER.'/'.$ref.'/'. $realFileName;
if($file->saveAs($savePath)){
if($this->isImage(Url::base(true).'/'.$savePath)){
$this->createThumbnail($ref,$realFileName);
}
$model = new Uploads;
$model->ref = $ref;
$model->file_name = $fileName;
$model->real_filename = $realFileName;
$model->save();
if($isAjax===true){
echo json_encode(['success' => 'true']);
}
}else{
if($isAjax===true){
echo json_encode(['success'=>'false','eror'=>$file->error]);
}
}
}
}
}
}
private function getInitialPreview($ref) {
$datas = Uploads::find()->where(['ref'=>$ref])->all();
$initialPreview = [];
$initialPreviewConfig = [];
foreach ($datas as $key => $value) {
array_push($initialPreview, $this->getTemplatePreview($value));
array_push($initialPreviewConfig, [
'caption'=> $value->file_name,
'width' => '120px',
'url' => Url::to(['/products/deletefile-ajax']),
'key' => $value->upload_id
]);
}
return [$initialPreview,$initialPreviewConfig];
}
public function isImage($filePath){
return #is_array(getimagesize($filePath)) ? true : false;
}
private function getTemplatePreview(Uploads $model){
$filePath = Products::getUploadUrl().$model->ref.'/thumbnail/'.$model->real_filename;
$isImage = $this->isImage($filePath);
if($isImage){
$file = Html::img($filePath,['class'=>'file-preview-image', 'alt'=>$model->file_name, 'title'=>$model->file_name]);
}else{
$file = "<div class='file-preview-other'> " .
"<h2><i class='glyphicon glyphicon-file'></i></h2>" .
"</div>";
}
return $file;
}
private function createThumbnail($folderName,$fileName,$width=250){
$uploadPath = Products::getUploadPath().'/'.$folderName.'/';
$file = $uploadPath.$fileName;
$image = Yii::$app->image->load($file);
$image->resize($width);
$image->save($uploadPath.'thumbnail/'.$fileName);
return;
}
public function actionDeletefileAjax(){
$model = Uploads::findOne(Yii::$app->request->post('key'));
if($model!==NULL){
$filename = Products::getUploadPath().$model->ref.'/'.$model->real_filename;
$thumbnail = Products::getUploadPath().$model->ref.'/thumbnail/'.$model->real_filename;
if($model->delete()){
#unlink($filename);
#unlink($thumbnail);
echo json_encode(['success'=>true]);
}else{
echo json_encode(['success'=>false]);
}
}else{
echo json_encode(['success'=>false]);
}
}
}
_form.php
<?php
//use kartik\file\FileInput;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use kartik\select2\Select2;
use yii\helpers\ArrayHelper;
use backend\models\Brands;
use backend\models\Categorys;
use yii\helpers\Url;
use kartik\file\FileInput;
/* #var $this yii\web\View */
/* #var $model backend\models\Products */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="photo-library-form">
<?php $form = ActiveForm::begin(['options'=>['enctype'=>'multipart/form-data']]); ?>
<?php $form->errorSummary($model) ?>
<?= $form->field($model, 'ref')->hiddenInput(['maxlength' => 100])->label(false); ?>
<?= $form->field($model, 'productName')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'productDescription')->textarea(['rows' => 6]) ?>
<?= $form->field($model, 'productPrice')->textInput() ?>
<?=
$form->field($model, 'brandId')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Brands::find()->where(['brandStatus'=>'active'])->all(),'brandId','brandName'),
'language' => 'en',
'options' => ['placeholder' => 'Select a brand ...'],
'pluginOptions' => [
'allowClear' => true
],
]);
?>
<?=
$form->field($model, 'categoryId')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Categorys::find()->where(['categoryStatus'=>'active'])->all(),'categoryId','categoryName'),
'language' => 'en',
'options' => ['placeholder' => 'Select a category ...'],
'pluginOptions' => [
'allowClear' => true
],
]);
?>
<?= $form->field($model, 'productStatus')->dropDownList([ 'active' => 'Active', 'inactive' => 'Inactive', ], ['prompt' => 'Status']) ?>
<div class="form-group field-upload_files">
<label class="control-label" for="upload_files[]"> Product Images </label>
<div>
<?=
FileInput::widget([
'name' => 'upload_ajax[]',
//'attribute'=>'productImage[]',
//'name'=>'productImage[]',
'options' => [
'multiple'=>true,
'accept' => 'image/*',
//'id'=>'imageId',
],
'pluginOptions' => [
'initialPreview'=> $initialPreview,
'initialPreviewConfig'=> $initialPreviewConfig,
'deleteUrl'=>Url::to(['/products/deletefile-ajax']),
'showPreview' => true,
'showCaption' => false,
'showRemove' => false,
'showUpload' => false,
'uploadAsync' => true,
'uploadUrl'=>Url::to(['/products/upload-ajax']),
'maxFileCount' => 5,
'allowedFileExtensions' => ['jpg', 'png','jpeg'],
'previewFileType' => ['jpg', 'png','jpeg'],
'overwriteInitial'=>false,
'uploadExtraData' => [
'ref'=>$model->ref
],
'msgUploadBegin' => Yii::t('app', 'Please wait, system is uploading the files'),
'validateInitailCount'=>true,
'layoutTemplates'=>[
'actionZoom'=>'<button type="button" class="kv-file-zoom">{zoomIcon}</button>',
'actionUpload'=>'',
//'actionDelete'=>'<a>jj</a>',
//'footer' => '<div class="file-thumbnail-footer"><div class="file-caption-name" style="width:{width}">{caption}{size}</div>
//{progress}{actions}',
//'footer' => '<div class="file-thumbnail-footer"> <div class="file-caption-caption" title="{caption}"</div>'
//'actionDelete'=>'<button type="button" class="kv-file-remove"> {dataKey}{deleteUrl} {removeIcon}</button>',
],
],
'pluginEvents' => [
'filebatchselected' => 'function(event, files) {
$(this).fileinput("/products/upload-ajax");
}',
],
]);
?>
<br>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord? 'Save': 'Update', ['class' => 'btn btn-primary']) ?>
<?= Html::a(Yii::t('app', 'Cancel'), ['index', 'id' => $model->productId], ['class'=>'btn btn-danger']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>

I found the solution my bad
need to change all the Url::to() in controller and _form
to this format solution

The detail answer as below
_form.php
<?php
//use kartik\file\FileInput;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use kartik\select2\Select2;
use yii\helpers\ArrayHelper;
use backend\models\Brands;
use backend\models\Categorys;
use yii\helpers\Url;
use kartik\file\FileInput;
/* #var $this yii\web\View */
/* #var $model backend\models\Products */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="photo-library-form">
<?php $form = ActiveForm::begin(['options'=>['enctype'=>'multipart/form-data']]); ?>
<?php $form->errorSummary($model) ?>
<?= $form->field($model, 'ref')->hiddenInput(['maxlength' => 100])->label(false); ?>
<?= $form->field($model, 'productName')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'productDescription')->textarea(['rows' => 6]) ?>
<?= $form->field($model, 'productPrice')->textInput() ?>
<?=
$form->field($model, 'brandId')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Brands::find()->where(['brandStatus'=>'active'])->all(),'brandId','brandName'),
'language' => 'en',
'options' => ['placeholder' => 'Select a brand ...'],
'pluginOptions' => [
'allowClear' => true
],
]);
?>
<?=
$form->field($model, 'categoryId')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Categorys::find()->where(['categoryStatus'=>'active'])->all(),'categoryId','categoryName'),
'language' => 'en',
'options' => ['placeholder' => 'Select a category ...'],
'pluginOptions' => [
'allowClear' => true
],
]);
?>
<?= $form->field($model, 'productStatus')->dropDownList([ 'active' => 'Active', 'inactive' => 'Inactive', ], ['prompt' => 'Status']) ?>
<label>Product Images</label>
<?=
FileInput::widget([
'name' => 'upload_ajax[]',
//'attribute'=>'productImage[]',
//'name'=>'productImage[]',
'options' => [
'multiple'=>true,
'accept' => 'image/*',
//'id'=>'imageId',
],
'pluginOptions' => [
'initialPreview'=> $initialPreview,
'initialPreviewConfig'=> $initialPreviewConfig,
'showPreview' => true,
'showCaption' => false,
'showRemove' => false,
'showUpload' => false,
'uploadAsync' => false,
'uploadUrl'=>Url::to('index.php?r=products/upload-ajax'),
'deleteUrl'=>Url::to('index.php?r=products/deletefile-ajax'),
'maxFileCount' => 5,
'allowedFileExtensions' => ['jpg', 'png','jpeg'],
'previewFileType' => ['jpg', 'png','jpeg'],
'overwriteInitial'=>false,
'enableResumableUpload'=>true,
'uploadExtraData' => [
'ref'=>$model->ref
],
'validateInitialCount'=>true,
'initialPreviewShowDelete' => true,
'layoutTemplates'=>[
'actionZoom'=>'<button type="button" class="kv-file-zoom">{zoomIcon}</button>',
'actionUpload'=>'',
'actionDelete' => '<button type="button" class="kv-file-remove" title="{removeTitle}" {dataKey}{dataUrl}><i class="glyphicon glyphicon-trash"></i></button>'
],
],
'pluginEvents' => [
// 'filebatchselected' => 'function(files) {
// $(this).fileinput("index.php?r=products/upload-ajax");
// }',
'filepredelete'=>'function(jqXHR){
var abort = true;
if (confirm("Are you sure you want to delete this image?")) {
abort = false;
}
return abort;
}'
],
]);
?>
<br>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord? 'Save': 'Update', ['class' => 'btn btn-primary']) ?>
<?= Html::a(Yii::t('app', 'Cancel'), ['index', 'id' => $model->productId], ['class'=>'btn btn-danger']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
ProductsController
private function getInitialPreview($ref) {
$datas = Uploads::find()->where(['ref'=>$ref])->all();
$initialPreview = [];
$initialPreviewConfig = [];
foreach ($datas as $key => $value) {
array_push($initialPreview, $this->getTemplatePreview($value));
array_push($initialPreviewConfig, [
'caption'=> $value->file_name,
'width' => '120px',
'url' => Url::to('index.php?r=products/deletefile-ajax'),
'key' => $value->upload_id
]);
}
return [$initialPreview,$initialPreviewConfig];
}

Related

Why does it give an error "missing required parameters: id"?

I understand that the error occurred due to the confusion of variables, although these are my assumptions .. The fact is that this error occurred in the update and in the view: update and view. I have already tried everything .. Please poke your nose where I went wrong?
My controller in which I pass two actions view and update:
public function actionView($id)
{
return $this->render('view', [
'faq' => $this->findModel($id),
]);
}
public function actionUpdate($id)
{
$faq = FaqLang::findOne($id);
$faqLang = Faq::findOne($faq->faq_id);
if ($faq->load(Yii::$app->request->post()) && $faqLang->load(Yii::$app->request->post()) && Model::validateMultiple([$faq, $faqLang]))
{
$faqLang->save(false);
$faq->save(false);
return $this->redirect(['view', 'id' => $faq->id]);
}
return $this->render('update', [
'faq' => $faq,
'faqLang' => $faqLang,
]);
}
protected function findModel($id)
{
if (($faq = FaqLang::findOne($id)) !== null) {
return $faq;
}
throw new NotFoundHttpException(Yii::t('app', 'The requested page does not exist.'));
}
view.php in which I am trying to display data using DetailView
<?php
use yii\helpers\Html;
use yii\widgets\DetailView;
/* #var $this yii\web\View */
/* #var $faqLang app\modules\admin\models\Faq */
/* #var $faq app\modules\admin\models\FaqLang */
//$this->title = $faq->id;
$this->params['breadcrumbs'][] = ['label' => Yii::t('app', 'Faqs'), 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="faq-view">
<h1><?= Html::encode($this->title) ?></h1>
<p>
<?= Html::a(Yii::t('app', 'Update'), ['update', 'id' => $faq->id], ['class' => 'btn btn-primary']) ?>
<?= Html::a(Yii::t('app', 'Delete'), ['delete', 'id' => $faq->id], [
'class' => 'btn btn-danger',
'data' => [
'confirm' => Yii::t('app', 'Are you sure you want to delete this item?'),
'method' => 'post',
],
]) ?>
</p>
<?= DetailView::widget([
'faq' => $faq,
'attributes' => [
'id',
['attribute' => 'name', 'value' => 'faqLang.name'],
['attribute' => 'body', 'value' => 'faqLang.body:ntext'],
'put_date',
[
'attribute' => 'hide',
'format' => 'html',
'value' => function($model) {
if($model->hide == 'show')
return 'Нет';
else
return 'Да';
}
],
],
]) ?>
update.php through which the records are updated
<?php
use yii\helpers\Html;
/* #var $this yii\web\View */
/* #var $faqLang app\modules\admin\models\Faq */
/* #var $faq app\modules\admin\models\FaqLang */
$this->title = Yii::t('app', 'Update Faq: ' . $faq->id, [
'nameAttribute' => '' . $faq->id,
]);
$this->params['breadcrumbs'][] = ['label' => Yii::t('app', 'Faqs'), 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => $faq->id, 'url' => ['view', 'id' => $faq->id]];
$this->params['breadcrumbs'][] = Yii::t('app', 'Update');
?>
<div class="faq-update">
<h1><?= Html::encode($this->title) ?></h1>
<?= $this->render('_form', [
'faq' => $faq,
'faqLang' => $faqLang,
]) ?>
</div>
And 2 related Faq and FaqLang models
Faq.php
public function getFaqLang()
{
return $this->hasMany(FaqLang::className(), ['faq_id' => 'id']);
}
FaqLang.php
public function getFaq()
{
return $this->hasOne(Faq::className(), ['id' => 'faq_id']);
}
You may be seeing this error because the request path/query string you're using to run your controller actions does not include the $id parameter.
If you specify a method parameter in a controller action, that parameter must be defined in your routes, and passed in the request
Your action methods are as follows:
public function actionView($id)
{
....
}
Which expects a route like
'/view/<id:\d+>' => 'admin/faqs/view'
and
public function actionUpdate($id)
{
...
}
Which expects a route like
'/update/<id:\d+>' => 'admin/faqs/update'
So for example, for the request /view/123 , the value 123 is passed as the value of $id into the actionView($id) method.
If you have a route set up like
'/view' => 'admin/faqs/view'
There's no id parameter defined, and the controller will throw the error missing required parameters: id

Yii2 - Two models in one form - Values are not saved in the second model

I have a model called Patientinformation.php and a model called AlternativeInformation.php. I would like to use the two models in the patientinformation_form.php
Patientinformation model:
- id (PK)
- patient_id
- patient_initials
- collection_site
- cancer
- study (FK to study model)
AlternativeInformation model:
- alternative_id (PK)
- patients_patient_id (FK to id of the Patientinformation model)
- alternative_study (FK to study model)
- alternative_patient_id
I have updated the Patientinformation controller as well as the create.php file and the _form.php file.
If I enter values in the Patientinformation form.php, I am redirected to the Patientinformation view site. The values of the Patientinformation model (id, patient_id, patient_initials, collection_site, cancer and study) are saved in the database. However, the values of the AlternativeInformation model (alternative_study and alternative_patient_id) are not saved in the database.
This is the PatientinformationController.php file:
<?php
namespace app\controllers;
use Yii;
use app\models\Patientinformation;
use app\models\AlternativeInformation;
use app\models\PatientinformationSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
/**
* Creates a new Patientinformation model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new Patientinformation();
$modelAlternative = new AlternativeInformation();
if ($model->load(Yii::$app->request->post()) && $modelAlternative->load(Yii::$app->request->post())){
$model->save();
$modelAlternative->patients_patient_id = $model->id;
$modelAlternative->save();
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('create', [
'model' => $model,
'modelAlternative' => $modelAlternative,
]);
}
This is the create.php file:
<?php
use yii\helpers\Html;
/* #var $this yii\web\View */
/* #var $model app\models\Patientinformation */
/* #var $modelAlternative app\models\AlternativeInformation */
$this->title = 'Add patient';
$this->params['breadcrumbs'][] = ['label' => 'Patients', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="patientinformation-create">
<h1><?= Html::encode($this->title) ?></h1>
<?= $this->render('_form', [
'model' => $model,
'modelAlternative' => $modelAlternative,
]) ?>
</div>
And this is the _form.php file:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper;
use app\models\CollectionSiteInformation;
use app\models\AlternativeInformation;
use app\models\StudyInformation;
use app\models\CancerInformation;
use unclead\multipleinput\MultipleInput;
use kartik\select2\Select2;
/* #var $this yii\web\View */
/* #var $model app\models\Patientinformation */
/* #var $modelAlternative app\models\AlternativeInformation */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="patientinformation-form">
<?php $form = ActiveForm::begin(); ?>
<p>
Please note that all fields marked with an asterisk (<font color="red">*</font>) are required.
</p>
<?= $form->field($model, 'study')->widget(Select2::classname(), [
'data' => ArrayHelper::map(StudyInformation::find()->all(),'id','study'),
'language' => 'en',
'options' => ['placeholder' => 'Please select a study'],
]);
?>
<?= $form->field($model, 'patient_id')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'patient_initials')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'collection_site')->widget(Select2::classname(), [
'data' => ArrayHelper::map(CollectionSiteInformation::find()->all(),'id','collection_site'),
'language' => 'en',
'options' => ['placeholder' => 'Please select a collection site'],
]);
?>
<?= $form->field($model, 'cancer')->widget(Select2::classname(), [
'data' => ArrayHelper::map(CancerInformation::find()->all(),'id','cancer'),
'language' => 'en',
'options' => ['placeholder' => 'Please select a cancer type'],
]);
?>
<?= $form->field($modelAlternative,'alternative_study')->widget(MultipleInput::class,[
'max' => 6,
'allowEmptyList' => false,
'enableGuessTitle' => true,
'columns' => [
[
'name' => 'alternative_study',
'type' => 'dropDownList',
'title' => 'Alternative Study',
'items' => ArrayHelper::map(studyInformation::find()->asArray()->all (),'id','study'),
'options' => ['prompt' => 'Please select an alternative study if applicable'],
],
]
])
->label(false);
?>
<?= $form->field($modelAlternative,'alternative_patient_id')->widget(MultipleInput::class,[
'max' => 6,
'allowEmptyList' => false,
'enableGuessTitle' => true,
'columns' => [
[
'name' => 'alternative_patient_id',
'title' => 'Alternative patient ID',
'options' => ['prompt' => 'Please select an alternative study if applicable'],
],
]
])
->label(false);
?>
<div class="form-group">
<?= Html::submitButton('Save', ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
If I don`t use unclead\multipleinput\MultipleInput in my _form.php, all the values of AlternativeInformation model (alternative_study and alternative_patient_id) are saved into the model/database.
So I assume that I don`t pass any items to the MultipleInput widget.
This is the AlternativeInformation model file:
/**
* {#inheritdoc}
*/
public function rules()
{
return [
[['patients_patient_id', 'alternative_study'], 'required'],
[['patients_patient_id', 'alternative_study'], 'integer'],
[['alternative_patient_id'], 'string', 'max' => 265],
[['patients_patient_id'], 'exist', 'skipOnError' => true, 'targetClass' => PatientInformation::className(), 'targetAttribute' => ['patients_patient_id' => 'id']],
[['alternative_study'], 'exist', 'skipOnError' => true, 'targetClass' => StudyInformation::className(), 'targetAttribute' => ['alternative_study' => 'id']],
];
}
/**
* {#inheritdoc}
*/
public function attributeLabels()
{
return [
'alternative_id' => 'Alternative ID',
'patients_patient_id' => 'Patients Patient ID',
'alternative_study' => 'Alternative Study',
'alternative_patient_id' => 'Alternative Patient ID',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getPatientsPatient()
{
return $this->hasOne(PatientInformation::className(), ['id' => 'patients_patient_id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getAlternativeStudy()
{
return $this->hasOne(StudyInformation::className(), ['id' => 'alternative_study']);
}
}
Does anyone have any suggestions how this issue can be solved? How will be the values of "alternative_study" and "alternative_patient_id" saved into the AlternativeInformation model if using the MultipleInput widget?
I really need the option in the form to enter no, one or several alternative studies as well as alternative patient ids.
I really appreciate any help how I can solve this issue.
Thanks :)
You are probably getting some validation errors that you can't see because you are redirecting to the view action even if the AlternativeInformation model has validation errors.
The first step towards finding a solution would be making sure that, if AlternativeInformation doesn't save you show the form again, that way you will see the validation errors.
Update your controller code to this:
public function actionCreate()
{
$model = new Patientinformation();
$modelAlternative = new AlternativeInformation();
if ($model->load(Yii::$app->request->post())
&& $modelAlternative->load(Yii::$app->request->post())
&& $model->save()) {
$modelAlternative->patients_patient_id = $model->id;
if ($modelAlternative->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
}
return $this->render('create', [
'model' => $model,
'modelAlternative' => $modelAlternative,
]);
}
That should help you find the problem, it will also give your users information about any future errors that may happen.
The validation problem may be on alternative_patient_id, it seems that you are not passing any items to the MultipleInput widget.
Update your controller with the following code.
public function actionCreate()
{
$model = new Patientinformation();
$modelAlternative = new AlternativeInformation();
if ($model->load(Yii::$app->request->post()) && $modelAlternative->load(Yii::$app->request->post())){
if($model->save()){
$modelAlternative->patients_patient_id = $model->id;
$modelAlternative->save();
return $this->redirect(['view', 'id' => $model->id]);
}
}
return $this->render('create', [
'model' => $model,
'modelAlternative' => $modelAlternative,
]);
}

Activeform data submit in database using Yii2, Not working

I m new in yii2 framework, when I submit my Activeform data to save in database in display error
Not Found (#404).
This Activeform mention in different model view. My form is on product page and I want just give review of customer regarding this product and save in DB.
view file: detail.php:
<?php
use yii\helpers\Html;
use yii\widgets\DetailView;
use yii\widgets\ActiveForm;
/* #var $this yii\web\View */
/* #var $model app\models\Product */
$name = $result->name;
$price = $result->price;
$offerrate = 8;
$offer = ($price / 100) * $offerrate;
$offerprice = number_format($price - $offer, 2);
$text = $result->Description;
$list = explode(",", $text);
?>
<div id="page-content" class="home-page">
<div class="container">
<div class="row">
<div class="col-lg-5">
<center>
<?= Html::img(Yii::$app->urlManagerBackend->BaseUrl.'/'.$result->image, ['alt'=>'myImage','width'=>'300','height'=>'300', 'class' => 'img-responsive']) ?>
<br/>
<?= Html::button('ADD TO CART', ['class' => 'btn btn-success', 'id'=>'addcart']) ?>
<?= Html::button('BUY NOW', ['class' => 'btn btn-danger', 'id'=>'buynow']) ?>
</center>
</div>
<div class="col-lg-7">
<?php echo "<h5 style='color:#009933'>".$name."</h5>"?><br/>
<?php
echo "<ul>";
foreach ($list as $lists)
{
echo "<li class='liststyle'>".$lists."</li>";
}
echo "</ul>";
?><br/>
<?php echo "<h6 style='color:#009933'>MobileShop Offer Price Rs: ".$offerprice."</h6>" ?>
<?= Html::button('Rate and Review product', ['class' => 'btn btn-default', 'id'=>'review', 'data-toggle' => 'collapse', 'data-target' => '#demo']) ?>
<div id="demo" class="collapse">
<?php $form = ActiveForm::begin(['id' => 'reviewForm', 'action' => Yii::$app->urlManager->createUrl(['TblFeedback/create'])]); ?>
<?= $form->field($feedback, 'cust_name')->textInput() ?>
<?= $form->field($feedback, 'feedback')->textArea(['rows' => '2', 'cols' => '10'])?>
<?= $form->field($feedback, 'rating')->dropDownlist(['1' => '*', '2' => '* *', '3' => '* * *', '4' => '* * * *', '5' => '* * * * *']) ?>
<div class="form-group">
<?= Html::submitButton('Save', ['id' => 'savebtn', 'class' => 'btn btn-default']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>
</div>
</div>
Controller file: TblFeedbackController.php
<?php
namespace frontend\controllers;
use Yii;
use app\models\TblFeedback;
use frontend\models\Product;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
class TblFeedbackController extends \yii\web\Controller
{
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
public function actionIndex()
{
return $this->render('index');
}
public function actionCreate()
{
$feedback = new TblFeedback();
if ($feedback->load(Yii::$app->request->post()) && $feedback->validate())
{
var_dump($feedback);
die();
$feedback->save();
Yii::$app->session->setFlash('success', '<h5>Thanks for review!</h5>');
return $this->redirect(['index']);
}
else {
return $this->render('index',
['feedback' => $feedback,
]);
Yii::$app->session->setFlash('error', 'Error Found!');
}
}
}
model file: TblFeedback.php
<?php
namespace frontend\models;
use Yii;
/**
* This is the model class for table "tbl_feedback".
*
* #property integer $id
* #property integer $product_id
* #property integer $cust_id
* #property string $cust_name
* #property integer $rating
* #property string $feedback
*
* #property Product $product
* #property User $cust
*/
class TblFeedback extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'tbl_feedback';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['product_id', 'cust_id', 'cust_name', 'rating', 'feedback'], 'required'],
[['product_id', 'cust_id', 'rating'], 'integer'],
[['rating'], 'integer', 'min' => 1, 'max' => 5],
[['cust_name'], 'string', 'max' => 200],
[['feedback'], 'string', 'max' => 1000],
[['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => Product::className(), 'targetAttribute' => ['product_id' => 'id']],
[['cust_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['cust_id' => 'id']],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'product_id' => 'Product ID',
'cust_id' => 'Cust ID',
'cust_name' => 'Enter Name:',
'rating' => 'Rating',
'feedback' => 'Description',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getProduct()
{
return $this->hasOne(Product::className(), ['id' => 'product_id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getCust()
{
return $this->hasOne(User::className(), ['id' => 'cust_id']);
}
}
The naming convention for controller action are based on - separator when a part is uppercase so you should use
<?php $form = ActiveForm::begin(['id' => 'reviewForm',
'action' => Yii::$app->urlManager->createUrl(['Tbl-feedback/create'])]); ?>
the naming convention,for the controllers, it is to start with a lowercase character.
so you should use
class tblFeedbackController extends \yii\web\Controller
and
<?php $form = ActiveForm::begin(['id' => 'reviewForm',
'action' => Yii::$app->urlManager->createUrl(['tbl-feedback/create'])]); ?>
and last suggestion you could use urlHelper
use yii\helpers\Url;
<?php $form = ActiveForm::begin(['id' => 'reviewForm',
'action' => Url::to(['tbl-feedback/create'])]); ?>

Insert multiple rows into table by checkboxcolumn in yii2

I have a table rawmaterial. The fields are - rmname, usedate, useqty, unitcost, productname, chargenumber. I've added a gridview (which comes from rmtemplate table) with a checkboxcolumn in the form. The gridview contains columns productname, rmname, qty, unitcost. How can I insert the checked rows along with usedate, chargenumber(which come from respective textboxes) in the table rawmaterial.
I've checked ActiveRecord batch insert (yii2) but not getting how to use it with checkbocolumn.
Checked How I can process a checkbox column from Yii2 gridview? - not quite sure with it.
Checked Yii2 How to properly create checkbox column in gridview for bulk actions? - I think it's not using activeform.
form.php
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use kartik\grid\GridView;
use dosamigos\datepicker\DatePicker;
use kartik\select2\Select2;
use yii\helpers\ArrayHelper;
use frontend\models\Rmtemplate;
/* #var $this yii\web\View */
/* #var $model frontend\models\Rawmaterial */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="rawmaterial-form">
<?php $form = ActiveForm::begin(); ?>
<div class="form-group">
<div class="col-xs-12 col-sm-12 col-lg-12">
<?= $form->field($model, 'usedate')->widget(
DatePicker::className(), [
// inline too, not bad
'inline' => false,
// modify template for custom rendering
//'template' => '<div class="well well-sm" style="background-color: #fff; width:250px">{input}</div>',
'clientOptions' => [
'autoclose' => true,
'todayHighlight' => true,
'format' => 'yyyy-mm-dd'
]
]);?>
</div>
<div class="col-xs-12 col-sm-12 col-lg-12">
<?= GridView::widget([
'dataProvider' => $dataProvider2,
'filterModel' => $searchModel2,
'columns' => [
['class' => 'kartik\grid\CheckboxColumn'],
//'id',
//'productname',
[
'attribute'=>'productname',
'filterType'=>GridView::FILTER_SELECT2,
'filter'=>ArrayHelper::map(Rmtemplate::find()->orderBy(['productname' => SORT_ASC])->asArray()->all(), 'productname', 'productname'),
'filterWidgetOptions'=>[
'pluginOptions'=>['allowClear'=>true],
],
'filterInputOptions'=>['placeholder'=>'Charge Name'],
],
'rmname',
'qty',
[
'attribute' => 'unitcost',
'value' => 'unitcost.unitcost',
],
//['class' => 'yii\grid\ActionColumn'],
],
]); ?>
</div>
</div>
<?= $form->field($model, 'chargenumber')->textInput()->hiddenInput()->label(false) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary','name' => 'submit', 'value' => 'create_update']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
<?php
/* start getting the chargeno */
$script = <<<EOD
$(window).load(function(){
$.get('index.php?r=rmprod/rawmaterial/get-for-chargeno',{ orderid : 1 }, function(data){
//alert(data);
var data = $.parseJSON(data);
$('#rawmaterial-chargenumber').attr('value',data.chargeno);
}
);
});
EOD;
$this->registerJs($script);
/*end getting the chargeno */
?>
And it looks like below.
CreateAction looks like -
public function actionCreate()
{
$model = new Rawmaterial();
$searchModel2 = new RmtemplateSearch();
$dataProvider2 = $searchModel2->search(Yii::$app->request->queryParams);
if (isset($_POST['submit'])) {
if ($_POST('submit') == 'create_update' ) {
// then perform the insert
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
'searchModel2' => $searchModel2,
'dataProvider2' => $dataProvider2,
]);
}
}
} else {
// no insert but render for filter ..
return $this->render('create', [
'model' => $model,
'searchModel2' => $searchModel2,
'dataProvider2' => $dataProvider2,
]);
}
}
Update
RawMaterialForm.php
<?php
namespace frontend\modules\rmprod\models;
use Yii;
/**
* This is the model class for table "rawmaterial".
*
* #property integer $id
* #property string $vname
* #property string $challan
* #property string $purchasedate
* #property string $purchaseqty
* #property string $rate
* #property string $rmname
* #property string $usedate
* #property string $useqty
* #property string $unitcost
* #property string $productname
* #property integer $chargenumber
*/
class RawMaterialForm extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'rawmaterial';
}
/**
* #inheritdoc
*/
// public function rules()
// {
// return [
// [['purchasedate', 'usedate'], 'safe'],
// [['chargenumber'], 'integer'],
// [['vname', 'productname'], 'string', 'max' => 40],
// [['challan'], 'string', 'max' => 20],
// [['purchaseqty', 'rmname', 'useqty'], 'string', 'max' => 50],
// [['rate', 'unitcost'], 'string', 'max' => 10],
// ];
// }
public function rules()
{
return [
[['usedate'], 'safe'],
[['chargenumber'], 'integer'],
[['productname'], 'string', 'max' => 40],
[['rmname', 'useqty'], 'string', 'max' => 50],
[['unitcost'], 'string', 'max' => 10],
[['rmtemplate_ids'], 'safe'],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'vname' => 'Vname',
'challan' => 'Challan',
'purchasedate' => 'Purchasedate',
'purchaseqty' => 'Purchaseqty',
'rate' => 'Rate',
'rmname' => 'Rmname',
'usedate' => 'Usedate',
'useqty' => 'Useqty',
'unitcost' => 'Unitcost',
'productname' => 'Productname',
'chargenumber' => 'Chargenumber',
];
}
}
RawmaterialController
<?php
namespace frontend\modules\rmprod\controllers;
use Yii;
use frontend\models\Rawmaterial;
use frontend\modules\rmprod\models\RawmaterialSearch;
use frontend\modules\rmprod\models\RmtemplateSearch;
use frontend\modules\rmprod\models\RawMaterialForm;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\helpers\Json;
/**
* RawmaterialController implements the CRUD actions for Rawmaterial model.
*/
class RawmaterialController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all Rawmaterial models.
* #return mixed
*/
public function actionIndex()
{
$searchModel = new RawmaterialSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
$searchModel2 = new RmtemplateSearch();
$dataProvider2 = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'searchModel2' => $searchModel2,
'dataProvider2' => $dataProvider2,
]);
}
/**
* Displays a single Rawmaterial model.
* #param integer $id
* #return mixed
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Rawmaterial model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new RawMaterialForm();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(
['create']
// redirect to where you want
);
}
$searchModel2 = new RmtemplateSearch();
$dataProvider2 = $searchModel2->search(Yii::$app->request->queryParams);
return $this->render('create', [
'model' => $model,
'searchModel2' => $searchModel2,
'dataProvider2' => $dataProvider2,
]);
}
/**
* Updates an existing Rawmaterial model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param integer $id
* #return mixed
*/
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,
]);
}
}
/**
* Deletes an existing Rawmaterial model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param integer $id
* #return mixed
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
public function actionGetForChargeno($orderid)
{
$rates = Rawmaterial::find()->select('(max(chargenumber) + 1) as chargeno')->asArray()->one();
echo Json::encode($rates);
}
/**
* Finds the Rawmaterial model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return Rawmaterial the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Rawmaterial::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
public function save()
{
try {
if ($this->validate()) {
// assuming Rmtemplate is the model used in RmtemplateSearch
$selectedRmtemplate = Rmtemplate::find()->where(['id' => $this->rmtemplate_ids]);
foreach ($selectedRmtemplate->each() as $rm) {
$rawMaterial = new Rawmaterial();
$rawMaterial->rmname = $rm->rmname;
$rawMaterial->usedate = $this->usedate;
$rawMaterial->useqty = $rm->qty;
$rawMaterial->unitcost = $rm->unitcost;
$rawMaterial->productname = $rm->productname;
$rawMaterial->chargenumber = $this->chargenumber;
if (!$rawMaterial->save()) {
throw new \Exception('Error while saving rawMaterial!');
}
}
return true;
}
} catch (\Exception $exc) {
\Yii::error($exc->getMessage());
}
return false;
}
}
Error
According to my understanding, you have to do two things.
Firstly, you have to grab all the checked rows data of the grid view as an array or object. You can see how to do that from Get Grid Data .
Secondly you have to change your create action for handling the data you fetch from that grid. You can take help from Batch Insert
Hope it helps...
Prepare additional model like RawMaterialForm with properties that will be taken from ActiveForm usedate, chargenumber and rmtemplate_ids. The last one is the array of GridView IDs. Remember to add rules() in the RawMaterialForm for the properties.
The view - just the GridView needs some tweaks. Extend the configuration for Checkbox column.
[
'class' => 'kartik\grid\CheckboxColumn',
'name' => 'RawMaterialForm[rmtemplate_ids]',
'checkboxOptions' => function ($model, $key, $index, $column) {
return ['value' => $model->id];
}
],
The action:
public function actionCreate()
{
$model = new RawMaterialForm();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(
// redirect to where you want
);
}
$searchModel2 = new RmtemplateSearch();
$dataProvider2 = $searchModel2->search(Yii::$app->request->queryParams);
return $this->render('create', [
'model' => $model,
'searchModel2' => $searchModel2,
'dataProvider2' => $dataProvider2,
]);
}
RawMaterialForm's save() method:
public function save()
{
try {
if ($this->validate()) {
// assuming Rmtemplate is the model used in RmtemplateSearch
$selectedRmtemplate = Rmtemplate::find()->where(['id' => $this->rmtemplate_ids]);
foreach ($selectedRmtemplate->each() as $rm) {
$rawMaterial = new Rawmaterial();
$rawMaterial->rmname = $rm->rmname;
$rawMaterial->usedate = $this->usedate;
$rawMaterial->useqty = $rm->qty;
$rawMaterial->unitcost = $rm->unitcost;
$rawMaterial->productname = $rm->productname;
$rawMaterial->chargenumber = $this->chargenumber;
if (!$rawMaterial->save()) {
throw new \Exception('Error while saving rawMaterial!');
}
}
return true;
}
} catch (\Exception $exc) {
\Yii::error($exc->getMessage());
}
return false;
}
This will copy every selected row into a new Rawmaterial row with additional inputs from ActiveForm.
In case of errors in $rawMaterial saving check $rawMaterial->errors property.
Fair warning - depending on the system performance this can be slow (or even fatal) in case of selecting many rows at once.

Yii2 Select2 - selected value on update - junction table (many to many)

I am successfully inserting new rows in my junction table (userlocations) on action create and I successfully update them on action update but the problem is on ation update the location_id field is always empty. It should retrieve the location_id's from userlocations table and populate the field on update but it doesnt.
Database: http://i.stack.imgur.com/JFjdz.png
UserController:
<?php
namespace backend\controllers;
use Yii;
use backend\models\User;
use backend\models\UserSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\helpers\ArrayHelper;
use backend\models\Locations;
use backend\models\Userlocations;
class UserController extends Controller
{
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all User models.
* #return mixed
*/
public function actionIndex()
{
$searchModel = new UserSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single User model.
* #param integer $id
* #return mixed
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new User model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new User();
$locations = ArrayHelper::map(Locations::find()->all(), 'id', 'name');
$userlocations = new Userlocations();
if ($model->load(Yii::$app->request->post()) ) {
$model->setPassword($model->password);
$model->generateAuthKey();
$userlocations->load(Yii::$app->request->post());
if ($model->save() && !empty($userlocations->location_id)){
foreach ($userlocations->location_id as $location_id) {
$userlocations = new Userlocations();
$userlocations->setAttributes([
'location_id' => $location_id,
'user_id' => $model->id,
]);
$userlocations->save();
}
}
return $this->redirect(['user/index']);
} else {
return $this->render('create', [
'model' => $model,
'locations' => $locations,
'userlocations' => $userlocations,
]);
}
}
/**
* Updates an existing User model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param integer $id
* #return mixed
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
$locations = ArrayHelper::map(Locations::find()->all(), 'id', 'name');
$userlocations = new Userlocations();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
Userlocations::deleteAll(['user_id' => $id]);
$userlocations->load(Yii::$app->request->post());
if (!empty($userlocations->location_id)){
foreach ($userlocations->location_id as $location_id) {
$userlocations = new Userlocations();
$userlocations->setAttributes([
'location_id' => $location_id,
'user_id' => $model->id,
]);
$userlocations->save();
}
}
return $this->redirect(['user/index']);
} else {
return $this->render('update', [
'model' => $model,
'locations' => $locations,
'userlocations' => $userlocations,
]);
}
}
/**
* Deletes an existing User model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param integer $id
* #return mixed
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the User model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return User the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = User::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}
User model:
class User extends \common\models\User
{
public $password;
/**
* #inheritdoc
*/
public static function tableName()
{
return 'User';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['username', 'password'], 'required'],
[['status', 'created_at', 'updated_at'], 'integer'],
[['username', 'password_hash', 'password_reset_token', 'email'], 'string', 'max' => 255],
[['auth_key'], 'string', 'max' => 32],
[['username'], 'unique', 'message' => 'Username already taken!'],
[['email'], 'unique'],
[['password_reset_token'], 'unique'],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'username' => 'Username',
'auth_key' => 'Auth Key',
'password_hash' => 'Password Hash',
'password_reset_token' => 'Password Reset Token',
'email' => 'Email',
'status' => 'Status',
'created_at' => 'Created At',
'updated_at' => 'Updated At',
];
}
}
My form:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper;
use kartik\select2\Select2;
use backend\models\Locations;
?>
<div class="user-form">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'username')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'password')->passwordInput(['maxlength' => true]) ?>
<?= $form->field($model, 'email')->textInput(['maxlength' => true]) ?>
<?= $form->field($userlocations, 'location_id')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Locations::find()->all(), 'id', 'name'),
'size' => Select2::MEDIUM,
'options' => ['placeholder' => 'Select a location ...', 'multiple' => true],
'pluginOptions' => [
'allowClear' => true,
],
]); ?>
<?= $form->field($model, 'status')->dropDownList(['10' => 'Active', '0' => 'Inactive']) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
For multiple location select, use the plugin code as given below.
<?= Select2::widget([
'name' => 'Userlocations[location_id]',
'value' => $location_ids, // initial value
'data' => ArrayHelper::map(Locations::find()->all(), 'id', 'name'),
'options' => ['placeholder' => 'Select your locations...', 'multiple' => true],
'pluginOptions' => [
'tags' => true,
'maximumInputLength' => 10
],
]); ?>
$location_ids will be the location array you have previously selected during creation time.Also remember when you are making changes for more than one table,make sure you do it in a transaction.