<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>

CC BY-SA 3.0
2017-07-12T06:07:52.580Z
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
Alberto
CC BY-SA 3.0
2017-07-11T04:38:47.060Z
2017-07-11T04:38:47.060Z
Luke Holder
<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>

CC BY-SA 3.0
2017-07-07T05:39:02.503Z
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?
Alberto
CC BY-SA 3.0
2017-07-06T04:13:12.400Z
2017-07-06T04:13:12.400Z
Luke Holder
<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>

CC BY-SA 3.0
2017-07-05T18:07:46.070Z
Does that same order load in the Control Panel fine? If so, does it show the correct address?
Brad Bell
CC BY-SA 3.0
2017-07-06T02:59:26.073Z
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
Alberto
<plugin-craftcommerce><order><addresses>
Craft Commerce - Edit Complete Order Address from frontend
# 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,
Alberto

**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 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  

---

## 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 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  

---

### 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 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?  

---

