yii2-dynamicform
yii2-dynamicform copied to clipboard
Multiple nested widget example
It's possible to send me any example of deeper scenario with mutiple nested widget?
"Here's could be hypothetical scenario: A PERSON can have many HOUSES, each house, can have multiple ROOMS."
Thank you.
+1 one more example.. Thank you.
+1 My problem is when pressing add for the second level widget it add the first within. How can i separate forms. ?
Try to use different values for 'widgetBody' parameter in parent and child widgets Also, take unique values for 'insertButton' and 'deleteButton' for each child widget (i use foreach index)
Thank you for your prompt reply. Much appreciated
I hope wbraganca helps us.
did any find a it out how to do?
I don't think its supported in that manner. Otherwise we would know by now. I hope I'm wrong though :)
thats the picture he uploaded... so it musst be possible :D
this image isnt our scenario :(. really, look at it again...
is it possible with this widget to have Multiple nested inputs ???
Yes, is it possible @skeeran. I apologize for still have not added in the documentation an example of how to do this. I'll try to work on it this week.
okay cool Thank you. I am eagerly waiting for this example.
'dynamic-form']); ?>
is it possible to have multitple "dynamic-form" in the same view
I am also interested if I can have more dynamic forms in the same form.. If someone can help me, I would appreciate it!
@wbraganca can you show us the code used in the 'Demo 3 - (Nested Dynamic Form)'?
i am waiting for this example code over 3 months... will it be ever given ?
waiting for the example - please post
Suggest closing this issue - reference Wiki. https://github.com/wbraganca/yii2-dynamicform/wiki/Nested-Forms-Example
I'm having a problem with this solution. In my case then I change something in nested form (in my case is Program and ProgramItem) fe remove or add ProgramItem, the script adds empty record for each Program.
I check my code couple of time to find out if I missed something from the tutorial, but failed to find anthnig odd.
Here's the code.
public function actionUpdate($id)
{
$model = $this->findModel($id);
$this->oldFiles = $model->getImageFiles();
$this->oldFileNames = $model->getImageFileNames();
// retrieve existing Payment data
$oldProgramIds = Program::find()->select('id')->asArray()->all();
$oldProgramIds = ArrayHelper::getColumn($oldProgramIds,'id');
$modelsProgram = Program::findAll(['id' => $oldProgramIds]);
$modelsProgram = (empty($modelsProgram)) ? [new Program()] : $modelsProgram;
// retrieve existing Loads data
$oldProgramItemIds = [];
foreach ($modelsProgram as $i => $modelProgram) {
$oldItems = ProgramItem::findAll(['program_id' => $modelProgram->id]);
$modelsProgramItem[$i] = $oldItems;
$oldProgramItemIds = array_merge($oldProgramItemIds,ArrayHelper::getColumn($oldItems,'id'));
$modelsProgramItem[$i] = (empty($modelsProgramItem[$i])) ? [new ProgramItem()] : $modelsProgramItem[$i];
}
if ($model->load(Yii::$app->request->post())){
$this->image = $model->uploadImage();
if($this->image === false){
$model->information_images = json_encode($this->oldFileNames);
}
$modelsProgram = DynamicForms::createMultiple(Program::className(),$modelsProgram);
DynamicForms::loadMultiple($modelsProgram, Yii::$app->request->post());
$newProgramIds = ArrayHelper::getColumn($modelsProgram,'id');
$newProgramItemIds = [];
$itemsData['_backendCsrf'] = Yii::$app->request->post()['_backendCsrf'];
for($i=0;$i<count($modelsProgram);$i++){
$itemsData['ProgramItem'] = Yii::$app->request->post()['ProgramItem'][$i];
$modelsProgramItem[$i] = DynamicForms::createMultiple(ProgramItem::classname(),$modelsProgramItem[$i] ,$itemsData);
DynamicForms::loadMultiple($modelsProgramItem[$i], $itemsData);
$newProgramItemIds = array_merge($newProgramItemIds,ArrayHelper::getColumn($itemsData['ProgramItem'],'id'));
}
// delete removed data
$delItemIds = array_diff($oldProgramItemIds,$newProgramItemIds);
if (! empty($delItemIds)) ProgramItem::deleteAll(['id' => $delItemIds]);
$delProgramIds = array_diff($oldProgramIds,$newProgramIds);
if (! empty($delProgramIds)) Program::deleteAll(['id' => $delProgramIds]);
// validate all models
$valid = $model->validate();
$valid = Program::validateInformation($modelsProgram, $modelsProgramItem);// && $valid;
// save deposit data
if ($valid) {
if ($this->saveInformation($model, $modelsProgram, $modelsProgramItem)) {
if($this->image !== false){
foreach($this->oldFiles as $of){
unlink($of);
}
foreach ($this->image as $i) {
$path = $model->getImageFile($i);
$i->saveAs($path);
}
}
Yii::$app->getSession()->setFlash('success','Zapisano wszystkie dane');
return $this->redirect(['update','id'=>$id]);
}
}
}
// show VIEW
return $this->render('update2', [
'model' => $model,
'modelsProgram' => $modelsProgram,
'modelsProgramItem' => $modelsProgramItem,
]);
}
I appreciate any help.
I attach my screens
how should be the _controller (actionUpdate & actionCreate) if i want to have two dynamic forms in one view
@cloudcaptain I'm using your solution and creation is working correctly, but the update is working partially in my case.
Let me explain using your example...
I can Create a Deposit with many Payments and many Loads for each Payment (works properly).
On Update, i can add some Loads for Payments, but when i try to add a new Payment and new Loads for this new Payment, i got an error Undefined offset: 2 // for example
The error occurs near this section:
// get Slots data from POST
$newSlotIds = [];
$loadsData['_csrf'] = Yii::$app->request->post()['_csrf'];
for ($i=0; $i < count($modelsGrupos); $i++) {
$loadsData['MissaoSlot'] = Yii::$app->request->post()['MissaoSlot'][$i];
// ERROR POINTS TO THE LINE BELOW
$modelsSlots[$i] = Model::createMultiple(MissaoSlot::classname(), $modelsSlots[$i], $loadsData);
Model::loadMultiple($modelsSlots[$i], $loadsData);
$newSlotIds = array_merge($newSlotIds, ArrayHelper::getColumn($loadsData['MissaoSlot'], 'id'));
}
I have reviewed all my code following his example and didn't find the error. Could you help me?
My Update Action in Controller:
public function actionUpdate($id)
{
// retrieve existing Missao (mission) data
$model = $this->findModel($id);
// retrieve existing Grupos (groups) data
$oldGrupoIds = MissaoGrupo::find()->select('id')->where(['missao_id' => $id])->asArray()->all();
$oldGrupoIds = ArrayHelper::getColumn($oldGrupoIds,'id');
$modelsGrupos = MissaoGrupo::findAll(['id' => $oldGrupoIds]);
$modelsGrupos = (empty($modelsGrupos)) ? [new MissaoGrupo] : $modelsGrupos;
// retrieve existing Slots data
$oldSlotIds = [];
foreach ($modelsGrupos as $i => $modelGrupo) {
$oldSlots = MissaoSlot::findAll(['grupo_id' => $modelGrupo->id]);
$modelsSlots[$i] = $oldSlots;
$oldSlotIds = array_merge($oldSlotIds, ArrayHelper::getColumn($oldSlots, 'id'));
$modelsSlots[$i] = (empty($modelsSlots[$i])) ? [new MissaoSlot()] : $modelsSlots[$i];
}
// handle POST
if ($model->load(Yii::$app->request->post())) {
// Pega os Grupos via POST
$modelsGrupos = Model::createMultiple(MissaoGrupo::classname(), $modelsGrupos);
Model::loadMultiple($modelsGrupos, Yii::$app->request->post());
$newGrupoIds = ArrayHelper::getColumn($modelsGrupos, 'id');
// get Slots data from POST
$newSlotIds = [];
$loadsData['_csrf'] = Yii::$app->request->post()['_csrf'];
for ($i=0; $i < count($modelsGrupos); $i++) {
$loadsData['MissaoSlot'] = Yii::$app->request->post()['MissaoSlot'][$i];
$modelsSlots[$i] = Model::createMultiple(MissaoSlot::classname(), $modelsSlots[$i], $loadsData);
Model::loadMultiple($modelsSlots[$i], $loadsData);
$newSlotIds = array_merge($newSlotIds, ArrayHelper::getColumn($loadsData['MissaoSlot'], 'id'));
}
// delete removed data
$delSlotIds = array_diff($oldSlotIds, $newSlotIds);
if (! empty($delSlotIds)) MissaoSlot::deleteAll(['id' => $delSlotIds]);
$delGrupoIds = array_diff($oldGrupoIds, $newGrupoIds);
if (! empty($delGrupoIds)) MissaoGrupo::deleteAll(['id' => $delGrupoIds]);
// validate all models
$valid = $model->validate();
$valid = $this->validaMissao($modelsGrupos, $modelsSlots) && $valid;
if ($valid) {
if ($this->saveMissao($model, $modelsGrupos, $modelsSlots)) {
return $this->redirect(['view', 'id' => $model->id]);
}
}
}
return $this->render('update', [
'model' => $model,
'modelsGrupos' => $modelsGrupos,
'modelsSlots' => $modelsSlots,
]);
}
Sorry for my bad english!
EDIT (SOLVED)
http://stackoverflow.com/questions/32585832/yii-2-nested-forms
plz let me see your validaMissao function
Of course:
public static function validaMissao($modelsGrupos, $modelsSlots)
{
$valid = true;
foreach ($modelsGrupos as $i => $modelGrupo) {
$valid = $modelGrupo->validate() && $valid;
$valid = Model::validateMultiple($modelsSlots[$i]) && $valid;
}
return $valid;
}
I solved the question above with StackOverflow help: http://stackoverflow.com/questions/32585832/yii-2-nested-forms
thx i solved actionCreate, but now I've been following the example for actionUpdate and i get this when i click on the update button
PHP Warning – yii\base\ErrorException
Invalid argument supplied for foreach()
1. in C:\wamp\www\advanced\vendor\yiisoft\yii2\helpers\BaseArrayHelper.php at line 371
362363364365366367368369370371372373374375376377378379380 * @param array $array
* @param string|\Closure $from
* @param string|\Closure $to
* @param string|\Closure $group
* @return array
*/
public static function map($array, $from, $to, $group = null)
{
$result = [];
foreach ($array as $element) {
$key = static::getValue($element, $from);
$value = static::getValue($element, $to);
if ($group !== null) {
$result[static::getValue($element, $group)][$key] = $value;
} else {
$result[$key] = $value;
}
}
could someone help me?
Please post your actionUpdate code and i'll try to help you.
public function actionUpdate($id)
{
$model = $this->findModel($id);
$modelsModelo01 = $model->modelo01;
$modelsModelo03 = $model->modelo03s;
$modelsModelo04 = $model->modelo04s;
// retrieve existing Modelo05 data
$oldModelo05Ids = Modelo05::find()->select('planificacion_fk')
->where(['planificacion_fk' => $id])->asArray()->all();
$oldModelo05Ids = ArrayHelper::getColumn($oldModelo05Ids,'planificacion_fk');
$modelsModelo05 = Modelo05::findAll(['planificacion_fk' => $oldModelo05Ids]);
$modelsModelo05 = (empty($modelsModelo05)) ? [new Modelo05] : $modelsModelo05;
// retrieve existing Implicados data
$oldImplicadosIds = [];
foreach ($modelsModelo05 as $i => $modelModelo05) {
$oldImplicados = Implicados::findAll(['modelo05_fk' => $modelModelo05->modelo05_no_registro]);
$modelsImplicados[$i] = $oldImplicados;
$oldImplicadosIds = array_merge($oldImplicadosIds,ArrayHelper::getColumn($oldImplicados,'modelo05_fk'));
$modelsImplicados[$i] = (empty($modelsImplicados[$i])) ? [new Implicados] : $modelsImplicados[$i];
}
if ($model->load(Yii::$app->request->post()) )
{
//modelo01
$oldIDs = ArrayHelper::map($modelsModelo01, 'planificacion_fk', 'planificacion_fk');
$modelsModelo01 = Model::createMultiple(Modelo01::classname(), $modelsModelo01);
Model::loadMultiple($modelsModelo01, Yii::$app->request->post());
$deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($modelsModelo01, 'planificacion_fk', 'planificacion_fk')));
//modelo03
$oldIDs1 = ArrayHelper::map($modelsModelo03, 'planificacion_fk', 'planificacion_fk');
$modelsModelo03 = Model::createMultiple(Modelo03::classname(), $modelsModelo03);
Model::loadMultiple($modelsModelo03, Yii::$app->request->post());
$deletedIDs1 = array_diff($oldIDs1, array_filter(ArrayHelper::map($modelsModelo03, 'planificacion_fk', 'planificacion_fk')));
//modelo04
$oldIDs2 = ArrayHelper::map($modelsModelo04, 'planificacion_fk', 'planificacion_fk');
$modelsModelo04 = Model::createMultiple(Modelo04::classname(), $modelsModelo04);
Model::loadMultiple($modelsModelo04, Yii::$app->request->post());
$deletedIDs2 = array_diff($oldIDs2, array_filter(ArrayHelper::map($modelsModelo04, 'planificacion_fk', 'planificacion_fk')));
//modelo05
$modelsModelo05 = Model::createMultiple(Modelo05::classname(), $modelsModelo05);
Model::loadMultiple($modelsModelo05, Yii::$app->request->post());
$newModelo05Ids = ArrayHelper::getColumn($newModelo05Ids,'planificacion_fk');
// implicados
$newImplicadosIds = [];
$implicadosData['_csrf'] = Yii::$app->request->post()['_csrf'];
for ($i=0; $i<count($modelsModelo05); $i++) {
$implicadosData['Implicados'] = Yii::$app->request->post()['Implicados'][$i];
$modelsImplicados[$i] = Model::createMultiple(Implicados::classname(),$modelsImplicados[$i] ,$implicadosData);
Model::loadMultiple($modelsImplicados[$i], $implicadosData);
$newImplicadosIds = array_merge($newImplicadosIds,ArrayHelper::getColumn($implicadosData['Implicados'],'modelo05_fk'));
}
// delete removed data
$delImplicadosIds = array_diff($oldImplicadosIds,$newImplicadosIds);
if (! empty($delImplicadosIds))
{
Implicados::deleteAll(['modelo05_fk' => $delImplicadosIds]);
}
$delModelo05Ids = array_diff($oldModelo05Ids,$newModelo05Ids);
if (! empty($delModelo05Ids))
{
Modelo05::deleteAll(['planificacion_fk' => $delModelo05Ids]);
}
// validate all models
$valid = $model->validate();
$valid = Model::validateMultiple($modelsModelo01) && $valid;
$valid1 = $model->validate();
$valid1 = Model::validateMultiple($modelsModelo03) && $valid1;
$valid2 = $model->validate();
$valid2 = Model::validateMultiple($modelsModelo04) && $valid2;
$valid3 = $model->validate();
$valid3 = Modelo05::validatePlanificacion($modelsModelo05,$modelsImplicados) && $valid3;
if ($valid && $valid1 && $valid2 && $valid3) {
$transaction = \Yii::$app->db->beginTransaction();
try {
if ($flag = $model->save(false)) {
if (! empty($deletedIDs) && ! empty($deletedIDs1) && ! empty($deletedIDs2)) {
Modelo01::deleteAll(['planificacion_fk' => $deletedIDs]);
Modelo03::deleteAll(['planificacion_fk' => $deletedIDs1]);
Modelo04::deleteAll(['planificacion_fk' => $deletedIDs2]);
}
foreach ($modelsModelo01 as $modelModelo01) {
$modelModelo01->planificacion_fk = $model->plan_cod;
if (! ($flag = $modelModelo01->save(false))) {
$transaction->rollBack();
break;
}
}
foreach ($modelsModelo03 as $modelModelo03) {
$modelModelo03->planificacion_fk = $model->plan_cod;
if (! ($flag = $modelModelo03->save(false))) {
$transaction->rollBack();
break;
}
}
foreach ($modelsModelo04 as $modelModelo04) {
$modelModelo04->planificacion_fk = $model->plan_cod;
if (! ($flag = $modelModelo04->save(false))) {
$transaction->rollBack();
break;
}
}
foreach ($modelsModelo05 as $i => $modelModelo05) {
// save the payment record
$modelModelo05->planificacion_fk = $model->plan_cod;
if ($flag = $modelModelo05->save(false)) {
// loop through each load
foreach ($modelsImplicados[$i] as $ix => $modelImplicados) {
// save the load record
$modelImplicados->modelo05_fk = $modelModelo05->modelo05_no_registro;
if (! ($flag = $modelImplicados->save(false))) {
$transaction->rollBack();
break;
}
}
}
}
}
if ($flag) {
$transaction->commit();
return $this->redirect(['view', 'id' => $model->plan_cod]);
}
} catch (Exception $e) {
$transaction->rollBack();
}
}
} else {
return $this->render('update', [
'model' => $model,
'modelsModelo01' => (empty($modelsModelo01)) ? [new Modelo01] : $modelsModelo01,
'modelsModelo03' => (empty($modelsModelo03)) ? [new Modelo03] : $modelsModelo03,
'modelsModelo04' => (empty($modelsModelo04)) ? [new Modelo04] : $modelsModelo04,
'modelsModelo05' => (empty($modelsModelo05)) ? [new Modelo05] : $modelsModelo05,
'modelsImplicados' => (empty($modelsImplicados)) ? [new Implicados] : $modelsImplicados
]);
}
}
Guys, I had the same issue here: i have a form with two nested forms in it, and the second form's add button appends a first nested form's item, I solved it changing the widgetContainer param in DynamicFormWidget initialization.
Hope it helps!
@asaenzestrada its works thx a lot, but now actionUpdate give me this error PHP Warning – yii\base\ErrorException
array_combine(): Both parameters should have an equal number of elements
this happends here
$modelsModelo03 = Model::createMultiple(Modelo03::classname(), $modelsModelo03);
anytime that i call createMultiple in my actionUpdate i get the same
@epulgaron You have to adjust your controller to process the nested forms. Use Xdebug to check the values on execution and find data you need in \Yii::$app->request->post(), there is a multidimensional array with the form data, You should load it to your models.