Ember Octane Как получить сообщения об ошибках для отображения? - PullRequest
0 голосов
/ 30 марта 2020

Этот вопрос относится к Обновлению Ember Octane Как передать значения из компонента в контроллер

Как мне заставить Ember Octane отображаться на веб-странице? Например, если старый пароль и новый пароль совпадают, мы хотим, чтобы эта ошибка отображалась на странице.

Ember-Twiddle здесь

Пример кода:

Форма ввода пользователя

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>

Компонент шаблона

ChangePassword.hbs

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

Компонент

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
        });
    }
}

Контроллер

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);
            });
        }
    }
}

Модель

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 Ответ

2 голосов
/ 31 марта 2020

В вашем компоненте формы вы ссылаетесь на такие ошибки, как

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

В компонентах класса -> компонентах glimmer произошел фундаментальный сдвиг в доступе к аргументам компонента по сравнению с его собственными значениями (для тем лучше!)

В компонентах класса аргументы присваиваются непосредственно экземпляру класса. В течение многих лет это вызывало множество проблем - от перезаписываемых методов и действий до неясного кода, в котором трудно рассуждать о разнице между внутренними значениями классов и аргументами.

Новые компоненты решают эту проблему, помещая все аргументы в объекте, доступном как свойство args.

При ссылке аргумента на компонент в javascript вы используете: this.args.someArg. В шаблоне вы используете сокращение @someArg. Они известны как «именованные аргументы» (не стесняйтесь читать rf c для получения дополнительной информации). Когда вы, как и здесь, используете this.errors в своем шаблоне, вы ищете локальное свойство компонента errors.

Просто чтобы подчеркнуть, это не работает, потому что ошибки передаются в Clients::ChangePasswordForm через @errors здесь:

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

и должно быть @errors в шаблоне

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