Answers.Body: <p>Of course it clears all the existing matrix elements if you update an entry. For craft it's like you delete the existing matrix blocks and create a new one. In order to keep all of them you have to send them in the form or create a custom controller to do it.
  You can insert all current matrix blocks in hidden fields, so users won't see them but craft will not delete them.</p>
  
  <p>The following code is totally untested (I don't have much time) it is just to show you the direction</p>
  
  <pre><code>{% for block in entry.measurement %}
      &lt;input type="hidden" name="fields[measurement][{{ block.id }}][type]" value="{{ block.getType().handle }}"&gt;
      &lt;input type="hidden" name="fields[measurement][{{ block.id }}][enabled]" value="1"&gt;
      &lt;input type="hidden" name="fields[measurement][{{ block.id }}][fields][length]" value="{{ block.length }}" &gt;
  {% endfor %}
  </code></pre>
  
  <p>Important note: your new matrix element's should not have the id of the latest+1. Your new matrix elements index should be <code>newX</code> with X = the number of the new element. So if you want to insert 1 new block your index would be <code>new1</code>, your second block would be <code>new2</code></p>
  
  <pre><code>&lt;input type="number" name="fields[measurement][new1][fields][length]"&gt;
  </code></pre>
  
  <p>you can inspect the backend form in your cp to get to know the structure craft need. It should look like this:</p>
  
  <pre><code>&lt;!-- existing block --&gt;
  &lt;div class="matrixblock" data-id="7" data-type="block"&gt;
      &lt;input type="hidden" name="fields[contentMatrix][7][type]" value="block"&gt;
      &lt;input type="hidden" name="fields[contentMatrix][7][enabled]" value="1"&gt;
      &lt;!-- some fields here --&gt;
  &lt;/div&gt;
  
  &lt;!-- new block --&gt;
  &lt;div class="matrixblock" data-id="new1" data-type="newBlock" style="opacity: 1;"&gt;
      &lt;input type="hidden" name="fields[contentMatrix][new1][type]" value="newBlock"&gt;
      &lt;input type="hidden" name="fields[contentMatrix][new1][enabled]" value="1"&gt;
      &lt;!-- some fields here --&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>If you do't want to render the entire matrix as hidden fields for any reason let me know and I'll provide you a custom controller action to add the matrix block instead of overwriting it</p>
  
  <p><strong>Update</strong><br>
  This is your controller action</p>
  
  <pre><code>/**
   * @throws Exception
   */
  public function actionSaveEntryMatrix(){
      $this-&gt;requirePostRequest();
      // check for the entries id, throw an exception if there is none (eg user manipulated the form)
      if(!$entryId = craft()-&gt;request-&gt;getParam('entryId')){
          throw new Exception('could not find EntryId');
      }
      if(!$entry = craft()-&gt;elements-&gt;getElementById($entryId)){
          throw new Exception('Could not find entry with id');
      }
  
      // get all attributes
      $attributes = $entry-&gt;getContent()-&gt;getAttributes();
      $entryData = craft()-&gt;request-&gt;getParam('fields');
  
      // just in case you want to update other fields of the entry
      if($entryData &amp;&amp; is_array($entryData)){
          foreach ($entryData as $k =&gt; $v){
              if(array_key_exists($k, $attributes)){
                  $attributes[$k] = $v;
              }
          }
      }
  
      // now the fun starts...
      // insert your field Handle of your matrix field here to get the field
      $measurementField = craft()-&gt;fields-&gt;getFieldByHandle('measurement');
      // fetch all available blocktypes for that field
      $blockTypes = craft()-&gt;matrix-&gt;getBlockTypesByFieldId($measurementField-&gt;id, 'handle');
  
      // get all measurements from post request
      $measurements = craft()-&gt;request-&gt;getParam('measurement');
      // this array will contain all your matrixblocks
      $measurementsBlocks = [];
  
      // fetch all old/existing matrix blocks
      $criteria = craft()-&gt;elements-&gt;getCriteria(ElementType::MatrixBlock);
      $criteria-&gt;fieldId = $measurementField-&gt;id;
      $criteria-&gt;ownerId = $entry-&gt;id;
      $criteria-&gt;limit = null;
      $criteria-&gt;status = null;
      $criteria-&gt;localeEnabled = null;
      $criteria-&gt;locale = $entry-&gt;locale;
      $oldBlocks = $criteria-&gt;find();
  
      // Index them by ID
      foreach ($oldBlocks as $oldBlock) {
          $measurementsBlocks[$oldBlock-&gt;id] = $oldBlock;
      }
  
      // start the new sortOrder
      $sortOrder = count($measurementsBlocks);
      foreach ($measurements as $blockId =&gt; $blockData) {
          $blockType = $blockTypes[$blockData['type']];
          // Is this new a new block or an existing?
          if (strncmp($blockId, 'new', 3) === 0){
              $block = new MatrixBlockModel();
              $block-&gt;fieldId = $measurementField-&gt;id;
              $block-&gt;typeId  = $blockType-&gt;id;
              $block-&gt;ownerId = $entry-&gt;id;
              $block-&gt;locale  = $entry-&gt;locale;
  
              $isNew = true;
              // Preserve the collapsed state, which the browser can't remember on its own for new blocks
              $block-&gt;collapsed = !empty($blockData['collapsed']);
          }else{
              // if it is an existing block just load it
              $block = $measurementsBlocks[$blockId];
              $isNew = false;
          }
  
          // get content from Post
          if(isset($blockData['fields'])){
              $block-&gt;setContentFromPost($blockData['fields']);
          }
  
          // if it is a new block increase the sortOrder and add it to the array
          if($isNew){
              $sortOrder++;
              $block-&gt;sortOrder = $sortOrder;
              $measurementsBlocks[] = $block;
          }else{
              // otherwise just update the array
              $measurementsBlocks[$block-&gt;id] = $block;
          }
      }
  
      // add the matrix elements + all updated field to the entries content
      $attributes['measurement'] = $measurementsBlocks;
      $entry-&gt;getContent()-&gt;setAttributes($attributes);
  
      // finally save the entry
      if(craft()-&gt;elements-&gt;saveElement($entry)){
          // redirect to your preferred url
          $this-&gt;redirect(craft()-&gt;request-&gt;getParam('redirect'));
      }else{
          // if there are errors add the entry to the route variables so you can display errors in twig via
          // entry.getErrors()
          craft()-&gt;urlManager-&gt;setRouteVariables(array(
              'entry' =&gt; $entry
          ));
      }
  }
  </code></pre>
  
  <p>And this will be your form</p>
  
  <pre><code>&lt;form method="post" accept-charset="UTF-8"&gt;
      {{ getCsrfInput() }}
      &lt;!-- change your action value to your one... my plugin has the handle test --&gt;
      &lt;input type="hidden" name="action" value="test/saveEntryMatrix"&gt;
      &lt;!--
          set your redirect value to your needs
          as you said if you want to add a field
          `/{{ entry.url }}/add-data`
          or
          `/{{ entry.url }}/edit-data?id=yourId`
      --&gt;
      &lt;input type="hidden" name="redirect" value="{{ entry.url }}"&gt;
      &lt;input type="hidden" name="sectionId" value="3"&gt;
      &lt;input type="hidden" name="enabled" value="1"&gt;
      &lt;input type="hidden" name="entryId" value="{{ entry.id }}"&gt;
  
      &lt;!-- in case you want to edit an existing block note: 50 was my id to test things --&gt;
      &lt;input type="hidden" name="measurement[50][type]" value="measurement"&gt;
  
      &lt;div class="legend"&gt;
          &lt;h2&gt;Tumour Volume&lt;/h2&gt;
          &lt;p&gt;All entries should be submitted in (mm)&lt;/p&gt;
      &lt;/div&gt;
      &lt;div class="fields"&gt;
          &lt;div class="field"&gt;
              &lt;label for=""&gt;Length&lt;/label&gt;
              &lt;input type="number" name="measurement[50][fields][length]"&gt;
          &lt;/div&gt;
      &lt;/div&gt;
      &lt;!-- endcase --&gt;
  
      &lt;!-- in case you want to add a new one --&gt;
      &lt;input type="hidden" name="measurement[new1][type]" value="measurement"&gt;
  
      &lt;div class="legend"&gt;
          &lt;h2&gt;Tumour Volume&lt;/h2&gt;
          &lt;p&gt;All entries should be submitted in (mm)&lt;/p&gt;
      &lt;/div&gt;
      &lt;div class="fields"&gt;
          &lt;div class="field"&gt;
              &lt;label for=""&gt;Length&lt;/label&gt;
              &lt;input type="number" name="measurement[new1][fields][length]"&gt;
          &lt;/div&gt;
      &lt;/div&gt;
      &lt;!-- endcase --&gt;
  
      &lt;input type="submit" value="Save"&gt;
  &lt;/form&gt;
  </code></pre>
  
  <p>About the redirect: do you know how craft rooting works?
  It seems like you have to make use of the <code>public function registerSiteRoutes()</code> function: in case you don't know how that works, please open another question to keep this one clean or read the documentation</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-11-11T08:09:56.693Z
Answers.Text: Hi Robin - thanks again for responding - I'd ideally not want to add all the matrix entries over again - i'd love to see that controller! Thanks!
Answers.UserDisplayName: Graham Winston
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-11-11T08:15:13.240Z
Answers.Text: Also would this be the same case for editing a specific matrix block?
Answers.UserDisplayName: Graham Winston
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-11-11T08:19:14.567Z
Answers.Text: Yes. The behavior of the default `entries/saveEntry` is fetching all matrix elements from your form, inserting new one + updating existing one and deleting the rest. I'll update my answer with the controller as soon as I can but it could take a few hours, sry for that.
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-11-11T08:25:19.773Z
Answers.Text: Thanks Robin - I really appreciate the time you are spending just a few points:
  
  1. I'm trying to build it so that I can add and edit single blocks within the matrix field
  2. The form is going to be in a separate URL eg.
  (/<rodent-url>/add-data)
  (/rodents-url/edit-data?id=<matrix-block-id>)
Answers.UserDisplayName: Graham Winston
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-11-11T10:42:19.280Z
Answers.Text: I updated my answer.. With this function you can add and update as many blocks as you like. When you index it with a current matrix id it is going to be updated, if you insert a `newX` it is going to be inserted. Old matrix blocks won't be deleted. As for the url: you just have to insert the url you wish to be redirected to the `redirect` field.
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-11-11T16:31:16.647Z
Answers.Text: Robin I just want to say thank you so much - I've begun to extend your first controller you wrote for me and I'm getting pretty comfortable - I've been using https://github.com/pixelandtonic/Craft-Release/blob/master/app/controllers/EntriesController.php as a terrific resource to help me through!
Answers.UserDisplayName: Graham Winston
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-11-11T16:49:29.377Z
Answers.Text: Glad I could help you. This git repo is a very good resource for learning craft and it is a smart idea to look up in different sources since I didn't include much error handling to not overload the templates.
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-11-11T07:56:46.993Z
Answers.LastActivityDate: 2017-11-11T10:39:30.043Z
Answers.LastEditDate: 2017-11-11T10:39:30.043Z
Answers.UserDisplayName: Robin Schambach
Body: <p>I'm trying to post a public entry form in a matrix field. I've added a count so that the block id is unique. However it's just clearing the matrix field and saving a single entry.</p>
  
  <pre><code>{% set matrix = entry.measurement | length %}
  {% set count = matrix + 1 %}
  {% set matrix_count = 'new' ~ count %}
  
  &lt;form method="post" accept-charset="UTF-8"&gt;
      {{ getCsrfInput() }}
      &lt;input type="hidden" name="action" value="entries/saveEntry"&gt;
      &lt;input type="hidden" name="redirect" value="{{ entry.url }}"&gt;
      &lt;input type="hidden" name="sectionId" value="3"&gt;
      &lt;input type="hidden" name="enabled" value="1"&gt;
      &lt;input type="hidden" name="entryId" value="{{ entry.id }}"&gt;
  
      &lt;input type="hidden" name="fields[measurement][{{ matrix_count }}][type]" value="measurement"&gt;
  
      &lt;div class="legend"&gt;
        &lt;h2&gt;Tumour Volume&lt;/h2&gt;
        &lt;p&gt;All entries should be submitted in (mm)&lt;/p&gt;
      &lt;/div&gt;
      &lt;div class="fields"&gt;
        &lt;div class="field"&gt;
          &lt;label for=""&gt;Length&lt;/label&gt;
          &lt;input type="number" name="fields[measurement][{{ matrix_count }}][fields][length]"&gt;
        &lt;/div&gt;
      &lt;/div&gt;
  
      &lt;input type="submit" value="Save"&gt;
  &lt;/form&gt;
  </code></pre>
  
  <p>Thanks!</p>
  
Tags: <matrix><entry><entry-form>
Title: Matrix Entry form
ThreadText: # Matrix Entry form
  
  (Asked by: username_0 on 2017-11-10)
  
  I'm trying to post a public entry form in a matrix field. I've added a count so that the block id is unique. However it's just clearing the matrix field and saving a single entry.
  
  ```
  {% set matrix = entry.measurement | length %}
  {% set count = matrix + 1 %}
  {% set matrix_count = 'new' ~ count %}
  
  <form method="post" accept-charset="UTF-8">
      {{ getCsrfInput() }}
      <input type="hidden" name="action" value="entries/saveEntry">
      <input type="hidden" name="redirect" value="{{ entry.url }}">
      <input type="hidden" name="sectionId" value="3">
      <input type="hidden" name="enabled" value="1">
      <input type="hidden" name="entryId" value="{{ entry.id }}">
  
      <input type="hidden" name="fields[measurement][{{ matrix_count }}][type]" value="measurement">
  
      <div class="legend">
        <h2>Tumour Volume</h2>
        <p>All entries should be submitted in (mm)</p>
      </div>
      <div class="fields">
        <div class="field">
          <label for="">Length</label>
          <input type="number" name="fields[measurement][{{ matrix_count }}][fields][length]">
        </div>
      </div>
  
      <input type="submit" value="Save">
  </form>
  
  ```
  
  Thanks!
  
  **Tags:** matrix, entry, entry-form
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2017-11-11. Score: 3 | Accepted answer
  
  Of course it clears all the existing matrix elements if you update an entry. For craft it's like you delete the existing matrix blocks and create a new one. In order to keep all of them you have to send them in the form or create a custom controller to do it.
  You can insert all current matrix blocks in hidden fields, so users won't see them but craft will not delete them.
  
  The following code is totally untested (I don't have much time) it is just to show you the direction
  
  ```
  {% for block in entry.measurement %}
      <input type="hidden" name="fields[measurement][{{ block.id }}][type]" value="{{ block.getType().handle }}">
      <input type="hidden" name="fields[measurement][{{ block.id }}][enabled]" value="1">
      <input type="hidden" name="fields[measurement][{{ block.id }}][fields][length]" value="{{ block.length }}" >
  {% endfor %}
  
  ```
  
  Important note: your new matrix element's should not have the id of the latest+1. Your new matrix elements index should be `newX` with X = the number of the new element. So if you want to insert 1 new block your index would be `new1`, your second block would be `new2`
  
  ```
  <input type="number" name="fields[measurement][new1][fields][length]">
  
  ```
  
  you can inspect the backend form in your cp to get to know the structure craft need. It should look like this:
  
  ```
  <!-- existing block -->
  <div class="matrixblock" data-id="7" data-type="block">
      <input type="hidden" name="fields[contentMatrix][7][type]" value="block">
      <input type="hidden" name="fields[contentMatrix][7][enabled]" value="1">
      <!-- some fields here -->
  </div>
  
  <!-- new block -->
  <div class="matrixblock" data-id="new1" data-type="newBlock" style="opacity: 1;">
      <input type="hidden" name="fields[contentMatrix][new1][type]" value="newBlock">
      <input type="hidden" name="fields[contentMatrix][new1][enabled]" value="1">
      <!-- some fields here -->
  </div>
  
  ```
  
  If you do't want to render the entire matrix as hidden fields for any reason let me know and I'll provide you a custom controller action to add the matrix block instead of overwriting it
  
  **Update**  
  This is your controller action
  
  ```
  /**
   * @throws Exception
   */
  public function actionSaveEntryMatrix(){
      $this->requirePostRequest();
      // check for the entries id, throw an exception if there is none (eg user manipulated the form)
      if(!$entryId = craft()->request->getParam('entryId')){
          throw new Exception('could not find EntryId');
      }
      if(!$entry = craft()->elements->getElementById($entryId)){
          throw new Exception('Could not find entry with id');
      }
  
      // get all attributes
      $attributes = $entry->getContent()->getAttributes();
      $entryData = craft()->request->getParam('fields');
  
      // just in case you want to update other fields of the entry
      if($entryData && is_array($entryData)){
          foreach ($entryData as $k => $v){
              if(array_key_exists($k, $attributes)){
                  $attributes[$k] = $v;
              }
          }
      }
  
      // now the fun starts...
      // insert your field Handle of your matrix field here to get the field
      $measurementField = craft()->fields->getFieldByHandle('measurement');
      // fetch all available blocktypes for that field
      $blockTypes = craft()->matrix->getBlockTypesByFieldId($measurementField->id, 'handle');
  
      // get all measurements from post request
      $measurements = craft()->request->getParam('measurement');
      // this array will contain all your matrixblocks
      $measurementsBlocks = [];
  
      // fetch all old/existing matrix blocks
      $criteria = craft()->elements->getCriteria(ElementType::MatrixBlock);
      $criteria->fieldId = $measurementField->id;
      $criteria->ownerId = $entry->id;
      $criteria->limit = null;
      $criteria->status = null;
      $criteria->localeEnabled = null;
      $criteria->locale = $entry->locale;
      $oldBlocks = $criteria->find();
  
      // Index them by ID
      foreach ($oldBlocks as $oldBlock) {
          $measurementsBlocks[$oldBlock->id] = $oldBlock;
      }
  
      // start the new sortOrder
      $sortOrder = count($measurementsBlocks);
      foreach ($measurements as $blockId => $blockData) {
          $blockType = $blockTypes[$blockData['type']];
          // Is this new a new block or an existing?
          if (strncmp($blockId, 'new', 3) === 0){
              $block = new MatrixBlockModel();
              $block->fieldId = $measurementField->id;
              $block->typeId  = $blockType->id;
              $block->ownerId = $entry->id;
              $block->locale  = $entry->locale;
  
              $isNew = true;
              // Preserve the collapsed state, which the browser can't remember on its own for new blocks
              $block->collapsed = !empty($blockData['collapsed']);
          }else{
              // if it is an existing block just load it
              $block = $measurementsBlocks[$blockId];
              $isNew = false;
          }
  
          // get content from Post
          if(isset($blockData['fields'])){
              $block->setContentFromPost($blockData['fields']);
          }
  
          // if it is a new block increase the sortOrder and add it to the array
          if($isNew){
              $sortOrder++;
              $block->sortOrder = $sortOrder;
              $measurementsBlocks[] = $block;
          }else{
              // otherwise just update the array
              $measurementsBlocks[$block->id] = $block;
          }
      }
  
      // add the matrix elements + all updated field to the entries content
      $attributes['measurement'] = $measurementsBlocks;
      $entry->getContent()->setAttributes($attributes);
  
      // finally save the entry
      if(craft()->elements->saveElement($entry)){
          // redirect to your preferred url
          $this->redirect(craft()->request->getParam('redirect'));
      }else{
          // if there are errors add the entry to the route variables so you can display errors in twig via
          // entry.getErrors()
          craft()->urlManager->setRouteVariables(array(
              'entry' => $entry
          ));
      }
  }
  
  ```
  
  And this will be your form
  
  ```
  <form method="post" accept-charset="UTF-8">
      {{ getCsrfInput() }}
      <!-- change your action value to your one... my plugin has the handle test -->
      <input type="hidden" name="action" value="test/saveEntryMatrix">
      <!--
          set your redirect value to your needs
          as you said if you want to add a field
          `/{{ entry.url }}/add-data`
          or
          `/{{ entry.url }}/edit-data?id=yourId`
      -->
      <input type="hidden" name="redirect" value="{{ entry.url }}">
      <input type="hidden" name="sectionId" value="3">
      <input type="hidden" name="enabled" value="1">
      <input type="hidden" name="entryId" value="{{ entry.id }}">
  
      <!-- in case you want to edit an existing block note: 50 was my id to test things -->
      <input type="hidden" name="measurement[50][type]" value="measurement">
  
      <div class="legend">
          <h2>Tumour Volume</h2>
          <p>All entries should be submitted in (mm)</p>
      </div>
      <div class="fields">
          <div class="field">
              <label for="">Length</label>
              <input type="number" name="measurement[50][fields][length]">
          </div>
      </div>
      <!-- endcase -->
  
      <!-- in case you want to add a new one -->
      <input type="hidden" name="measurement[new1][type]" value="measurement">
  
      <div class="legend">
          <h2>Tumour Volume</h2>
          <p>All entries should be submitted in (mm)</p>
      </div>
      <div class="fields">
          <div class="field">
              <label for="">Length</label>
              <input type="number" name="measurement[new1][fields][length]">
          </div>
      </div>
      <!-- endcase -->
  
      <input type="submit" value="Save">
  </form>
  
  ```
  
  About the redirect: do you know how craft rooting works?
  It seems like you have to make use of the `public function registerSiteRoutes()` function: in case you don't know how that works, please open another question to keep this one clean or read the documentation
  
  > **Comments:**
  > **username_0**: Hi username_1 - thanks again for responding - I'd ideally not want to add all the matrix entries over again - i'd love to see that controller! Thanks!  
  > **username_0**: Also would this be the same case for editing a specific matrix block?  
  > **username_1**: Yes. The behavior of the default `entries/saveEntry` is fetching all matrix elements from your form, inserting new one + updating existing one and deleting the rest. I'll update my answer with the controller as soon as I can but it could take a few hours, sry for that.  
  > **username_0**: Thanks username_1 - I really appreciate the time you are spending just a few points:  1. I'm trying to build it so that I can add and edit single blocks within the matrix field 2. The form is going to be in a separate URL eg. (/<rodent-url>/add-data) (/rodents-url/edit-data?id=<matrix-block-id>)  
  > **username_1**: I updated my answer.. With this function you can add and update as many blocks as you like. When you index it with a current matrix id it is going to be updated, if you insert a `newX` it is going to be inserted. Old matrix blocks won't be deleted. As for the url: you just have to insert the url you wish to be redirected to the `redirect` field.  
  > **username_0**: username_1 I just want to say thank you so much - I've begun to extend your first controller you wrote for me and I'm getting pretty comfortable - I've been using https://github.com/pixelandtonic/Craft-Release/blob/master/app/controllers/EntriesController.php as a terrific resource to help me through!  
  > **username_1**: Glad I could help you. This git repo is a very good resource for learning craft and it is a smart idea to look up in different sources since I didn't include much error handling to not overload the templates.  
  
  ---
  
  