ember.js 如何调用Ember Octane Glimmer组件@操作?

r6l8ljro  于 2022-11-05  发布在  其他
关注(0)|答案(2)|浏览(174)

此问题与Ember Octane Upgrade How to pass values from component to controller相关
我很难从HBS表单接收值并将其赋值到一个组件中,然后将其传递给控制器。工作答案表明我必须为每个表单字段创建一个@action函数。例如:

@action
changeNewPassword(ev) {
    this.newPassword = ev.target.value;
}

但是,我不明白这些功能是在哪里或如何调用的,因此我不明白它们为什么工作。有人知道这些功能是如何调用的吗?
模板组件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>

模板HBS

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

模板组件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
        });
    }
}
2w2cym1i

2w2cym1i1#

在Ember Octane中,您希望使用on修改器来设置动作。

<form class="m-t" role="form" {{on "submit" this.changePassword}}>

有效地为该表单元素的submit事件设置事件侦听器,该事件侦听器将调用组件类上的changePassword函数(因为this.changePassword中的this表示该函数是组件的本地函数)
调用此操作的:

@action
changePassword(ev) {

  ev.preventDefault();

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

changePassword操作又调用changePassword函数,该函数在命名参数@changePassword下传递给组件

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

现在,在Template Component JS中,您有三个其他操作

  1. changeOldPassword
  2. changeNewPassword
  3. changeConfirmPassword
    从你贴出的代码中我可以看出,它们从来没有被使用过。它们看起来像是你用来设置单向绑定输入的代码,但您使用的是内置的Input,即Ember input built-in component(并且在输入值和@value之间使用双向绑定)。需要注意的一个非常重要的区别是Input上的大写I。所有尖括号组件都使用标题大小写(每个单独的单词都以大写字母开头)。
    如果你做了这样的事情:
<input type="password" class="form-control" placeholder="New Password" value={{this.newPassword}} {{on 'input' this.changeNewPassword}} required="true">

然后将this.changeNewPassword函数绑定到<input>元素的input事件(它是原生html <input>。使用您定义的changeNewPassword操作:

@action
changeNewPassword(ev) {
  this.newPassword = ev.target.value;
}

您应该通过单向绑定使this.newPassword值与输入保持同步。

gkn4icbw

gkn4icbw2#

我认为您在示例中使用操作的方式有两种。
1.通过{{on}}

<form class="m-t" role="form" {{on "submit" this.changePassword}}>

这种情况更简单,当在组件模板中执行this时,您引用的是组件的类,因此,当form元素中发生submit DOM事件时,模板将调用this.changePassword
您可以在{{on}} API docs中查看更多信息。
1.通过{{action}}

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

在这种情况下,每当@changePasswordClients::ChangePasswordForm中被触发时,Ember将在操作哈希(经典语法)或使用Clients::ChangePasswordForm的组件的类中的装饰方法(@action)中搜索changePassword
您可以在{{action}} API docs中查看更多信息。
希望这有助于阐明作用机制。
对于额外的家庭作业,您可能需要检查upgrade guides on actions

相关问题