I'm trying to modify Craft 3's example 'Change password' form to work with a logged in Commerce 2 user, and have copied that code to templates/setpassword.twig.

Two problems...

(1) The {{ code }} and {{ id }} variables throw Don't exist errors.

(2) If I comment those variables out, I get a Page not found/"Unable to resolve the request: users/setPassword" error when submitting the form.

Clearly I'm doing this totally wrong 🙃... can anyone set me straight?

<form method="post" accept-charset="UTF-8">
{{ csrfInput() }}
<input type="hidden" name="action" value="users/set-password">
<input type="hidden" name="code" value="{{ code }}">
<input type="hidden" name="id" value="{{ id }}">

<h3><label for="newPassword">New Password</label></h3>
<input id="newPassword" type="password" name="newPassword">
{% if errors is defined %}
    <ul class="errors">
        {% for error in errors %}
            <li>{{ error }}</li>
        {% endfor %}
    </ul>
{% endif %}

<input type="submit" value="Submit">

  • Is this for when a user forgets their password, or do you want a form that allows them to change their password at their leisure? – Andrea DeMers Oct 30 at 12:09
  • One that lets them change it at leisure : ) – James Greig Oct 30 at 13:46
up vote 3 down vote accepted

The code you are currently using is for the Set Password form that is used when a user forgets their password and you send them a Password reset email as documented at https://docs.craftcms.com/v3/dev/examples/set-password-form.html.

Here is what I'm using to allow users to change their passwords on demand. It is based on the User Profile Form documented at https://docs.craftcms.com/v3/dev/examples/user-profile-form.html

<form method="post" accept-charset="UTF-8">
    {{ csrfInput() }}
    <input type="hidden" name="action" value="users/save-user">
    {# Change to suit your needs #}
    {{ redirectInput('users/'~currentUser.username) }}
    {# Get logged-in user's ID #}
    <input type="hidden" name="userId" value="{{ currentUser.id }}">

    {% macro errorList(errors) %}
        {% if errors %}
            <ul class="errors">
                {% for error in errors %}
                    <li>{{ error }}</li>
                {% endfor %}
            </ul>
        {% endif %}
    {% endmacro %}

    {% from _self import errorList %}

    {# Enter current password #}
    <h3><label for="password">Current Password</label></h3>
    <input id="password" type="password" name="password">

    {% if account is defined %}
        {{ errorList(user.getErrors('password')) }}
    {% endif %}

    {# Enter new password #}
    <h3><label for="newPassword">New Password</label></h3>
    <input id="newPassword" type="password" name="newPassword">

    {% if account is defined %}
        {{ errorList(user.getErrors('newPassword')) }}
    {% endif %}

    <input type="submit" value="Submit">
</form>

UPDATE: updated form to include error handling.

I raised a PR for this last week but it was closed. Apparently you're not supposed to load those templates from the front end as those variables are not auto-populated by craft. (This code fixes the problem)

  • Note: use that on your own risk. I wouldn't recommend doing so – Robin Schambach Oct 30 at 15:13

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.