Ember Octane How to Get Error Messages to be Displayed?

两盒软妹~` 提交于 2020-05-17 07:01:46

问题


This question is related to Ember Octane Upgrade How to pass values from component to controller

How do I get Ember Octane to display on the webpage? For instance, if the old password and new password are the same we want that error to display on the page.

Ember-Twiddle here

Code example:

User Input Form

ChangePasswordForm.hbs

<div class="middle-box text-center loginscreen animated fadeInDown">
    <div>
        <h3>Change Password</h3>
        <form class="m-t" role="form" {{on "submit" this.changePassword}}>
            {{#each this.errors as |error|}}
                <div class="error-alert">{{error.detail}}</div>
            {{/each}}
            <div class="form-group">
                <Input @type="password" class="form-control" placeholder="Old Password" @value={{this.oldPassword}} required="true" />
            </div>
            <div class="form-group">
                <Input @type="password" class="form-control" placeholder="New Password" @value={{this.newPassword}} required="true" />
            </div>
            <div class="form-group">
                <Input @type="password" class="form-control" placeholder="Confirm Password" @value={{this.confirmPassword}} required="true" />
            </div>
            <div>
                <button type="submit" class="btn btn-primary block full-width m-b">Submit</button>
            </div>
        </form>
    </div>
</div>

Template Component

ChangePassword.hbs

<Clients::ChangePasswordForm @chgpwd={{this.model}} @changePassword={{action 'changePassword'}} @errors={{this.errors}} />

Component

ChangePasswordForm.js

import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';

export default class ChangePasswordForm extends Component {

    @tracked oldPassword;
    @tracked newPassword;
    @tracked confirmPassword;
    @tracked errors = [];

    @action
    changeOldPassword(ev) {
        this.oldPassword = ev.target.value;
    }
    @action
    changeNewPassword(ev) {
        this.newPassword = ev.target.value;
    }
    @action
    changeConfirmPassword(ev) {
        this.confirmPassword = ev.target.value;
    }

    @action
    changePassword(ev) {

        ev.preventDefault();

        this.args.changePassword({
            oldPassword: this.oldPassword,
            newPassword: this.newPassword,
            confirmPassword: this.confirmPassword
        });
    }
}

Controller

ChangePassword.js

import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';

export default class ChangePassword extends Controller {

    @service ajax
    @service session

    @action
    changePassword(attrs) { 

        if(attrs.newPassword == attrs.oldPassword)
        {
shown in the UI.
            this.set('errors', [{
                detail: "The old password and new password are the same.  The password was not changed.",
                status: 1003,
                title: 'Change Password Failed'
            }]);
        }
        else if(attrs.newPassword != attrs.confirmPassword)
        {

            this.set('errors', [{
                detail: "The new password and confirm password must be the same value.  The password was not changed.",
                status: 1003,
                title: 'Change Password Failed'
            }]);
        }
        else
        {

            let token = this.get('session.data.authenticated.token');
            this.ajax.request(this.store.adapterFor('application').get('host') + "/clients/change-password", {
                method: 'POST',
                data: JSON.stringify({ 
                    data: {
                        attributes: {
                            "old-password" : attrs.oldPassword,
                            "new-password" : attrs.newPassword,
                            "confirm-password" : attrs.confirmPassword
                        },
                        type: 'change-passwords'
                    }
                }),
                headers: {
                    'Authorization': `Bearer ${token}`,
                    'Content-Type': 'application/vnd.api+json',
                    'Accept': 'application/vnd.api+json'
                }
            })
            .then(() => {

                this.transitionToRoute('clients.change-password-success');
            })
            .catch((ex) => {

                this.set('errors', ex.payload.errors);
            });
        }
    }
}

Model

ChangePassword.js

import Route from '@ember/routing/route';
import AbcAuthenticatedRouteMixin from '../../mixins/efa-authenticated-route-mixin';

export default class ChangePasswordRoute extends Route.extend(AbcAuthenticatedRouteMixin) {

    model() {

        // Return a new model.
        return {
            oldPassword: '',
            newPassword: '',
            confirmPassword: ''
        };
    }
}

回答1:


In your form component, you reference the errors like

{{#each this.errors as |error|}}
  <div class="error-alert">{{error.detail}}</div>
{{/each}}

From class components -> glimmer components, there's been a fundamental shift in the way you access the component's arguments vs the component's own values (for the better!)

In class components, arguments are assigned directly to the class instance. This has caused a lot of issues over the years, from methods and actions being overwritten, to unclear code where the difference between internal class values and arguments is hard to reason about.

New components solve this by placing all arguments in an object available as the args property.

When referencing an argument to a component in javascript, you use: this.args.someArg. In the template, you use the shorthand @someArg. These are known as "named arguments" (feel free to read the rfc for more info). When you, as you did here, use this.errors in your template, you are looking for a local component property errors.

Just to emphasize, this does not work because errors is passed to Clients::ChangePasswordForm via @errors here:

<Clients::ChangePasswordForm @chgpwd={{this.model}} @changePassword={{action 'changePassword'}} @errors={{this.errors}} />

and must be @errors in the template

{{#each @errors as |error|}}
  <div class="error-alert">{{error.detail}}</div>
{{/each}}


来源:https://stackoverflow.com/questions/60922133/ember-octane-how-to-get-error-messages-to-be-displayed

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!