javascript - Angular 父子绑定(bind)变化检测

标签 javascript angular angular-template

简而言之,我有一个用作文本输入的组件。父组件使用 @Input 绑定(bind)将数据传递到此组件。当通过 @Output 绑定(bind)触发更改事件时,我在父组件中执行一些自动验证。这是为了删除错误值并用一些合理的默认值替换它们以获得更好的用户体验。

这是父组件的基本版本

@Component({
    selector: 'parent',
    template: `
    <div>
        <child [value]="item.key1"
               (valueChange)="onValueChange($event)">
            </child>
    </div>
    `
})
export class Parent {
    item = {
        key1: 'test value',
        key2: 'another test value'
    };

    onValueChange(newValue) {
        // Perform some validation and set default
        if (newValue.length > 4) {
            newValue = newValue.substring(0, 4);
        }

        this.item.key1 = newValue;
    }
}

和子组件

@Component({
    selector: 'child',
    template: `
    <div>
        <input type="text"
               [(ngModel)]="value"
               (blur)="onBlur($event)" />
    </div>
    `
})
export class Child {
    @Input() value: string;
    @Output() valueChange = new EventEmitter();

    onBlur() {
        this.valueChange.emit(this.value);
    }
}

参见 here for a Plunker example

我遇到的问题如下:

当在子输入中输入一个值并触发 blur 事件时,新值冒泡到父级并应用验证 - 如果验证导致值被修改,它正确地回到 child 的值(value) - 快乐的日子。

但是,如果前 4 个字符保持不变,并且您追加了其他字符,则在 blur 上仍会应用验证,并且父项的值将正确更新,但子项将保留“无效”值 - 不再有快乐的日子。

所以在我看来 Angular 没有检测到 parent 数据的变化(这很公平,因为它在技术上没有改变)所以它没有将“最新”值发送回 child 。

我的问题是,如何让子文本输入始终显示父项的正确值,即使它在技术上没有“改变”?

最佳答案

更好的解决方案

@Jota.Toledo 的好评让我意识到我的方法,虽然它当时确实是我的一种快速解决方法,但它不是一个好方法,所以我实际上去对我的项目做了一些可行的更改对你也一样,也听从他的建议

Delegating that "validation" logic into the child component

同时将验证定义作为一个函数保留在父级中,该函数作为 @Input 参数传递给子级。

这样我会给父级 2 个公共(public)变量

  • 一个对象(项目)
  • 一个函数(验证)

并更改 onValueChange 函数以仅更新 item.key1,因为它已经过验证。

在 child 中添加一个新的 @Input 类型的 Function 参数(验证)并使用该函数来验证 onBlur 中的新值,然后再将值发送给 parent 。

我觉得我在这里写的内容可能“听起来”有点令人困惑,所以我添加了我想要解释的代码。

parent

@Component({
selector: 'parent',
template: `
<div>
    <p><b>This is the parent component</b></p>
    <child [value]="item.key1"
           [validation]="validation"
           (valueChange)="onValueChange($event)">
        </child>
    <p><b>Variable Value:</b> {{item | json}} </p>
</div>
`
})
   export class Parent {
   item = {
       key1: 'test value',
       key2: 'another test value'
   };

   validation = (newValue) => {
       if (newValue.length > 4) {
           newValue = newValue.substring(0, 4);
       }

       return newValue;
   }

   onValueChange(newValue) {
       this.item.key1 = newValue;
   }
}

子级(模板部分未更改,因为它未更改)

export class Child {
    @Input() value: string;
    @Input() validation: Function;
    @Output() valueChange = new EventEmitter();

    onBlur() {
        this.value = this.validation(this.value)
        this.valueChange.emit(this.value);
    }
}

以前的答案(不是一个好方法)

我过去遇到过类似的问题,我解决的方法是清除我的 var,然后在 setTimeout 中给它最终值而不指定毫秒数。

在你的父组件中它看起来像这样:

onValueChange(newValue) {
    console.log('Initial: ' + newValue);

    if (newValue.length > 4) {
        newValue = newValue.substring(0, 4);
    }
    console.log('Final: ' + newValue);
    this.item.key1 = '';
    setTimeout(() => {
        this.item.key1 = newValue;
    });

}

关于javascript - Angular 父子绑定(bind)变化检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57253822/

相关文章:

angular - 格式化秒数为 mm :ss in Angular 2

angular - 如何设置 ng-content 的样式

angular - 如何在 Angular 中将表单控件重置为原始状态?

java - 如何在 ionic 3 应用程序启动屏幕上设置自定义微调器

html - 从 angular 4 中的 html 中删除主机组件标签

javascript - Angular 5 在某些类中添加了 'ng-star-inserted' - 那是什么?

javascript - 文件更改时 Gulp 不编译我的 sass

javascript - 字符串连接错误

javascript - 如何处理内容更改的 history.pushState

Javascript SyntaxError 重新声明类