Getting duplicate text values while updating in yii2-dynamic form - yii2

I am using wbraganca
/
yii2-dynamicform. I have created a dynamic form, able to view the data. Now when I try to update it the value of my 1st text box is always the same for each record. Below is my view
Here Slab Names are S-1 to S-4. Now when I try to update them
Above all the slab names are S-1 but the other fields' data is correct.
public function actionUpdate($id)
{
$model = $this->findModel($id);
$modelsTariffSlabs = $this->findModelSlabs($model->id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
$oldIDs = ArrayHelper::map((array)$modelsTariffSlabs, 'id', 'id');
$modelsTariffSlabs = CustomtariffModel::createMultiple(MdcTariffSlabs::classname(), $modelsTariffSlabs);
CustomtariffModel::loadMultiple($modelsTariffSlabs, Yii::$app->request->post());
$deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($modelsTariffSlabs, 'id', 'id')));
// validate all models
$valid = $model->validate();
$valid = CustomtariffModel::validateMultiple($modelsTariffSlabs) && $valid;
if ($valid) {
$transaction = \Yii::$app->db->beginTransaction();
try {
if ($flag = $model->save(false)) {
if (! empty($deletedIDs)) {
MdcTariffSlabs::deleteAll(['id' => $deletedIDs]);
}
foreach ($modelsTariffSlabs as $modelTariffSlabs) {
$modelTariffSlabs->t_id = $model->id;
if (! ($flag = $modelTariffSlabs->save(false))) {
$transaction->rollBack();
break;
}
}
}
if ($flag) {
$transaction->commit();
return $this->redirect(['view', 'id' => $model->id]);
}
} catch (Exception $e) {
$transaction->rollBack();
}
}
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('update', [
'model' => $model,
'modelsTariffSlabs' => (empty($modelsTariffSlabs)) ? [new MdcTariffSlabs()] : $modelsTariffSlabs
]);
}
protected function findModelSlabs($id)
{
if (($model = MdcTariffSlabs::find()->where(['t_id'=>$id])->all()) !== null) {
return $model;
}
throw new NotFoundHttpException(Yii::t('app', 'The requested page does not exist.'));
}
_form
<div class="container-items"><!-- widgetContainer -->
<?php foreach ($modelsTariffSlabs as $i => $modelTariffSlabs): ?>
<div class="item panel panel-default"><!-- widgetBody -->
<div class="panel-heading">
<h3 class="panel-title pull-left">Slab</h3>
<div class="pull-right">
<button type="button" id="addBtn" class="js-add-filter btn btn-success btn-xs"><i class="glyphicon glyphicon-plus"></i></button>
<button type="button" id="remBtn" class="js-remove-filter 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 (! $modelTariffSlabs->isNewRecord) {
echo Html::activeHiddenInput($modelTariffSlabs, "[{$i}]id");
}
?>
<div class="row">
<div class="col-sm-3">
<?= $form->field($modelTariffSlabs, "[{$i}]slab_name")->textInput(['readonly'=>true,'value'=>'S-1','maxlength' => 10,"class"=>"form-control js-slab-name"]) ?>
</div>
<div class="col-sm-3">
<?= $form->field($modelTariffSlabs, "[{$i}]slab_start")->textInput(['maxlength' => 10,"class"=>"form-control js-slab-start"]) ?>
</div>
<div class="col-sm-3">
<?= $form->field($modelTariffSlabs, "[{$i}]slab_end")->textInput(['maxlength' => 10,"class"=>"form-control js-slab-end"]) ?>
</div>
<div class="col-sm-3">
<?= $form->field($modelTariffSlabs, "[{$i}]rate")->textInput(['maxlength' => 10, "class"=>"form-control js-slab-rate"]) ?>
</div>
</div><!-- .row -->
</div>
</div>
<?php endforeach; ?>
</div>
How can I show the actual slabs name?

You have to place a check for slab_name. Here is the snip
<div class="col-sm-3">
<?php if ($modelTariffSlabs->isNewRecord) { ?>
<?= $form->field($modelTariffSlabs, "[{$i}]slab_name")->textInput(['readonly'=>true,'value'=>'S-1','maxlength' => 10,"class"=>"form-control js-slab-name"]) ?>
<?php } elseif (!$modelTariffSlabs->isNewRecord) {?>
<?=$form->field($modelTariffSlabs, "[{$i}]slab_name")->textInput(['readonly' => true, 'value' => $modelTariffSlabs->slab_name, 'maxlength' => 10, "class" => "form-control js-slab-name"])?>
<?php }?>
</div>

Related

Yii2 - Dynamic Form with a single model

I have always worked with Dynamic Form that saved in multiple models, especially wbraganca. However, I want to create a Dynamic Form whereby everything will be saved on the same Model Class, CentreProgramme. When the Add button is clicked, Dropdownlist with attribute Programme_id will be created.
How do I achieve this.
I used the code shown below, but the Dropdown is not wide enough to accommodate on the data. When I select all from the dropdown, it spreads accross the dropdown because the data is too large. Thanks
I have this Model Class
CentreProgramme
public function attributeLabels()
{
return [
'id' => Yii::t('centre', 'ID'),
'state_office_id' => Yii::t('centre', 'State Office'),
'study_centre_id' => Yii::t('centre', 'Study Centre'),
'programme_id' => Yii::t('centre', 'Programme'),
];
}
Controller
public function actionCreate()
{
$model = new StudyCentreProgramme();
if ($model->load(Yii::$app->request->post()) && isset($_POST['StudyCentreProgramme'])) {
$model->attributes = $_POST['StudyCentreProgramme'];
for($i=0;$i<count($_REQUEST['StudyCentreProgramme']['programme_id']);$i++) :
$model->id = NULL;
$model->isNewRecord = true;
$model->programme_id = $_POST['StudyCentreProgramme']['programme_id'][$i];
$model->state_office_id = $_POST['StudyCentreProgramme']['state_office_id'];
$model->study_centre_id = $_POST['StudyCentreProgramme']['study_centre_id'];
if($model->save()) {
Yii::$app->session->setFlash('green-'.$i, '<i class="fa fa-info-circle"></i> <b>Study Centre Programme: </b> is created successfully');
} else {
Yii::$app->session->setFlash('red-'.$i, '<i class="fa fa-warning"></i><b>Study Centre Programme: </b> has already been taken.');
}
endfor;
return $this->redirect(['index']);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
View
<?php $form = ActiveForm::begin([
'id' => 'study-centre-programme-form',
'fieldConfig' => [
'template' => "{label}{input}{error}",
],
]); ?>
<div class="col-xs-12 col-sm-6 col-lg-6">
<?= $form->field($model, 'state_office_id')->dropDownList(ArrayHelper::map(\common\models\StateOffice::find()->where(['is_status' => 0])->all(),'id','state_name'),
[
'prompt'=>Yii::t('app', '--- Select State Officee ---'),
'onchange'=>'
$.get( "'.Url::toRoute('dependent/getprogrammestudycentre').'", { id: $(this).val() } )
.done(function( data ) {
$( "#'.Html::getInputId($model, 'state_office_id').'" ).html( data );
}
);'
]
); ?>
</div>
<div class="col-xs-12 col-sm-6 col-lg-6">
<?= $form->field($model, 'state_office_id')->dropDownList([''=>Yii::t('app', '--- Select Study Centre ---')]); ?>
</div>
<div class="col-xs-12 col-sm-12 col-lg-12">
<?php
if(Yii::$app->controller->action->id === 'create' ) {
echo $form->field($model, 'programme_id[]')->dropDownList(ArrayHelper::map(common\models\Programme::find()->where(['is_status' => 0])->all(),'id','programme_name'),['multiple' => "multiple", 'class'=>'form-control', 'placeholder' => $model->getAttributeLabel('programme_id')]);
} else {
echo $form->field($model, 'programme_id')->dropDownList(ArrayHelper::map(common\models\Programme::find()->where(['is_status' => 0])->all(),'id','programme_name'),['class'=>'form-control', 'placeholder' => $model->getAttributeLabel('programme_id')]);
}
?>
</div>
<div class="form-group col-xs-12 col-sm-6 col-lg-4 no-padding jkkesrmsArLangCss">
<div class="col-xs-6">
<?= Html::submitButton($model->isNewRecord ? Yii::t('centre', 'Create') : Yii::t('centre', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-block btn-success' : 'btn btn-block btn-info']) ?>
</div>
<div class="col-xs-6">
<?= Html::a(Yii::t('centre', 'Cancel'), ['index'], ['class' => 'btn btn-default btn-block']); ?>
</div>
</div>
<?php ActiveForm::end(); ?>
[

Yii2 dynamic form with number of record based on variable value

I cannot save all records but just the last.
In a form users insert Year_begin and Year_end
A variable $years (where $years = Year_end - Year_begin) is passed to the dynamic form.
Example:
Worked 2010 and 2011 I need to generate two records
Worked from 2010 to 2015 I need to generate six records
I don't want to use "+" and "-" button to generate new record.
Every record shows the correct YEAR value
This is the result:
This is the code of my form with while cycle:
<?php foreach ($modelsComm as $i => $modelComm): ?>
<div class="item panel panel-default"><!-- widgetBody -->
<div class="panel-heading">
<h3 class="panel-title pull-left">id_calcolo</h3>
<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">
<!-- loop begin -->
<?php
$n=0;
while ($n < $years) {
// necessary for update action.
if (! $modelComm->isNewRecord) {
echo Html::activeHiddenInput($modelComm, "[{$i}]id");
}
?>
<div class="row">
<div class="col-sm-2">
<?= $form->field($modelComm, "[{$i}]year")->textInput(['value' => $year_begin+$n]) ?>
</div>
<div class="col-sm-4">
<?= $form->field($modelComm, "[{$i}]worked")->textInput(['maxlength' => true]) ?>
</div>
<div class="col-sm-4">
<?= $form->field($modelComm, "[{$i}]paid")->textInput(['maxlength' => true]) ?>
</div>
</div><!-- .row -->
<?php
$n++;
}
?>
<!-- loop end -->
</div>
</div>
<?php endforeach; ?>
My Controller function:
public function actionCreate($years,$year_begin)
{
$model = new CalcReference();
$modelsComm = [new Comm];
if ($model->load(Yii::$app->request->post()) && $model->save())
{
$modelsComm = Model::createMultiple(Comm::classname());
Model::loadMultiple($modelsComm, Yii::$app->request->post());
// ajax validation
if (Yii::$app->request->isAjax) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ArrayHelper::merge(
ActiveForm::validateMultiple($modelsComm),
ActiveForm::validate($model)
);
}
// validate all models
$valid = $model->validate();
$valid = Model::validateMultiple($modelsComm) && $valid;
if ($valid) {
$transaction = \Yii::$app->db->beginTransaction();
try {
if ($flag = $model->save(false)) {
foreach ($modelsComm as $modelComm) {
$modelComm->id_pratica = $model->id;
if (! ($flag = $modelComm->save(false))) {
$transaction->rollBack();
break;
}
}
}
if ($flag) {
$transaction->commit();
return $this->redirect(['view',
'id' => $model->id,
'year_begin' => $yeear_begin,
'years' => $years,
]);
}
} catch (Exception $e) {
$transaction->rollBack();
}
}
/* return $this->redirect(['view', 'id' => $model->id,
'anno_inizio' => $anno_inizio,
'qta_anni' => $qta_anni,
'dal' => $dal,
'al' => $al,
'id_pratica' => $id_pratica,
]);*/
} else
{
return $this->render('create', [
'model' => $model,
'modelsComm' => (empty($modelsComm)) ? [new Comm] : $modelsComm,
'year_begin' => $yeear_begin,
'years' => $years,
]);
}
}
My model:
public static function tableName()
{
return 'comm';
}
public function rules()
{
return [
[['year', 'worked', ], 'required'],
[['worked', 'paid'], 'integer'],
];
}
public function attributeLabels()
{
return [
'id' => 'ID',
'year' => 'Year',
'worked' => 'Worked days',
'paid' => 'Total Paid',
];
}
This is model Model.php:
class Model extends \yii\base\Model
{
/**
* Creates and populates a set of models.
*
* #param string $modelClass
* #param array $multipleModels
* #return array
*/
public static function createMultiple($modelClass, $multipleModels = [])
{
$model = new $modelClass;
$formName = $model->formName();
$post = Yii::$app->request->post($formName);
$models = [];
if (! empty($multipleModels)) {
$keys = array_keys(ArrayHelper::map($multipleModels, 'id', 'id'));
$multipleModels = array_combine($keys, $multipleModels);
}
if ($post && is_array($post)) {
foreach ($post as $i => $item) {
if (isset($item['id']) && !empty($item['id']) && isset($multipleModels[$item['id']])) {
$models[] = $multipleModels[$item['id']];
} else {
$models[] = new $modelClass;
}
}
}
unset($model, $formName, $post);
return $models;
In the years loop You use $n but input names have $i inside. So all Your inputs are initialized with [0] prefix. That's why on server side You have only the last record.
Just change [{$i}]id to [{$n}]id, [{$i}]year to [{$n}]year and so on

yii2 dynamic form updating only one table

I'm trying to update data with the help of yii2/dynamic form.
Table 1- "sellsg" - columns (ssg_id,ssg_customer,ssg_invoiceno,ssg_date,ssg_amount)
Table2 - "sellitemsg" - columns (ssgi_id,ssgi_invoiceno,ssgi_sgname,ssgi_price)
Relation - sellsg.ssg_invoiceno = sellitemsg.ssgi_invoiceno
The Create part is working fine. I'm struggling with the update part.
Problem 1.
When the form was creating new record - There is a javascript code in the form to increase the invoice no by 1 everytime. When I'm loading the form for update, it also increases in by 1 overriding the original invoiceno. I want to limit this function only when I create but not in update.
Problem 2
When I am updating the form, it only updating the sellsg table but not sellitemsg table.
_Form
<?php
use yii\helpers\Html;
use kartik\form\ActiveForm;
use wbraganca\dynamicform\DynamicFormWidget;
use dosamigos\datepicker\DatePicker;
use yii\helpers\ArrayHelper;
use kartik\select2\Select2;
use frontend\modules\sellsg\models\Customer;
use frontend\modules\sellsg\models\Sunglass;
/* #var $this yii\web\View */
/* #var $model frontend\modules\sellsg\models\Sellsg */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="sellsg-form">
<?php $form = ActiveForm::begin([
'id' => 'dynamic-form',
'type' => ActiveForm::TYPE_HORIZONTAL,
'formConfig' => ['labelSpan' => 3, 'deviceSize' => ActiveForm::SIZE_SMALL]
]);
?>
<div class="row">
<div class="col-xs-12 col-sm-12 col-lg-12">
<div class="form-group">
<div class="col-xs-6 col-sm-6 col-lg-6">
<?= $form->field($model, 'ssg_customer')->label(false)->widget(Select2::classname(), [
'data' => ArrayHelper::map(Customer::find()->all(),'c_name','customerDetails'),
'language' => 'en',
'options' => ['placeholder' => 'Select Customer Details', 'id' => 'custid'],
'pluginOptions' => [
'allowClear' => true
],
]);
?>
</div>
<div class="col-xs-3 col-sm-3 col-lg-3">
<?= $form->field($model, 'ssg_date')->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-3 col-sm-3 col-lg-3">
</div>
</div>
</div>
</div>
<?= $form->field($model, 'ssg_invoiceno')->textInput() ?>
<div class="rows">
<div class="panel panel-default">
<div class="panel-heading"><h4><i class="glyphicon glyphicon-envelope"></i> Sunglasses</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' => 1, // 0 or 1 (default 1)
'insertButton' => '.add-item', // css class
'deleteButton' => '.remove-item', // css class
'model' => $modelsSellitemsg[0],
'formId' => 'dynamic-form',
'formFields' => [
'ssgi_sgname',
'ssgi_price',
],
]); ?>
<div class="container-items"><!-- widgetContainer -->
<?php foreach ($modelsSellitemsg as $i => $modelSellitemsg): ?>
<div class="item panel panel-default"><!-- widgetBody -->
<div class="panel-body">
<?php
// necessary for update action.
if (! $modelSellitemsg->isNewRecord) {
echo Html::activeHiddenInput($modelSellitemsg, "[{$i}]ssgi_id");
}
?>
<div class="row">
<div class="col-sm-6">
<?= $form->field($modelSellitemsg, "[{$i}]ssgi_sgname")->label(false)->widget(Select2::classname(), [
'data' => ArrayHelper::map(Sunglass::find()->all(),'sg_name','sg_name'),
'language' => 'en',
'options' => ['placeholder' => 'Select Sunglass'],
'pluginOptions' => [
'allowClear' => true
],
]);
?>
</div>
<div class="col-sm-3">
<?= $form->field($modelSellitemsg, "[{$i}]ssgi_price")->textInput([
'maxlength' => true,
'class' => 'sumPart',
//'onfocus'=>'sum()', 'onBlur'=>'sum()'
]) ?>
</div>
<div class="col-sm-3">
<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>
</div><!-- .row -->
</div>
</div>
<?php endforeach; ?>
</div>
<?php DynamicFormWidget::end(); ?>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-12 col-lg-12">
<div class="form-group">
<div class="col-xs-6 col-sm-6 col-lg-6">
</div>
<div class="col-xs-3 col-sm-3 col-lg-3">
<?= $form->field($model, 'ssg_amount')->textInput(['class' => 'sum']) ?>
</div>
<div class="col-xs-3 col-sm-3 col-lg-3">
</div>
</div>
</div>
</div>
</div>
<div class="col-xs-12 col-sm-12 col-lg-12">
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
</div>
<?php ActiveForm::end(); ?>
</div>
<?php
/* start getting the invoiceno */
$script = <<<EOD
$(window).load(function(){
$.get('get-for-invoiceno',{ invoiceid : 1 }, function(data){
//alert(data);
var data = $.parseJSON(data);
$('#sellsg-ssg_invoiceno').attr('value',data.invoiceno);
}
);
});
EOD;
$this->registerJs($script);
/*end getting the invoiceno */
?>
<?php
/* start getting the totalamount */
$script = <<<EOD
var getSum = function() {
var items = $(".item");
var sum = 0;
items.each(function (index, elem) {
var priceValue = $(elem).find(".sumPart").val();
//Check if priceValue is numeric or something like that
sum = parseInt(sum) + parseInt(priceValue);
});
//Assign the sum value to the field
$(".sum").val(sum);
};
//Bind new elements to support the function too
$(".container-items").on("change", ".sumPart", function() {
getSum();
});
EOD;
$this->registerJs($script);
/*end getting the totalamount */
?>
SellsgController
public function actionCreate()
{
$model = new Sellsg();
$modelsSellitemsg = [new Sellitemsg];
if ($model->load(Yii::$app->request->post()) && $model->save()) {
$modelsSellitemsg = Model::createMultiple(Sellitemsg::classname());
Model::loadMultiple($modelsSellitemsg, Yii::$app->request->post());
// validate all models
$valid = $model->validate();
$valid = Model::validateMultiple($modelsSellitemsg) && $valid;
if ($valid) {
$transaction = \Yii::$app->db->beginTransaction();
try {
if ($flag = $model->save(false)) {
foreach ($modelsSellitemsg as $modelSellitemsg) {
$modelSellitemsg->ssgi_invoiceno = $model->ssg_invoiceno;
if (! ($flag = $modelSellitemsg->save(false))) {
$transaction->rollBack();
break;
}
}
}
if ($flag) {
$transaction->commit();
return $this->redirect(['view', 'id' => $model->ssg_id]);
}
} catch (Exception $e) {
$transaction->rollBack();
}
}
}
else {
return $this->render('create', [
'model' => $model,
'modelsSellitemsg' => (empty($modelsSellitemsg)) ? [new Sellitemsg] : $modelsSellitemsg
]);
}
}
/**
* Updates an existing Sellsg 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);
$modelsSellitemsg = $model->sellitemsg;
if ($model->load(Yii::$app->request->post()) && $model->save()) {
$oldIDs = ArrayHelper::map($modelsSellitemsg, 'id', 'id');
//var_dump($oldIDs);
$modelsSellitemsg = Model::createMultiple(Sellitemsg::classname(), $modelsSellitemsg);
Model::loadMultiple($modelsSellitemsg, Yii::$app->request->post());
$deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($modelsSellitemsg, 'id', 'id')));
// validate all models
$valid = $model->validate();
$valid = Model::validateMultiple($modelsSellitemsg) && $valid;
if ($valid) {
$transaction = \Yii::$app->db->beginTransaction();
try {
if ($flag = $model->save(false)) {
if (! empty($deletedIDs)) {
Sellitemsg::deleteAll(['id' => $deletedIDs]);
}
foreach ($modelsSellitemsg as $modelSellitemsg) {
$modelSellitemsg->ssgi_invoiceno = $model->ssg_invoiceno;
if (! ($flag = $modelSellitemsg->save(false))) {
$transaction->rollBack();
break;
}
}
}
if ($flag) {
$transaction->commit();
return $this->redirect(['view', 'id' => $model->ssg_id]);
}
} catch (Exception $e) {
$transaction->rollBack();
}
}
}
else {
return $this->render('update', [
'model' => $model,
'modelsSellitemsg' => (empty($modelsSellitemsg)) ? [new Sellitemsg] : $modelsSellitemsg
]);
}
}
sellsg model
<?php
namespace frontend\modules\sellsg\models;
use Yii;
/**
* This is the model class for table "sellsg".
*
* #property integer $ssg_id
* #property string $ssg_customer
* #property integer $ssg_invoiceno
* #property string $ssg_date
* #property integer $ssg_amount
*/
class Sellsg extends \yii\db\ActiveRecord
{
public $modelsSellitemsg;
/**
* #inheritdoc
*/
public static function tableName()
{
return 'sellsg';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['ssg_customer', 'ssg_invoiceno', 'ssg_date', 'ssg_amount'], 'required'],
[['ssg_invoiceno', 'ssg_amount'], 'integer'],
[['ssg_customer'], 'string', 'max' => 200],
[['ssg_invoiceno'], 'unique'],
[['ssg_date'], 'string', 'max' => 10],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'ssg_id' => 'ID',
'ssg_customer' => 'Customer',
'ssg_invoiceno' => 'Invoice No',
'ssg_date' => 'Date',
'ssg_amount' => 'Amount',
];
}
public function getSellitemsg()
{
return $this->hasMany(Sellitemsg::className(), ['ssgi_invoiceno' => 'ssg_invoiceno']);
}
}
update.php
<?php
use yii\helpers\Html;
/* #var $this yii\web\View */
/* #var $model frontend\modules\sellsg\models\Sellsg */
$this->title = 'Update Sellsg: ' . $model->ssg_id;
$this->params['breadcrumbs'][] = ['label' => 'Sellsgs', 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => $model->ssg_id, 'url' => ['view', 'id' => $model->ssg_id]];
$this->params['breadcrumbs'][] = 'Update';
?>
<div class="sellsg-update">
<h1><?= Html::encode($this->title) ?></h1>
<?= $this->render('_form', [
'model' => $model,
'modelsSellitemsg' => $modelsSellitemsg,
]) ?>
</div>
With the current code I'm getting error
Getting unknown property: frontend\modules\sellsg\models\Sellitemsg::id
I've found the solution
Problem1 -
I've created _updateform.php and redirected to update from there and removed the javascript to load invoicno -
Update.php
<?php
use yii\helpers\Html;
/* #var $this yii\web\View */
/* #var $model frontend\modules\sellsg\models\Sellsg */
$this->title = 'Update InvoiceNo: ' . $model->ssg_id;
$this->params['breadcrumbs'][] = ['label' => 'Sellsgs', 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => $model->ssg_id, 'url' => ['view', 'id' => $model->ssg_id]];
$this->params['breadcrumbs'][] = 'Update';
?>
<div class="sellsg-update">
<h1><?= Html::encode($this->title) ?></h1>
<?= $this->render('_updateform', [
'model' => $model,
'modelsSellitemsg' => $modelsSellitemsg,
]) ?>
</div>
Problem2
My actionUpdate code now looks like -
public function actionUpdate($id)
{
$model = $this->findModel($id);
$modelsSellitemsg = $model->sellitemsg;
//$model->setScenario('update');
if ($model->load(Yii::$app->request->post()) && $model->save()) {
$oldIDs = ArrayHelper::map($modelsSellitemsg, 'ssgi_id', 'ssgi_id');
//var_dump($oldIDs);
$modelsSellitemsg = Model::createMultiple(Sellitemsg::classname(), $modelsSellitemsg);
Model::loadMultiple($modelsSellitemsg, Yii::$app->request->post());
$deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($modelsSellitemsg, 'ssgi_id', 'ssgi_id')));
// validate all models
$valid = $model->validate();
$valid = Model::validateMultiple($modelsSellitemsg) && $valid;
if ($valid) {
$transaction = \Yii::$app->db->beginTransaction();
try {
if ($flag = $model->save(false)) {
if (! empty($deletedIDs)) {
Sellitemsg::deleteAll(['ssgi_id' => $deletedIDs]);
}
foreach ($modelsSellitemsg as $modelSellitemsg) {
$modelSellitemsg->ssgi_invoiceno = $model->ssg_invoiceno;
if (! ($flag = $modelSellitemsg->save(false))) {
$transaction->rollBack();
break;
}
}
}
if ($flag) {
$transaction->commit();
return $this->redirect(['view', 'id' => $model->ssg_id]);
}
} catch (Exception $e) {
$transaction->rollBack();
}
}
}
else {
return $this->render('update', [
'model' => $model,
'modelsSellitemsg' => (empty($modelsSellitemsg)) ? [new Sellitemsg] : $modelsSellitemsg
]);
}
}
/**
* Deletes an existing Sellsg 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']);
}
and Model.php -
<?php
namespace frontend\modules\sellsg\models;
use Yii;
use yii\helpers\ArrayHelper;
class Model extends \yii\base\Model
{
/**
* Creates and populates a set of models.
*
* #param string $modelClass
* #param array $multipleModels
* #return array
*/
public static function createMultiple($modelClass, $multipleModels = [])
{
$model = new $modelClass;
$formName = $model->formName();
$post = Yii::$app->request->post($formName);
$models = [];
if (! empty($multipleModels)) {
$keys = array_keys(ArrayHelper::map($multipleModels, 'ssgi_id', 'ssgi_id'));
$multipleModels = array_combine($keys, $multipleModels);
}
if ($post && is_array($post)) {
foreach ($post as $i => $item) {
if (isset($item['ssgi_id']) && !empty($item['ssgi_id']) && isset($multipleModels[$item['ssgi_id']])) {
$models[] = $multipleModels[$item['ssgi_id']];
} else {
$models[] = new $modelClass;
}
}
}
unset($model, $formName, $post);
return $models;
}
}
And Is working fine now.

yii2 dynamic form inserting data in one model only

I'm trying to incorporate wbraganca dynamic form in yii2. But it's inserting data in only bills table(equivalent to the customer table) but not in productsales table(equivalent to address table). I'm not getting where the error is. There's no error in the console. After hitting the create button the page goes blank with a white screen. I can see data inserted in the bills table but not in productsales table.
_form.php in bills -
<?php
use yii\helpers\Html;
use yii\helpers\Url;
use kartik\form\ActiveForm;
use dosamigos\datepicker\DatePicker;
use yii\helpers\ArrayHelper;
use kartik\select2\Select2;
use yii\helpers\Json;
use yii\web\View;
use frontend\modules\invoice\models\Parties;
use frontend\modules\invoice\models\Productbatch;
use frontend\modules\invoice\models\Year;
use frontend\modules\invoice\models\Console;
use wbraganca\dynamicform\DynamicFormWidget;
use kartik\depdrop\DepDrop;
/* #var $this yii\web\View */
/* #var $model frontend\modules\invoice\models\Bills */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="bills-form">
<?php $form = ActiveForm::begin([
'id' => 'dynamic-form',
'type' => ActiveForm::TYPE_HORIZONTAL,
'formConfig' => ['labelSpan' => 3, 'deviceSize' => ActiveForm::SIZE_SMALL]
]); ?>
<div class="row">
<div class="form-group">
<div class="col-xs-9 col-sm-9 col-lg-9">
<?= $form->field($model, 'bills_partyname')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Parties::find()->orderBy(['parties_partyname' => SORT_ASC,])->all(),'parties_partyname','partyDetails'),
'language' => 'en',
'options' => ['placeholder' => 'Select Party Name', 'id' => 'partyid'],
'pluginOptions' => [
'allowClear' => true
],
]); ?>
</div>
<div class="col-xs-3 col-sm-3 col-lg-3">
<?= $form->field($model, 'transport')->textInput(['maxlength' => true]) ?>
</div>
</div>
<div class="form-group">
<div class="col-xs-3 col-sm-3 col-lg-3">
<?= $form->field($model, 'bills_year')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Year::find()->orderBy(['yid' => SORT_DESC,])->all(),'year_year','year_year'),
'language' => 'en',
'options' => ['placeholder' => 'Select Year', 'id' => 'yearid'],
'pluginOptions' => [
'allowClear' => true
],
]); ?>
</div>
<div class="col-xs-3 col-sm-3 col-lg-3">
<?= $form->field($model, 'console')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Console::find()->orderBy(['consoleid' => SORT_ASC,])->all(),'console','console'),
'language' => 'en',
'options' => ['placeholder' => 'Select Console','id' => 'consoleid'],
'pluginOptions' => [
'allowClear' => true
],
]); ?>
</div>
<div class="col-xs-3 col-sm-3 col-lg-3">
<?= $form->field($model, 'billno')->textInput(['maxlength' => true,'readOnly'=>true]) ?>
</div>
<div class="col-xs-3 col-sm-3 col-lg-3">
<?= $form->field($model, 'billdate')->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>
<?= $form->field($model, 'bills_ebillid')->textInput()->hiddenInput()->label(false) ?>
<?= $form->field($model, 'num')->textInput()->hiddenInput()->label(false) ?>
</div>
<div class="row">
<div class="panel panel-default">
<div class="panel-heading"><h4><i class="glyphicon glyphicon-envelope"></i> Products</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' => 1, // 0 or 1 (default 1)
'insertButton' => '.add-item', // css class
'deleteButton' => '.remove-item', // css class
'model' => $modelsProductsales[0],
'formId' => 'dynamic-form',
'formFields' => [
//'itemid',
'productname',
//'batchno',
// 'expdate',
// 'mrp',
// 'rate',
// 'qty',
// 'free',
// 'total',
// 'discount',
],
]); ?>
<div class="container-items"><!-- widgetContainer -->
<?php foreach ($modelsProductsales as $i => $modelsProductsales): ?>
<div class="item panel panel-default"><!-- widgetBody -->
<div class="panel-heading">
<h3 class="panel-title pull-left">Products</h3>
<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 (! $modelsProductsales->isNewRecord) {
echo Html::activeHiddenInput($modelsProductsales, "[{$i}]id");
}
?>
<div class="row-fluid">
<div class="form-group">
<div class="col-xs-3 col-sm-3 col-lg-3">
<?= $form->field($modelsProductsales, "[{$i}]productname")->label(false)->textInput(['maxlength' => true,'placeholder' => 'Productname']) ?>
</div>
<div class="col-xs-1 col-sm-1 col-lg-1 nopadding">
<?= $form->field($modelsProductsales, "[{$i}]batchno")->label(false)->textInput(['maxlength' => true,'placeholder' => 'Batchno']) ?>
</div>
<div class="col-xs-1 col-sm-1 col-lg-1 nopadding" >
<?= $form->field($modelsProductsales, "[{$i}]expdate")->label(false)->textInput(['maxlength' => true,'placeholder' => 'ExpDate']) ?>
</div>
<div class="col-xs-1 col-sm-1 col-lg-1 nopadding">
<?= $form->field($modelsProductsales, "[{$i}]mrp")->label(false)->textInput(['maxlength' => true,'placeholder' => 'MRP']) ?>
</div>
<div class="col-xs-1 col-sm-1 col-lg-1 nopadding">
<?= $form->field($modelsProductsales, "[{$i}]rate")->label(false)->textInput(['maxlength' => true,'placeholder' => 'Rate']) ?>
</div>
<div class="col-xs-1 col-sm-1 col-lg-1 nopadding">
<?= $form->field($modelsProductsales, "[{$i}]qty")->label(false)->textInput(['maxlength' => true,'placeholder' => 'Qty']) ?>
</div>
<div class="col-xs-1 col-sm-1 col-lg-1 nopadding">
<?= $form->field($modelsProductsales, "[{$i}]free")->label(false)->textInput(['maxlength' => true,'placeholder' => 'Free']) ?>
</div>
<div class="col-xs-1 col-sm-1 col-lg-1 nopadding">
<?= $form->field($modelsProductsales, "[{$i}]discount")->label(false)->textInput(['maxlength' => true,'placeholder' => 'Discount']) ?>
</div>
</div>
<?= $form->field($modelsProductsales, "[{$i}]itemid")->textInput(['maxlength' => true]) ?>
<?= $form->field($modelsProductsales, "[{$i}]total")->textInput(['maxlength' => true]) ?>
</div><!-- .row -->
</div>
</div><!-- item panel default -->
<?php endforeach; ?>
</div><!-- container item -->
<?php DynamicFormWidget::end(); ?>
</div><!-- panel body -->
</div><!-- panel default -->
</div><!-- outer row -->
<?= $form->field($model, 'billamount')->textInput() ?>
<?= $form->field($model, 'overdue')->textInput() ?>
<?= $form->field($model, 'cst')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'wbst')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'caseno')->textInput() ?>
<?= $form->field($model, 'amount')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'discount')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'tot')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'surcharge')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'total')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'tax')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'mrpvalue')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'cstpercent')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'wbstpercent')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'surpercent')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'totpercent')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'transport')->textInput(['maxlength' => true]) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
<?php
/* start getting the transportdata */
$script = <<< JS
$('#partyid').change(function(){
var partyid = $(this).val();
$.get('index.php?r=invoice/bills/get-for-party',{ partyid : partyid }, function(data){
//alert(data);
var data = $.parseJSON(data);
$('#bills-transport').attr('value',data.transport);
});
});
JS;
$this->registerJs($script);
/* end getting the transportdata */
?>
<?php
/* start getting the ebilid */
$script = <<<EOD
$(window).load(function(){
$.get('index.php?r=invoice/bills/get-for-ebillid',{ ebillid : 1 }, function(data){
//alert(data);
var data = $.parseJSON(data);
$('#bills-bills_ebillid').attr('value',data.ebillid);
}
);
});
EOD;
$this->registerJs($script);
/*end getting the ebillid */
?>
<?php
/* start getting the num */
$script = <<< JS
$(function(){
$('#yearid').change(function(){
getNum();
});
$('#consoleid').change(function(){
getNum();
});
var yearid = $(this).val();
var consoleid = $(this).val();
var getNum = function(){
var yearid = String($('#yearid').val());
var consoleid = String($('#consoleid').val());
$.get('index.php?r=invoice/bills/get-for-num',{ yearid : yearid, consoleid : consoleid }, function(data){
//alert(data);
var data = $.parseJSON(data);
var getNum = data;
$('#bills-num').val(getNum["num"]);
});
} ;
});
JS;
$this->registerJs($script);
/* end getting the num */
?>
<?php
/* start getting the billno */
$script = <<< JS
$(function(){
$('#yearid').change(function(){
getBillno();
});
$('#consoleid').change(function(){
getBillno();
});
var yearid = $(this).val();
var consoleid = $(this).val();
var getBillno = function(){
var yearid = String($('#yearid').val());
var consoleid = String($('#consoleid').val());
$.get('index.php?r=invoice/bills/get-for-billno',{ yearid : yearid, consoleid : consoleid }, function(data){
//alert(data);
var data = $.parseJSON(data);
var getBillno = data;
$('#bills-billno').val(getBillno["billno"]);
});
} ;
});
JS;
$this->registerJs($script);
/* end getting the billno */
?>
BillsController
<?php
namespace frontend\modules\invoice\controllers;
use Yii;
use frontend\modules\invoice\models\Bills;
use frontend\modules\invoice\models\BillsSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use frontend\modules\invoice\models\Parties;
use frontend\modules\invoice\models\Productsales;
use frontend\modules\invoice\models\Productbatch;
use frontend\modules\invoice\models\Model;
use yii\helpers\Json;
/**
* BillsController implements the CRUD actions for Bills model.
*/
class BillsController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all Bills models.
* #return mixed
*/
public function actionIndex()
{
$searchModel = new BillsSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single Bills model.
* #param string $id
* #return mixed
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Bills model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new Bills();
$modelsProductsales = [new Productsales];
if ($model->load(Yii::$app->request->post()) && $model->save()) {
$modelsProductsales = Model::createMultiple(Productsales::classname());
Model::loadMultiple($modelsProductsales, Yii::$app->request->post());
// validate all models
$valid = $model->validate();
$valid = Model::validateMultiple($modelsProductsales) && $valid;
if ($valid) {
$transaction = \Yii::$app->db->beginTransaction();
try {
if ($flag = $model->save(false)) {
foreach ($modelsProductsales as $modelProductsales) {
$modelProductsales->productsales_ebillid = $model->bills_ebillid;
$modelProductsales->year = $model->bills_year;
$modelProductsales->console = $model->console;
$modelProductsales->billno = $model->billno;
$modelProductsales->billdate = $model->billdate;
$modelProductsales->productsales_partyname = $model->bills_partyname;
if (! ($flag = $modelProductsales->save(false))) {
$transaction->rollBack();
break;
}
}
}
if ($flag) {
$transaction->commit();
return $this->redirect(['view', 'id' => $model->id]);
}
} catch (Exception $e) {
$transaction->rollBack();
}
}
}
//return $this->redirect(['view', 'id' => $model->billid]);
else {
return $this->render('create', [
'model' => $model,
'modelsProductsales' => (empty($modelsProductsales)) ? [new Productsales] : $modelsProductsales
]);
}
}
/**
* Updates an existing Bills model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param string $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->billid]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
/**
* Deletes an existing Bills model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param string $id
* #return mixed
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
public function actionGetForParty($partyid)
{
$party = Parties::find()->where(['parties_partyname'=>$partyid])->asArray()->one();
//$bottle -> select(['productnames.productnames_productname','productnames.bottletype','bottlename.unitprice'])->from('Productnames')->leftJoin('bottlename','productnames.bottletype = bottlename.bottlename')->where(['productnames_productname'=>$catid])->limit(1);
echo Json::encode($party);
}
public function actionGetForEbillid($ebillid)
{
$ebillidvar = Bills::find()->select('(max(bills_ebillid) + 1) as ebillid')->asArray()->one();
echo Json::encode($ebillidvar);
}
public function actionGetForNum($yearid , $consoleid)
{
$num = Bills::find()->select('(max(num) + 1) as num')->where(['bills_year'=>$yearid])->andWhere(['console'=>$consoleid])->asArray()->one();
echo Json::encode($num);
}
public function actionGetForItemid($productid , $batchid)
{
$item = Productbatch::find()->select('max(itemid) as itemid')->where(['productname'=>$productid])->andWhere(['batchno'=>$batchid])->asArray()->one();
echo Json::encode($item);
}
public function actionGetForBillno($yearid , $consoleid)
{
if($consoleid == 'GM1' || $consoleid == 'GM2'){
$num = Bills::find()->select(['concat("GM/",(max(num) + 1)) as billno'])->where(['bills_year'=>$yearid])->andWhere(['console'=>$consoleid])->asArray()->one();
echo Json::encode($num);
}elseif($consoleid == 'SM1' || $consoleid == 'SM2'){
$num = Bills::find()->select(['concat("SM/",(max(num) + 1)) as billno'])->where(['bills_year'=>$yearid])->andWhere(['console'=>$consoleid])->asArray()->one();
echo Json::encode($num);
}elseif($consoleid == 'CN'){
$num = Bills::find()->select(['concat("CM/",(max(num) + 1)) as billno'])->where(['bills_year'=>$yearid])->andWhere(['console'=>$consoleid])->asArray()->one();
echo Json::encode($num);
}
}
public function actionSubcat() {
$out = [];
if (isset($_POST['depdrop_parents'])) {
$parents = $_POST['depdrop_parents'];
if ($parents != null) {
$cat_id = $parents[0];
$out = Productbatch::getBatchNo($cat_id);
echo Json::encode($out);
// the getSubCatList function will query the database based on the
// cat_id and return an array like below:
// [
// ['id'=>'<sub-cat-id-1>', 'name'=>'<sub-cat-name1>'],
// ['id'=>'<sub-cat_id_2>', 'name'=>'<sub-cat-name2>']
// ]
//echo Json::encode(['output'=>$out, 'selected'=>'']);
return;
}
}
echo Json::encode(['output'=>'', 'selected'=>'']);
}
/**
* Finds the Bills model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param string $id
* #return Bills the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Bills::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}
Create.php
<?php
use yii\helpers\Html;
/* #var $this yii\web\View */
/* #var $model frontend\modules\invoice\models\Bills */
$this->title = 'Create Bills';
$this->params['breadcrumbs'][] = ['label' => 'Bills', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="bills-create">
<h1><?= Html::encode($this->title) ?></h1>
<?= $this->render('_form', [
'model' => $model,
'modelsProductsales' => $modelsProductsales,
]) ?>
</div>
Model.php
<?php
namespace frontend\modules\invoice\models;
use Yii;
use yii\helpers\ArrayHelper;
class Model extends \yii\base\Model
{
/**
* Creates and populates a set of models.
*
* #param string $modelClass
* #param array $multipleModels
* #return array
*/
public static function createMultiple($modelClass, $multipleModels = [])
{
$model = new $modelClass;
$formName = $model->formName();
$post = Yii::$app->request->post($formName);
$models = [];
if (! empty($multipleModels)) {
$keys = array_keys(ArrayHelper::map($multipleModels, 'id', 'id'));
$multipleModels = array_combine($keys, $multipleModels);
}
if ($post && is_array($post)) {
foreach ($post as $i => $item) {
if (isset($item['id']) && !empty($item['id']) && isset($multipleModels[$item['id']])) {
$models[] = $multipleModels[$item['id']];
} else {
$models[] = new $modelClass;
}
}
}
unset($model, $formName, $post);
return $models;
}
}

Same index for all dynamic items - Nested dynamic form Yii2

I am getting same index( 0 ) for all new items rather than incremented index. I dont know what and where is wrong with my code. i am working on this by referring to this demo Nested Dynamic Form - Yii2. sorry for my bad english.
My Controller
This is my controller.
public function actionUpdateperkara($id)
{
$model = $this->findModel($id);
$modelsPerkaraSatu = $model->tblMinitperkaras;
$modelsPerkaraDua = [];
$oldPerkaraDuas = [];
if (!empty($modelsPerkaraSatu)) {
foreach ($modelsPerkaraSatu as $indexPerkaraSatu => $modelPerkaraSatu) {
$perkaraduas = $modelPerkaraSatu->tblMinitperkara2s;
$modelsPerkaraDua[$indexPerkaraSatu] = $perkaraduas;
$oldPerkaraDuas = ArrayHelper::merge(ArrayHelper::index($perkaraduas, 'per_id'), $oldPerkaraDuas);
}
}
if ($model->load(Yii::$app->request->post())) {
// reset
$modelsPerkaraDua = [];
$oldPerkaraSatuIDs = ArrayHelper::map($modelsPerkaraSatu, 'perkara_id', 'perkara_id');
$modelsPerkaraSatu = ModelPerkara::createMultiple(TblMinitperkara::classname(), $modelsPerkaraSatu);
ModelPerkara::loadMultiple($modelsPerkaraSatu, Yii::$app->request->post());
$deletedPerkaraSatuIDs = array_diff($oldPerkaraSatuIDs, array_filter(ArrayHelper::map($modelsPerkaraSatu, 'perkara_id', 'perkara_id')));
// validate model and tblMinitperkaras models
$valid = $model->validate();
$valid = ModelPerkara::validateMultiple($modelsPerkaraSatu) && $valid;
$perkaraDuasIDs = [];
if (isset($_POST['TblMinitperkara2'][0][0])) {
foreach ($_POST['TblMinitperkara2'] as $indexPerkaraSatu => $perkaraduas) {
$perkaraDuasIDs = ArrayHelper::merge($perkaraDuasIDs, array_filter(ArrayHelper::getColumn($perkaraduas, 'per_id')));
foreach ($perkaraduas as $indexPerkaraDua => $perkaradua) {
$data['TblMinitperkara2'] = $perkaradua;
$modelPerkaraDua = (isset($perkaradua['per_id']) && isset($oldPerkaraDuas[$perkaradua['per_id']])) ? $oldPerkaraDuas[$perkaradua['per_id']] : new TblMinitperkara2;
$modelPerkaraDua->load($data);
$modelsPerkaraDua[$indexPerkaraSatu][$indexPerkaraDua] = $modelPerkaraDua;
$valid = $modelPerkaraDua->validate();
}
}
}
$oldPerkaraDuasIDs = ArrayHelper::getColumn($oldPerkaraDuas, 'per_id');
$deletedPerkaraDuasIDs = array_diff($oldPerkaraDuasIDs, $perkaraDuasIDs);
if ($valid) {
$transaction = Yii::$app->db->beginTransaction();
try {
if ($flag = $model->save(false)) {
if (! empty($deletedPerkaraDuasIDs)) {
TblMinitperkara2::deleteAll(['per_id' => $deletedPerkaraDuasIDs]);
}
if (! empty($deletedPerkaraSatuIDs)) {
TblMinitperkara::deleteAll(['perkara_id' => $deletedPerkaraSatuIDs]);
}
foreach ($modelsPerkaraSatu as $indexPerkaraSatu => $modelPerkaraSatu) {
if ($flag === false) {
break;
}
$modelPerkaraSatu->butir_id = $model->butir_id;
if (!($flag = $modelPerkaraSatu->save(false))) {
break;
}
if (isset($modelsPerkaraDua[$indexPerkaraSatu]) && is_array($modelsPerkaraDua[$indexPerkaraSatu])) {
foreach ($modelsPerkaraDua[$indexPerkaraSatu] as $indexPerkaraDua => $modelPerkaraDua) {
$modelPerkaraDua->perkara_id = $modelPerkaraSatu->perkara_id;
if (!($flag = $modelPerkaraDua->save(false))) {
break;
}
}
}
}
}
if ($flag) {
$transaction->commit();
return $this->redirect(['view', 'id' => $model->butir_id]);
}
else {
$transaction->rollBack();
}
}
catch (Exception $e) {
$transaction->rollBack();
}
}
}
return $this->render('_form_perkara', [
'model' => $model,
'modelsPerkaraSatu' => (empty($modelsPerkaraSatu)) ? [new TblMinitperkara] : $modelsPerkaraSatu,
'modelsPerkaraDua' => (empty($modelsPerkaraDua)) ? [[new TblMinitperkara2]] : $modelsPerkaraDua
]);
}
_form_perkara
This is my form.
<?php
use yii\helpers\Html;
use yii\helpers\ArrayHelper;
use yii\helpers\Url;
use yii\widgets\ActiveForm;
use wbraganca\dynamicform\DynamicFormWidget;
use yii\jui\JuiAsset;
use yii\web\Response;
use yii\web\JsExpression;
use kartik\file\FileInput;
use kartik\date\DatePicker;
use kartik\time\TimePicker;
/* #var $this yii\web\View */
/* #var $model frontend\models\TblMinitbutiran */
/* #var $form yii\widgets\ActiveForm */
$this->title = 'Minit Mesyuarat : ' . $model->butir_id;
$this->params['breadcrumbs'][] = ['label' => 'Senarai Minit Mesyuarat', 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => 'Minit Mesyuarat : ' . $model->butir_id, 'url' => ['view', 'id' => $model->butir_id]];
$this->params['breadcrumbs'][] = 'Butiran Perkara';
?>
<div>
<?php $form = ActiveForm::begin(['id' => 'dynamic-form']); ?>
<div class="panel panel-primary">
<div class="panel-heading"><b>Butiran Mesyuarat</b></div>
<div class="panel-body">
<div class="col-sm-3 ">
<?= $form->field($model, 'butir_bil')->textInput(['maxlength' => true]) ?>
</div>
<div class="col-sm-4 ">
<?= $form->field($model, 'butir_tarikh')->widget(DatePicker::classname(), [
'options' => ['placeholder' => 'pilih tarikh mesyuarat'],
'pluginOptions' => [
'format' => 'yyyy-mm-dd',
'endDate' => '+0d',
'autoclose'=>true
]
]); ?>
<?= $form->field($model, 'butir_masa')->widget(TimePicker::classname(), [
'pluginOptions' => [
'showMeridian'=>false
]
]); ?>
</div>
<div class="col-sm-5">
<?= $form->field($model, 'butir_tempat')->textarea(['rows' => 4]) ?>
</div>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading"><b>Perkara</b></div>
<div class="panel-body">
<?php DynamicFormWidget::begin([
'widgetContainer' => 'dynamicform_wrapper',
'widgetBody' => '.container-items',
'widgetItem' => '.house-item',
'min' => 1,
'insertButton' => '.add-house',
'deleteButton' => '.remove-house',
'model' => $modelsPerkaraSatu[0],
'formId' => 'dynamic-form',
'formFields' => [
'perkara_bil',
'perkara_perkara',
],
]); ?>
<div>
<div>
<div style="overflow:hidden; height:30px;">
<div class="col-md-1 alert alert-info" role="alert" style="padding:5px; height:50px; text-align:left"><b>BIL</b></div>
<div class="col-md-9 alert alert-info" role="alert" style="padding:5px; height:50px; text-align:left"><b>PERKARA</b></div>
<div class="col-md-2 alert alert-info" role="alert" style="padding:5px; height:50px; text-align:left"><b>TINDAKAN / MAKLUMAN</b></div>
</div>
</div>
<div class="container-items">
<?php foreach ($modelsPerkaraSatu as $indexPerkaraSatu => $modelPerkaraSatu): ?>
<div class="house-item">
<div class="col-md-1 alert alert-info" role="alert" style="padding:5px; height:50px; text-align:center">
<?php
// necessary for update action.
if (! $modelPerkaraSatu->isNewRecord) {
echo Html::activeHiddenInput($modelPerkaraSatu, "[{$indexPerkaraSatu}]perkara_id");
}
?>
<?= $form->field($modelPerkaraSatu, "[{$indexPerkaraSatu}]perkara_bil")->label(false)->textInput(['maxlength' => true]) ?>
</div>
<div class="col-md-9 alert alert-info" role="alert" style="padding:5px; height:50px; text-align:center">
<?= $form->field($modelPerkaraSatu, "[{$indexPerkaraSatu}]perkara_perkara")->label(false)->textInput(['maxlength' => true]) ?>
</div>
<div class="col-md-2 alert alert-info" role="alert" style="padding:5px; height:50px; text-align:center">
<button type="button" class="add-house btn btn-success btn-xs"><span class="glyphicon glyphicon-plus"></span></button>
<button type="button" class="remove-house btn btn-danger btn-xs"><span class="glyphicon glyphicon-minus"></span></button>
</div>
<?= $this->render('_form_perkara2', [
'form' => $form,
'indexPerkaraSatu' => $indexPerkaraSatu,
'modelsPerkaraDua' => $modelsPerkaraDua[$indexPerkaraSatu],
]) ?>
</div>
<?php endforeach; ?>
</div>
</div>
<?php DynamicFormWidget::end(); ?>
</div>
</div>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Hantar' : 'Hantar', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
<script type="text/javascript">
$(".dynamicform_wrapper").on("beforeInsert", function(e, item) {
console.log("beforeInsert");
});
$(".dynamicform_wrapper").on("afterInsert", function(e, item) {
console.log("afterInsert");
});
$(".dynamicform_wrapper").on("beforeDelete", function(e, item) {
if (! confirm("Are you sure you want to delete this item?")) {
return false;
}
return true;
});
$(".dynamicform_wrapper").on("afterDelete", function(e) {
console.log("Deleted item!");
});
$(".dynamicform_wrapper").on("limitReached", function(e, item) {
alert("Limit reached");
});
</script>
_form_perkara2
<?php
use yii\helpers\Html;
use wbraganca\dynamicform\DynamicFormWidget;
?>
<?php DynamicFormWidget::begin([
'widgetContainer' => 'dynamicform_inner',
'widgetBody' => '.container-rooms',
'widgetItem' => '.room-item',
'min' => 1,
'insertButton' => '.add-room',
'deleteButton' => '.remove-room',
'model' => $modelsPerkaraDua[0],
'formId' => 'dynamic-form',
'formFields' => [
'per_no',
'per_butiran',
'per_maklumat'
],
]); ?>
<div class="container-rooms" style="align:center">
<?php foreach ($modelsPerkaraDua as $indexPerkaraDua => $modelPerkaraDua): ?>
<div class="room-item">
<div class="col-md-1 alert alert-danger" role="alert" style="padding:5px; height:50px; text-align:center">
<button type="button" class="add-room btn btn-primary btn-xs"><span class="glyphicon glyphicon-plus"></span></button>
<button type="button" class="remove-room btn btn-warning btn-xs"><span class="glyphicon glyphicon-minus"></span></button>
</div>
<div class="col-md-1 alert alert-danger" role="alert" style="padding:5px; height:50px; text-align:center">
<?php
// necessary for update action.
if (! $modelPerkaraDua->isNewRecord) {
echo Html::activeHiddenInput($modelPerkaraDua, "[{$indexPerkaraSatu}][{$indexPerkaraDua}]per_id");
}
?>
<?= $form->field($modelPerkaraDua, "[{$indexPerkaraSatu}][{$indexPerkaraDua}]per_no")->label(false)->textInput(['maxlength' => true]) ?>
</div>
<div class="col-md-8 alert alert-danger" role="alert" style="padding:5px; height:50px; text-align:center">
<?= $form->field($modelPerkaraDua, "[{$indexPerkaraSatu}][{$indexPerkaraDua}]per_butiran")->label(false)->textInput(['maxlength' => true]) ?>
</div>
<div class="col-md-2 alert alert-danger" role="alert" style="padding:5px; height:50px; text-align:center">
<?= $form->field($modelPerkaraDua, "[{$indexPerkaraSatu}][{$indexPerkaraDua}]per_maklumat")->label(false)->textInput(['maxlength' => true]) ?>
</div>
</div>
<?php endforeach; ?>
</div>
<?php DynamicFormWidget::end(); ?>
ModelPerkara class
<?php
namespace frontend\models;
use Yii;
use yii\helpers\ArrayHelper;
class ModelPerkara extends \yii\base\Model
{
/**
* Creates and populates a set of models.
*
* #param string $modelClass
* #param array $multipleModels
* #return array
*/
public static function createMultiple($modelClass, $multipleModels = [])
{
$model = new $modelClass;
$formName = $model->formName();
$post = Yii::$app->request->post($formName);
$models = [];
if (! empty($multipleModels)) {
$keys = array_keys(ArrayHelper::map($multipleModels, 'perkara_id', 'perkara_id'));
$multipleModels = array_combine($keys, $multipleModels);
}
if ($post && is_array($post)) {
foreach ($post as $indexPerkaraSatu => $item) {
if (isset($item['perkara_id']) && !empty($item['perkara_id']) && isset($multipleModels[$item['perkara_id']])) {
$models[] = $multipleModels[$item['perkara_id']];
} else {
$models[] = new $modelClass;
}
}
}
unset($model, $formName, $post);
return $models;
}
}
Screenshot of inspector
input id in second div of "house-item" is same with the first one. This show that the index is not increments
You need to add javascript events in your view file.
$js = '
jQuery(".dynamicform_wrapper").on("afterInsert", function(e, item) {
jQuery(".dynamicform_wrapper .panel-title-address").each(function(index) {
jQuery(this).html("Address: " + (index + 1))
});
});
jQuery(".dynamicform_wrapper").on("afterDelete", function(e) {
jQuery(".dynamicform_wrapper .panel-title-address").each(function(index) {
jQuery(this).html("Address: " + (index + 1))
});
});
';
$this->registerJs($js);