FaisalKhan
FaisalKhan

Reputation: 2496

Yii: Receiving multiple records for a single model from view in POST method: To save Parent Child data

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

Answers (3)

FaisalKhan
FaisalKhan

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

Brett Gregson
Brett Gregson

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

Asgaroth
Asgaroth

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

Related Questions