gpt4 book ai didi

javascript - 提交和值更改事件上的 Angular 4 ControlValueAccessor 值

转载 作者:数据小太阳 更新时间:2023-10-29 04:19:01 29 4
gpt4 key购买 nike

在我的 Angular (4 + Typescript) 项目中,我使用了已经准备好的组件(这并不重要,因为扩展 ControlValueAccessor 的方式是相同的,但如果这很重要,我使用了 ng2-select),因为更好用户体验和更好的外观。在将它包含到我看到的使用响应式(Reactive)表单的表单组件中之后,在提交时我返回(用于表单控件)基于类 SelectItem 的对象,该类在准备好的组件中使用,以管理选定的项目 - 如下所示:

// console.log(this.myForm.values)
Object {
txtInput: 'value',
// ...
preparedComponent: SelectItem { // <--
id: '1',
text: 'Chosen item'
}
}

因为该组件基本上只是标准选择控件的替代品,所以我期望我会取回以字符串形式形成的所选项目的 ID - 如下所示:

// console.log(this.myForm.values)
Object {
txtInput: 'value',
// ...
preparedComponent: '1' // <--
}

在了解了 ControlValueAccessor 的实际含义及其工作原理之后,我将提交时返回的内容(或者更确切地说是项目更改时返回的方式 - onChange)更改为项目的 ID。问题解决了一段时间,直到我开始设置预定义值(在编辑实例上)以形成控件而不是空值(在添加实例上)。我发现这次 writeValue 正在根据作为预定义值发送给它的内容来分配值以形成控件。因此,如果我将预定义值发送为 ...

Object {
id: '1',
text: 'Chosen item'
}

...这也是 Object on submit 中的值,就像上面的第一个代码示例一样。我为此做了一个解决方法,在调用 writeValue 后立即使用 onChange 分配正确的值来控制。这确实是不正确的做法,但我想不出除此之外的任何事情:

public writeValue(val: any): void {
this.selectedItems = val; // val is for example Object { id: '1', text: 'Chosen item' }

setTimeout(() => {
this.onChange(val.id); // just an example of emitted value, there should be some checks val is object and id exists in real code
}, 0);
}

就我没有开始订阅表单控件的 valueChanges 而言,这也有效。问题在于,每次为准备好的组件分配预定义值时,即使使用 { emitEvent: false } ,提交后也会发出使用的值,返回给订阅者。

所以这就是我想用准备好的组件以某种方式处理的事情,因为我想在提交时从控件中获得正确的值,并且我不希望在值真的没有改变之前向订阅者发出更改,而不仅仅是被替换作为预定义值。任何想法如何处理这将不胜感激。

最佳答案

我不确定我是否理解正确,但我想试一试。

您希望组件的输入为以下类型:

{
id: string,
text: string
}

但是您希望组件的输出 只是所选项目的字符串 ID。

我认为这个数据流有点尴尬。 During initialization, preparedComponent is an object, but when an item is selected you want to turn it into a string.除了类型安全问题之外,它感觉不直观。

为了比较,想象一下使用 ngModel 和文本输入来执行此操作:

<input type="text" [(ngModel)]="preparedComponent" />

您是否希望传入一个对象,并在用户键入时返回一个字符串?可能不是。


但是让我们假设由于某种原因它一定是这样的。您通过修改 ng2-selectControlValueAccessor 的实现,或者创建您自己的组件来实现 ControlValueAccessor 并包装 ng2-选择。 (我不知道你在你的问题中做了哪些)。现在您在选择一个项目时调用 this.onChange(val.id),这会使用字符串 ID 更新父组件。

然后您注意到一个单独的问题,即如果您预定义了一个选定值,ng2-select 会在初始化期间触发一个更改事件。这很奇怪,因为用户还没有与选择控件交互。因此,您尝试通过使用 emitEvent: false 在表单控件上调用 setValue 来初始化 preparedComponent,但我猜这是行不通的,因为虽然它可能在您初始化数据时阻止了更改事件的发生,ng2-select 立即对您的数据进行了第二次更改。

因此,您通过等到 ng2-select 的第一次更新将父组件更新为新对象来解决此问题,然后(使用 setTimeout)您用你真正想要的字符串 ID 覆盖它。这使 preparedComponent 与字符串保持同步,但并没有解决更改事件触发的问题,即使用户没有与控件交互也是如此。 (顺便说一句,如果你用自己的组件包装 ng2-select 那么我不确定你为什么必须做这个 setTimeout 部分,因为不会正如我在上一段中提到的,当 ng2-select 通知您一个新的选定项目时,您是否已经有另一个调用 this.onChange(val.id) 的函数? )


因为我不知道你是直接修改ng2-select,还是用你自己的组件包装它:

如果您正在修改 ng2-select,为什么不直接找到它的 writeValue 方法并删除发出事件的代码?这样它会在您预定义一个值时更新 DOM,但不会覆盖您的值。

如果你用你自己的组件包装 ng2-select,为什么不修改你的 writeValue 方法来存储一个标志 if ng2-select 即将触发一个事件,因此您可以忽略它:

private: ignoreSelectedEvent = false;

public writeValue(val: any): void {
this.ignoreSelectedEvent = true;

// Update ng2-select, which will cause an event to fire
}

然后在您对新选择的项目使用react的函数中:

if (this.ignoreSelectedEvent) {
this.ignoreSelectedEvent = false;

return;
}

// Update the model with the string ID

this.onChange(val.id);

关于javascript - 提交和值更改事件上的 Angular 4 ControlValueAccessor 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43515028/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com