Answers.Body: <p>A little bit late but here it is.</p>
  
  <ol>
  <li>Go to <a href="https://pluginfactory.io/" rel="noreferrer">https://pluginfactory.io/</a> and create a plugin, you need at least 1 Controller but you can leave the Name value blank to create a controller with the same Name as your PluginHandle. So if you choose "Experiment" as your Pluginhandle your controller will be <code>ExperimentController</code></li>
  <li>Click on "Build my Plugin" and save the files in your <code>craft/plugins/&gt;&gt;pluginhandle&lt;&lt;</code> folder (of course you need to create the >>pluginhandle&lt;&lt; directory eg.) Then you should install the plugin</li>
  <li><p>Insert this function in your controller. Note: this is just an example. I don't know your fieldLayout or some special behaviors you might want to include. So this is just the basic logic with some error handling. <strong>Important</strong> please read the commands and change the entryType Ids</p>
  
  <pre><code>     /**
       * @var    bool|array Allows anonymous access to this controller's actions.
       * @access protected
       */
      protected $allowAnonymous = true;
  
      /**
       * @throws Exception
       */
      public function actionSaveEntry(){
          $this-&gt;requirePostRequest();
          // check for an Id if there is one we update an existing entry if not we create a new one
          if($entryId = craft()-&gt;request-&gt;getParam('entryId')){
              if(!$entry = craft()-&gt;elements-&gt;getElementById($entryId)){
                  throw new Exception('Could not find entry with id');
              }
          }else{
              $entry = new EntryModel();
              $entry-&gt;typeId = craft()-&gt;request-&gt;getParam('entryType');
              $entry-&gt;sectionId = craft()-&gt;request-&gt;getParam('sectionId');
          }
  
          // set the content of your entry/experiment
          $entryData = craft()-&gt;request-&gt;getParam('experiment');
          $entry-&gt;getContent()-&gt;setAttributes($entryData['fields']);
  
          // try to save the entry
          if(craft()-&gt;entries-&gt;saveEntry($entry)){
              // fetch the id from the experiment so we can use that as a parentId for the cage
              $entryId = $entry-&gt;id;
              // if everything is alright we can save the cage like we did it with the experiment
              if($cagesData = craft()-&gt;request-&gt;getParam('cage')){
  
                  foreach ($cagesData as $cageData){
                      // like with the entry check for an Id
                      if($cageId = $cageData['entryId']){
                          if(!$cage = craft()-&gt;elements-&gt;getElementById($cageId)){
                              throw new Exception('Could not find cage with the given Id');
                          }
                      }else{
                          $cage = new EntryModel();
                          $cage-&gt;typeId = 5; // you could as well create a hidden field like for the entry itself but you must change the typeId to your entryType Id
                          $cage-&gt;sectionId = craft()-&gt;request-&gt;getParam('sectionId');
                      }
  
                      // save the content as well
                      $cage-&gt;getContent()-&gt;setAttributes($cageData['fields']);
                      // and set the parent
                      $cage-&gt;parentId = $entryId;
                      if(craft()-&gt;entries-&gt;saveEntry($cage)){
                          $cageId = $cage-&gt;id;
                          // and now we are going to do the same with the animals
                          if($rodentsData = $cageData['rodents']) {
                              $rodentErrors = [];
                              foreach ($rodentsData as $rodentData){
                                  // like with the entry check for an Id
                                  if (array_key_exists('entryId', $rodentData) &amp;&amp; $rodentId = $rodentData['entryId']) {
                                      if (!$rodent = craft()-&gt;elements-&gt;getElementById($rodentId)) {
                                          throw new Exception('Could not find rodent with the given Id');
                                      }
                                  } else {
                                      $rodent = new EntryModel();
                                      $rodent-&gt;typeId = 6; // change your entryType Id here
                                      $rodent-&gt;sectionId = craft()-&gt;request-&gt;getParam('sectionId');
                                  }
  
                                  $rodent-&gt;getContent()-&gt;setAttributes($rodentData['fields']);
                                  $rodent-&gt;parentId = $cageId;
                                  if (!craft()-&gt;entries-&gt;saveEntry($rodent)) {
                                      // important note: if there are any errors here, the cage and the experiment is
                                      // saved anyway so you should insert the id of the experiment to the form in order
                                      // to update the form instead of creating a new one again and again
                                      // if the experiment has an Id but the cage/rodent not you'll just update the experiment
                                      // and create new cages/rodents for it
                                      $rodentErrors[] = $rodent-&gt;getErrors();
                                  }else{
                                      $rodentErrors = [];
                                  }
                              }
                              // include errors of each item
                              craft()-&gt;urlManager-&gt;setRouteVariables(array(
                                  'rodentErrors' =&gt; $rodentErrors
                              ));
                          }
                      }else{
                          craft()-&gt;urlManager-&gt;setRouteVariables(array(
                              'cageErrors' =&gt; $cage-&gt;getErrors()
                          ));
                      }
                  }
  
              }
          }else{
              // handle your errors here.. you can use $entry-&gt;getErrors()
              // return them to your frontend and render them in twig or something
              craft()-&gt;urlManager-&gt;setRouteVariables(array(
                  'experimentErrors' =&gt; $entry-&gt;getErrors()
              ));
          }
      }
  </code></pre></li>
  <li><p>Your html template. Note I don't know your fieldLayout so I just included the title and the craft default <code>body</code> field. In order to add your custom fields to the html you need to set the input name to <code>entryType[fields][fieldHandle]</code> so if you want to add a field with the handle <code>foo</code> to the <code>cage</code> you would name it <code>cage[fields][foo]</code>. As for the routing: your <code>action</code> must be <code>pluginHandle/functionName</code></p>
  
  <pre><code>&lt;form method="post" accept-charset="UTF-8"&gt;
      {{ getCsrfInput() }}
      {# your plugin name and function name #}
      &lt;input type="hidden" name="action" value="test/saveEntry"&gt;
      {# the id of your section for me its 4 you need to change this value to your section Id #}
      &lt;input type="hidden" name="sectionId" value="4"&gt;
      {# enable the entry #}
      &lt;input type="hidden" name="enabled" value="1"&gt;
      {# id of your entry leave it blank to insert a new entry, insert a id to change an existing entry#}
      &lt;input type="hidden" name="entryId" value=""&gt;
      {# the id of your experiments entryType for me its 4 you need to change this value #}
      &lt;input type="hidden" name="entryType" value="4"&gt;
  
      &lt;label for="title"&gt;Title&lt;/label&gt;
      &lt;input id="title" type="text" name="experiment[fields][title]"&gt;
      &lt;input  type="text" name="experiment[fields][body]"&gt;
  
      {# now the cage as a children #}
      &lt;div&gt;
          &lt;label for="title"&gt;cage title&lt;/label&gt;
          &lt;input type="text" name="cage[0][fields][title]"&gt;
          &lt;input type="text" name="cage[0][fields][body]"&gt;
          &lt;input type="hidden" name="cage[0][entryId]" value=""&gt;
          {# and some Rodents as children for the cages #}
          &lt;div&gt;
              &lt;label for="title"&gt;Rodent title&lt;/label&gt;
              &lt;input type="text" name="cage[0][rodents][0][fields][title]"&gt;
              &lt;input type="text" name="cage[0][rodents][0][fields][body]"&gt;
              &lt;input type="hidden" name="cage[0][rodents][0][entryId]" value=""&gt;
          &lt;/div&gt;
  
          &lt;div&gt;
              &lt;label for="title"&gt;Rodent title&lt;/label&gt;
              &lt;input type="text" name="cage[0][rodents][1][fields][title]"&gt;
              &lt;input type="text" name="cage[0][rodents][1][fields][body]"&gt;
              &lt;input type="hidden" name="cage[0][rodents][1][entryId]" value=""&gt;
          &lt;/div&gt;
  
          &lt;div&gt;
              &lt;label for="title"&gt;Rodent title&lt;/label&gt;
              &lt;input type="text" name="cage[0][rodents][2][fields][title]"&gt;
              &lt;input type="text" name="cage[0][rodents][2][fields][body]"&gt;
              &lt;input type="hidden" name="cage[0][rodents][2][entryId]" value=""&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  
      {# and another cage #}
      &lt;div&gt;
          &lt;label for="title"&gt;cage title&lt;/label&gt;
          &lt;input type="text" name="cage[1][fields][title]"&gt;
          &lt;input type="text" name="cage[1][fields][body]"&gt;
          &lt;input type="hidden" name="cage[1][entryId]" value=""&gt;
          {# and some Rodents as children for the cages #}
          &lt;div&gt;
              &lt;label for="title"&gt;Rodent title&lt;/label&gt;
              &lt;input type="text" name="cage[1][rodents][0][fields][title]"&gt;
              &lt;input type="text" name="cage[1][rodents][0][fields][body]"&gt;
              &lt;input type="hidden" name="cage[1][rodents][0][entryId]" value=""&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  
      &lt;input type="submit" value="Publish"&gt;
  </code></pre>
  
  <p></p>
  
  <pre><code>{# just as an example how you could display errors or at least receive the error object #}
  {% if rodentErrors is defined %}
      {% for errors in rodentErrors %}
          {% for fieldHandle, errorMessages in errors  %}
              {{ fieldHandle }} {{ errorMessages[0] }}&lt;br&gt;
          {% endfor %}
      {% endfor %}
  {% endif %}
  </code></pre></li>
  </ol>
  
  <p>Please let me know when you need help and feel free to ask what you like.<br>
  If done right, you'll end up with a structure like this with your form (note: please ignore the titles...)
  <a href="https://i.sstatic.net/HtMAw.png" rel="noreferrer"><img src="https://i.sstatic.net/HtMAw.png" alt="enter image description here"></a></p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-11-10T11:59:45.487Z
Answers.Text: Robin this is absolutely perfect - thank you so much for the help!
Answers.UserDisplayName: Graham Winston
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-11-10T13:40:33.053Z
Answers.Text: Wow Robin, this is beyond phenomenal. Thank you so much for posting this! I look forward to hopping in and implementing some of the things you did here; really has me thinking about a whole host of wonderful changes to make in workflow.
Answers.UserDisplayName: Jeremiah
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-10-31T22:25:12.283Z
Answers.Text: How can this be accomplished in Craft 3?
Answers.UserDisplayName: Andrea DeMers
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-11-09T19:17:17.693Z
Answers.LastActivityDate: 2017-11-09T20:12:28.823Z
Answers.LastEditDate: 2017-11-09T20:12:28.823Z
Answers.UserDisplayName: Robin Schambach
Body: <p>I'm building an MVP for a project, I'm using Craft and would like to:</p>
  
  <ol>
  <li>Create an experiment (/experiments/)</li>
  <li>Create multiple cages for the animals within the previous created experiment eg. 5 cages - (/experiments//cages/)</li>
  <li>Add a number of rodents to each of those cages e.g. Create 5 cages with 5 rodents in each. (/experiments//cages/)</li>
  <li>Add measurements to a specific mouse e.g., weight / tumour size (/experiments//cages/)</li>
  </ol>
  
  <p>I was thinking this would be possible by using an entry form to add entries to a structure that looks like this-</p>
  
  <pre><code>--Experiments
  ----Cage 1
  ------Rodent 1
  ------Rodent 2
  ------Rodent 3
  ----Cage 2
  ------Rodent 1
  ------Rodent 2
  ------Rodent 3
  ...
  </code></pre>
  
  <p>My question is - </p>
  
  <ol>
  <li><p>Is it possible to create multiple entries per form eg.
  <strong>Create 5 cages with 5 rodents in each.</strong> from a single entry form submission?</p></li>
  <li><p>Is it possible to assign the entry type in an entry form? (eg. Cage or Mouse entry type?) </p></li>
  <li><p>Is it possible to assign the parent to an entry via the entry form?</p></li>
  </ol>
  
  <p>If these aren't possible with an entry form + structure what would be the best way to approach it?</p>
  
  <p>Thanks!</p>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-11-09T14:17:35.577Z
Comments.Text: It's relatively easy and fast to achieve once you've learned how craft works. It would just be nice to know if you need this form in your frontend or only in your backend. I think the most difficult part is to create the dynamic form with pure Javascript/jquery if you don't want to use angular. If you don't refuse to create a custom plugin I could provide you the basic code you need but I need to know if it's only for your backend or for your frontend too. As for your question for frontend request: I can say yes - it's all possible with a custom controller
Comments.UserDisplayName: Robin Schambach
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-11-09T14:52:08.340Z
Comments.Text: Hi Robin - This is only on the front end, I can handle the javascript side (It's my strong point!) I've never actually coded a custom controller so any help would be really appreaciated!
Comments.UserDisplayName: Graham Winston
Tags: <entry><structure><entry-type><parents><entry-form>
Title: Entry Form - Multiple Entries & Entry Type & Parent
ThreadText: # Entry Form - Multiple Entries & Entry Type & Parent
  
  (Asked by: username_0 on 2017-11-09)
  
  I'm building an MVP for a project, I'm using Craft and would like to:
  
  1. Create an experiment (/experiments/)
  2. Create multiple cages for the animals within the previous created experiment eg. 5 cages - (/experiments//cages/)
  3. Add a number of rodents to each of those cages e.g. Create 5 cages with 5 rodents in each. (/experiments//cages/)
  4. Add measurements to a specific mouse e.g., weight / tumour size (/experiments//cages/)
  
  I was thinking this would be possible by using an entry form to add entries to a structure that looks like this-
  
  ```
  --Experiments
  ----Cage 1
  ------Rodent 1
  ------Rodent 2
  ------Rodent 3
  ----Cage 2
  ------Rodent 1
  ------Rodent 2
  ------Rodent 3
  ...
  
  ```
  
  My question is -
  
  1. Is it possible to create multiple entries per form eg.
     **Create 5 cages with 5 rodents in each.** from a single entry form submission?
  2. Is it possible to assign the entry type in an entry form? (eg. Cage or Mouse entry type?)
  3. Is it possible to assign the parent to an entry via the entry form?
  
  If these aren't possible with an entry form + structure what would be the best way to approach it?
  
  Thanks!
  
  **Tags:** entry, structure, entry-type, parents, entry-form
  
  > **Comments:**
  > **username_1**: It's relatively easy and fast to achieve once you've learned how craft works. It would just be nice to know if you need this form in your frontend or only in your backend. I think the most difficult part is to create the dynamic form with pure Javascript/jquery if you don't want to use angular. If you don't refuse to create a custom plugin I could provide you the basic code you need but I need to know if it's only for your backend or for your frontend too. As for your question for frontend request: I can say yes - it's all possible with a custom controller  
  > **username_0**: Hi username_1 - This is only on the front end, I can handle the javascript side (It's my strong point!) I've never actually coded a custom controller so any help would be really appreaciated!  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2017-11-09. Score: 8 | Accepted answer
  
  A little bit late but here it is.
  
  1. Go to <https://pluginfactory.io/> and create a plugin, you need at least 1 Controller but you can leave the Name value blank to create a controller with the same Name as your PluginHandle. So if you choose "Experiment" as your Pluginhandle your controller will be `ExperimentController`
  2. Click on "Build my Plugin" and save the files in your `craft/plugins/>>pluginhandle<<` folder (of course you need to create the >>pluginhandle<< directory eg.) Then you should install the plugin
  3. Insert this function in your controller. Note: this is just an example. I don't know your fieldLayout or some special behaviors you might want to include. So this is just the basic logic with some error handling. **Important** please read the commands and change the entryType Ids
  
     ```
          /**
          * @var    bool|array Allows anonymous access to this controller's actions.
          * @access protected
          */
         protected $allowAnonymous = true;
  
         /**
          * @throws Exception
          */
         public function actionSaveEntry(){
             $this->requirePostRequest();
             // check for an Id if there is one we update an existing entry if not we create a new one
             if($entryId = craft()->request->getParam('entryId')){
                 if(!$entry = craft()->elements->getElementById($entryId)){
                     throw new Exception('Could not find entry with id');
                 }
             }else{
                 $entry = new EntryModel();
                 $entry->typeId = craft()->request->getParam('entryType');
                 $entry->sectionId = craft()->request->getParam('sectionId');
             }
  
             // set the content of your entry/experiment
             $entryData = craft()->request->getParam('experiment');
             $entry->getContent()->setAttributes($entryData['fields']);
  
             // try to save the entry
             if(craft()->entries->saveEntry($entry)){
                 // fetch the id from the experiment so we can use that as a parentId for the cage
                 $entryId = $entry->id;
                 // if everything is alright we can save the cage like we did it with the experiment
                 if($cagesData = craft()->request->getParam('cage')){
  
                     foreach ($cagesData as $cageData){
                         // like with the entry check for an Id
                         if($cageId = $cageData['entryId']){
                             if(!$cage = craft()->elements->getElementById($cageId)){
                                 throw new Exception('Could not find cage with the given Id');
                             }
                         }else{
                             $cage = new EntryModel();
                             $cage->typeId = 5; // you could as well create a hidden field like for the entry itself but you must change the typeId to your entryType Id
                             $cage->sectionId = craft()->request->getParam('sectionId');
                         }
  
                         // save the content as well
                         $cage->getContent()->setAttributes($cageData['fields']);
                         // and set the parent
                         $cage->parentId = $entryId;
                         if(craft()->entries->saveEntry($cage)){
                             $cageId = $cage->id;
                             // and now we are going to do the same with the animals
                             if($rodentsData = $cageData['rodents']) {
                                 $rodentErrors = [];
                                 foreach ($rodentsData as $rodentData){
                                     // like with the entry check for an Id
                                     if (array_key_exists('entryId', $rodentData) && $rodentId = $rodentData['entryId']) {
                                         if (!$rodent = craft()->elements->getElementById($rodentId)) {
                                             throw new Exception('Could not find rodent with the given Id');
                                         }
                                     } else {
                                         $rodent = new EntryModel();
                                         $rodent->typeId = 6; // change your entryType Id here
                                         $rodent->sectionId = craft()->request->getParam('sectionId');
                                     }
  
                                     $rodent->getContent()->setAttributes($rodentData['fields']);
                                     $rodent->parentId = $cageId;
                                     if (!craft()->entries->saveEntry($rodent)) {
                                         // important note: if there are any errors here, the cage and the experiment is
                                         // saved anyway so you should insert the id of the experiment to the form in order
                                         // to update the form instead of creating a new one again and again
                                         // if the experiment has an Id but the cage/rodent not you'll just update the experiment
                                         // and create new cages/rodents for it
                                         $rodentErrors[] = $rodent->getErrors();
                                     }else{
                                         $rodentErrors = [];
                                     }
                                 }
                                 // include errors of each item
                                 craft()->urlManager->setRouteVariables(array(
                                     'rodentErrors' => $rodentErrors
                                 ));
                             }
                         }else{
                             craft()->urlManager->setRouteVariables(array(
                                 'cageErrors' => $cage->getErrors()
                             ));
                         }
                     }
  
                 }
             }else{
                 // handle your errors here.. you can use $entry->getErrors()
                 // return them to your frontend and render them in twig or something
                 craft()->urlManager->setRouteVariables(array(
                     'experimentErrors' => $entry->getErrors()
                 ));
             }
         }
  
     ```
  4. Your html template. Note I don't know your fieldLayout so I just included the title and the craft default `body` field. In order to add your custom fields to the html you need to set the input name to `entryType[fields][fieldHandle]` so if you want to add a field with the handle `foo` to the `cage` you would name it `cage[fields][foo]`. As for the routing: your `action` must be `pluginHandle/functionName`
  
     ```
     <form method="post" accept-charset="UTF-8">
         {{ getCsrfInput() }}
         {# your plugin name and function name #}
         <input type="hidden" name="action" value="test/saveEntry">
         {# the id of your section for me its 4 you need to change this value to your section Id #}
         <input type="hidden" name="sectionId" value="4">
         {# enable the entry #}
         <input type="hidden" name="enabled" value="1">
         {# id of your entry leave it blank to insert a new entry, insert a id to change an existing entry#}
         <input type="hidden" name="entryId" value="">
         {# the id of your experiments entryType for me its 4 you need to change this value #}
         <input type="hidden" name="entryType" value="4">
  
         <label for="title">Title</label>
         <input id="title" type="text" name="experiment[fields][title]">
         <input  type="text" name="experiment[fields][body]">
  
         {# now the cage as a children #}
         <div>
             <label for="title">cage title</label>
             <input type="text" name="cage[0][fields][title]">
             <input type="text" name="cage[0][fields][body]">
             <input type="hidden" name="cage[0][entryId]" value="">
             {# and some Rodents as children for the cages #}
             <div>
                 <label for="title">Rodent title</label>
                 <input type="text" name="cage[0][rodents][0][fields][title]">
                 <input type="text" name="cage[0][rodents][0][fields][body]">
                 <input type="hidden" name="cage[0][rodents][0][entryId]" value="">
             </div>
  
             <div>
                 <label for="title">Rodent title</label>
                 <input type="text" name="cage[0][rodents][1][fields][title]">
                 <input type="text" name="cage[0][rodents][1][fields][body]">
                 <input type="hidden" name="cage[0][rodents][1][entryId]" value="">
             </div>
  
             <div>
                 <label for="title">Rodent title</label>
                 <input type="text" name="cage[0][rodents][2][fields][title]">
                 <input type="text" name="cage[0][rodents][2][fields][body]">
                 <input type="hidden" name="cage[0][rodents][2][entryId]" value="">
             </div>
         </div>
  
         {# and another cage #}
         <div>
             <label for="title">cage title</label>
             <input type="text" name="cage[1][fields][title]">
             <input type="text" name="cage[1][fields][body]">
             <input type="hidden" name="cage[1][entryId]" value="">
             {# and some Rodents as children for the cages #}
             <div>
                 <label for="title">Rodent title</label>
                 <input type="text" name="cage[1][rodents][0][fields][title]">
                 <input type="text" name="cage[1][rodents][0][fields][body]">
                 <input type="hidden" name="cage[1][rodents][0][entryId]" value="">
             </div>
         </div>
  
         <input type="submit" value="Publish">
  
     ```
  
     ```
     {# just as an example how you could display errors or at least receive the error object #}
     {% if rodentErrors is defined %}
         {% for errors in rodentErrors %}
             {% for fieldHandle, errorMessages in errors  %}
                 {{ fieldHandle }} {{ errorMessages[0] }}<br>
             {% endfor %}
         {% endfor %}
     {% endif %}
  
     ```
  
  Please let me know when you need help and feel free to ask what you like.  
  If done right, you'll end up with a structure like this with your form (note: please ignore the titles...)
  [![enter image description here](https://i.sstatic.net/HtMAw.png)](https://i.sstatic.net/HtMAw.png)
  
  > **Comments:**
  > **username_0**: username_1 this is absolutely perfect - thank you so much for the help!  
  > **username_2**: Wow username_1, this is beyond phenomenal. Thank you so much for posting this! I look forward to hopping in and implementing some of the things you did here; really has me thinking about a whole host of wonderful changes to make in workflow.  
  > **username_3**: How can this be accomplished in Craft 3?  
  
  ---
  
  