Answers.Body: <p>As mentioned previously, addresses can not be edited on the order once the order is complete (from the front-end).</p>
  
  <p>Right now completed order's addresses can only be edited by admins.</p>
  
  <p>The only way around that at the moment would be to create your own plugin controller action that your form would post to. The controller action would look like this:</p>
  
  <pre><code>public function actionSave()
  {
      $this-&gt;requirePostRequest();
      $this-&gt;requireLogin();
      $id = craft()-&gt;request-&gt;getRequiredPost('id');
      // IMPORTANT - Validate the current user is allowed to update the address $id
  
      $address = craft()-&gt;commerce_addresses-&gt;getAddressById($id);
  
      if (!$address)
      {
          $address = new Commerce_AddressModel();
      }
  
      // Shared attributes
      $attrs = [
          'attention',
          'title',
          'firstName',
          'lastName',
          'address1',
          'address2',
          'city',
          'zipCode',
          'phone',
          'alternativePhone',
          'businessName',
          'businessTaxId',
          'businessId',
          'countryId',
          'stateValue'
      ];
      foreach ($attrs as $attr)
      {
          $address-&gt;$attr = craft()-&gt;request-&gt;getPost($attr);
      }
  
      // Save it
      if (craft()-&gt;commerce_addresses-&gt;saveAddress($address))
      {
  
          if (craft()-&gt;request-&gt;isAjaxRequest)
          {
              $this-&gt;returnJson(['success' =&gt; true, 'address' =&gt; $address]);
          }
  
          craft()-&gt;userSession-&gt;setNotice(Craft::t('Address saved.'));
  
          // save address ID to the order (shipping or billing)
  
          $this-&gt;redirectToPostedUrl();
      }
      else
      {
          if (craft()-&gt;request-&gt;isAjaxRequest)
          {
              $this-&gt;returnJson([
                  'error'  =&gt; Craft::t("Couldn’t save address."),
                  'errors' =&gt; $address-&gt;errors
              ]);
          }
  
          craft()-&gt;userSession-&gt;setError(Craft::t('Couldn’t save address.'));
      }
  
      // Send the model back to the template
      craft()-&gt;urlManager-&gt;setRouteVariables(['address' =&gt; $address]);
      }
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-07-12T06:07:52.580Z
Answers.Text: Thanks Luke, for pointing us in the right direction with such detail, greatly appreciated. Will put together the plugin and let you know how we go
Answers.UserDisplayName: Alberto
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-07-11T04:38:47.060Z
Answers.LastActivityDate: 2017-07-11T04:38:47.060Z
Answers.UserDisplayName: Luke Holder
Answers.Body: <p>When the order is completed a copy of the address is made which is created for that specific order, that explains why it doesn't show up in the customers_addresses table. </p>
  
  <p>This is so that the address is unique to that order and can be edited by an admin without affecting the customers address book. Are you wanting customers to be able to edit that address after the order is complete?</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-07-07T05:39:02.503Z
Answers.Text: Hi Luke, that's what we thought it might be happening. It makes sense to keep order addresses and customer addresses separate so they don't get on each other's way. In our case, it would be good to allow customers to update an order address before the order has shipped so they don't need to contact support to do so. Do you have an idea on what would be the best way to accomplish that?
Answers.UserDisplayName: Alberto
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-07-06T04:13:12.400Z
Answers.LastActivityDate: 2017-07-06T04:13:12.400Z
Answers.UserDisplayName: Luke Holder
Body: <p>We are trying to give our clients the ability to update an order's shipping address before the order has been actually shipped.</p>
  
  <p>We've created a members area where they can list their orders and access them individually. When in an order, we have a link that loads a specific address form template <code>e.g. /addresses/edit/{{order.shippingAddress.id}}</code> but the address form doesn't load throwing the error <code>Impossible to access an attribute ("id") on a null variable.</code></p>
  
  <p>This exact same address edit form works fine when loading the address from the <code>craft.commerce.customer.addresses</code> model <code>e.g. addresses/edit/{{ address.id }}</code>. Having a look at the DB, we've found that the address if from the order model doesn't actually exists in the <code>craft_commerce_customers_addresses</code> table which would explain it.</p>
  
  <p>Is there anything we've missed?</p>
  
  <p>Cheers,
  Alberto</p>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-07-05T18:07:46.070Z
Comments.Text: Does that same order load in the Control Panel fine? If so, does it show the correct address?
Comments.UserDisplayName: Brad Bell
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-07-06T02:59:26.073Z
Comments.Text: Hi Brad, yes in Control Panel  the order loads fine and if you click on the `edit` address button the address form loads correctly and you can edit it. Both frontend and backend links point to the same address id. I think it might have to do with duplication of addresses when the order is completed but I can't seem to find the duplicated order address in the `craft_commerce_customers_addresses` and not sure why
Comments.UserDisplayName: Alberto
Tags: <plugin-craftcommerce><order><addresses>
Title: Craft Commerce - Edit Complete Order Address from frontend
ThreadText: # Craft Commerce - Edit Complete Order Address from frontend
  
  (Asked by: username_0 on 2017-07-05)
  
  We are trying to give our clients the ability to update an order's shipping address before the order has been actually shipped.
  
  We've created a members area where they can list their orders and access them individually. When in an order, we have a link that loads a specific address form template `e.g. /addresses/edit/{{order.shippingAddress.id}}` but the address form doesn't load throwing the error `Impossible to access an attribute ("id") on a null variable.`
  
  This exact same address edit form works fine when loading the address from the `craft.commerce.customer.addresses` model `e.g. addresses/edit/{{ address.id }}`. Having a look at the DB, we've found that the address if from the order model doesn't actually exists in the `craft_commerce_customers_addresses` table which would explain it.
  
  Is there anything we've missed?
  
  Cheers,
  username_0
  
  **Tags:** plugin-craftcommerce, order, addresses
  
  > **Comments:**
  > **username_1**: Does that same order load in the Control Panel fine? If so, does it show the correct address?  
  > **username_0**: Hi username_1, yes in Control Panel  the order loads fine and if you click on the `edit` address button the address form loads correctly and you can edit it. Both frontend and backend links point to the same address id. I think it might have to do with duplication of addresses when the order is completed but I can't seem to find the duplicated order address in the `craft_commerce_customers_addresses` and not sure why  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_2 on 2017-07-11. Score: 1 | Accepted answer
  
  As mentioned previously, addresses can not be edited on the order once the order is complete (from the front-end).
  
  Right now completed order's addresses can only be edited by admins.
  
  The only way around that at the moment would be to create your own plugin controller action that your form would post to. The controller action would look like this:
  
  ```
  public function actionSave()
  {
      $this->requirePostRequest();
      $this->requireLogin();
      $id = craft()->request->getRequiredPost('id');
      // IMPORTANT - Validate the current user is allowed to update the address $id
  
      $address = craft()->commerce_addresses->getAddressById($id);
  
      if (!$address)
      {
          $address = new Commerce_AddressModel();
      }
  
      // Shared attributes
      $attrs = [
          'attention',
          'title',
          'firstName',
          'lastName',
          'address1',
          'address2',
          'city',
          'zipCode',
          'phone',
          'alternativePhone',
          'businessName',
          'businessTaxId',
          'businessId',
          'countryId',
          'stateValue'
      ];
      foreach ($attrs as $attr)
      {
          $address->$attr = craft()->request->getPost($attr);
      }
  
      // Save it
      if (craft()->commerce_addresses->saveAddress($address))
      {
  
          if (craft()->request->isAjaxRequest)
          {
              $this->returnJson(['success' => true, 'address' => $address]);
          }
  
          craft()->userSession->setNotice(Craft::t('Address saved.'));
  
          // save address ID to the order (shipping or billing)
  
          $this->redirectToPostedUrl();
      }
      else
      {
          if (craft()->request->isAjaxRequest)
          {
              $this->returnJson([
                  'error'  => Craft::t("Couldn’t save address."),
                  'errors' => $address->errors
              ]);
          }
  
          craft()->userSession->setError(Craft::t('Couldn’t save address.'));
      }
  
      // Send the model back to the template
      craft()->urlManager->setRouteVariables(['address' => $address]);
      }
  
  ```
  
  > **Comments:**
  > **username_0**: Thanks username_2, for pointing us in the right direction with such detail, greatly appreciated. Will put together the plugin and let you know how we go  
  
  ---
  
  ### Answer by username_2 on 2017-07-06. Score: 1
  
  When the order is completed a copy of the address is made which is created for that specific order, that explains why it doesn't show up in the customers\_addresses table.
  
  This is so that the address is unique to that order and can be edited by an admin without affecting the customers address book. Are you wanting customers to be able to edit that address after the order is complete?
  
  > **Comments:**
  > **username_0**: Hi username_2, that's what we thought it might be happening. It makes sense to keep order addresses and customer addresses separate so they don't get on each other's way. In our case, it would be good to allow customers to update an order address before the order has shipped so they don't need to contact support to do so. Do you have an idea on what would be the best way to accomplish that?  
  
  ---
  
  