Reputation: 2496
I am in a situation where I have more than 4 child tables associated with one Parent table. I need to create a user experience in which user presses Save button only once, meaning by, user enters all the data in parent model fields, then enters data in all four child model fields and then presses the save button. As far as I know, having relations in the model allows you to make associated rows inserted easily but the main problem is how to receive multiple rows from view in POST method for a single model (here I essentially mean the child models). I have tried it manually by repeating the attributes of child model in view but when I save the record, only the last rowset gets stored in the child table along with parent table, one row for the child table gets missed. Kindly note that I am using CActiveForm and other Bootstrap widgets in my View files.
Is it possible in Yii or I am too wishful....any suggestions or comments ????
Many thanks in advance. Regards, Faisal
Upvotes: 1
Views: 2830
Reputation: 2496
I got the solution but with all the help from here and also from other forums. I followed the post by Kiran and tested it by generating additional HTML attributes using jQuery. On the submit, I got all the rows exactly how I wanted. In the controller, first I counted the total number of models submitted in the post request and then iterated over each one for desired processing. Following is the code snippet.
if(!empty($_POST))
{
$v=count($_POST['Address'])+1;
Yii::log(count($_POST['Address']));
for ($i=1; $i<$v; $i++){
$addressModel_1->attributes=$_POST['Address'][$i];
Yii::log('Dumping Data from '.$i.' model');
Yii::log($addressModel_1->city);
Yii::log($addressModel_1->street);
Yii::log($addressModel_1->state);}}
On the view side, I generated the HTML using jQuery function. All this function did was to add another set of html to allow the user to enter data. Important thing to note while generating the HTML is the name of model or else it wouldn't land where you want in controller.
Following is the code snippet of this function. Please note that I am hardcoding the "3" as id since I already had two sets of rows in DOM. I am going to further improve this code but rest assured, the logic works.
function createNewAddress(){
var newdiv = document.createElement('div');
var inner_html='<div class="row">';
inner_html+='<label for="Address_3_street">Street</label> <input name="Address[3][street]" id="Address_3_street" type="text" maxlength="200" /> </div>';
inner_html+='<div class="row">';
inner_html+='<label for="Address_3_city">City</label> <input name="Address[3][city]" id="Address_3_city" type="text" maxlength="200" /> </div> ';
inner_html+='<div class="row">';
inner_html+='<label for="Address_3_state">State</label> <input name="Address[3][state]" id="Address_3_state" type="text" maxlength="200" /> </div>';
newdiv.innerHTML=inner_html;
$('#user-form').append(newdiv);
}
This way, I can have n-number of child rows added on the fly from browser and user will save all data by pressing the Save or Submit button only once.
Thanks to everyone for their support.
Regards,
Faisal
Upvotes: 2
Reputation: 5913
You could make a new CFormModel to handle all the form fields validation, and then manually set the attributes after the $model->validate in the POST function. EG:
if ($model->validate){
$model_one = new ModelOne;
$model_one->name = $model->model_one_name;
$model_one->surname = $model->model_one_surname;
....
$model_two = new ModelTwo;
$model_two->name = $model->model_two_name;
$model_two->surname = $model->model_two_surname;
....
}
Upvotes: 0
Reputation: 4334
You should be using tabular input, that way you can receive data for multipe instances of the same type, you can then save the parent and use its id to fill the child foreign keys.
Upvotes: 0