【问题标题】:Angular 9 - NgModel in custom directive changed behaviour from Angular 7Angular 9 - 自定义指令中的 NgModel 改变了 Angular 7 的行为
【发布时间】:2020-06-05 03:48:05
【问题描述】:

我正在将大型应用程序升级到启用 Ivy 编译的 Angular 9 的过程中,并且遇到了将 NgModel 注入自定义指令的行为似乎发生了变化

使用该指令时,在使用 IVY 编译时,版本 7 和版本 8/9 注入的 NgModel 是不同的。

禁用 Ivy 编译时不会发生这种情况。

指令 (tabSelect)

import { Directive, AfterViewInit, OnDestroy, Optional } from '@angular/core';
import { NgModel } from "@angular/forms";
import { MatAutocompleteTrigger } from '@angular/material/autocomplete';


@Directive({
    selector: '[tabSelect]',
    providers: [NgModel]
})

export class TabSelectDirective implements AfterViewInit, OnDestroy {

    observable: any;
    onChange: any;      

    constructor(@Optional()        
        private autoTrigger: MatAutocompleteTrigger,            
        private ngModel: NgModel) { }
    ngAfterViewInit() {

        this.observable = this.autoTrigger.panelClosingActions.subscribe(x => {
            if (this.autoTrigger.activeOption && this.autoTrigger.activeOption.value) {
                if (this.ngModel.model !== this.autoTrigger.activeOption.value) {
                    this.ngModel.update.emit(this.autoTrigger.activeOption.value);
                    this.autoTrigger.autocomplete.optionSelected.emit();
                }
            } else {
                console.log(this.ngModel);
                console.log(this.autoTrigger);

                if (!this.ngModel.viewModel || this.ngModel.viewModel === "")
                    this.ngModel.update.emit(null);
            };
        });
    }
    ngOnDestroy() {
        this.observable.unsubscribe();
    }
};

在 HTML 中使用指令

<mat-form-field appearance="outline" color="primary" class="mat-input-no-validation pull-right"
                                style="width: 130px; margin-left: 10px">
                    <mat-label>Document Group</mat-label>
                    <input matInput
                           placeholder="Search.."
                           name="documentGroupInput"
                           spellcheck="false"
                           [(ngModel)]="documentNode.documentGroup"
                           [matAutocomplete]="documentGroupAuto"
                           #documentGroupCtrl="ngModel"
                           tabSelect />
                    <div class="small-progress-spinner-container" [hidden]="!documentGroupSearching">
                        <mat-progress-spinner [diameter]="15" [mode]="'indeterminate'"></mat-progress-spinner>
                    </div>
                    <mat-autocomplete #documentGroupAuto="matAutocomplete">
                        <mat-option *ngFor="let documentGroup of documentGroupResults; trackBy:formatters.trackIndex" [value]="documentGroup">
                            <div class="autocomplete-option">
                                {{ documentGroup }}
                            </div>
                        </mat-option>
                    </mat-autocomplete>
                </mat-form-field>

在检查注入指令的 NgModel 时,在 Angular 7 中,我们会看到 Control 名称

NgModel {_parent: NgForm, name: "documentGroupInput", valueAccessor: MatAutocompleteTrigger, _rawValidators: Array(0), _rawAsyncValidators: Array(0), …}

而在 Angular 9 中我们不这样做

NgModel {_parent: NgForm, name: null, valueAccessor: MatAutocompleteTrigger, _rawValidators: Array(0), _rawAsyncValidators: Array(0), …}

这让我相信注入的 NgModel 实际上并不是 Ivy 中控件本身的模型,而这得到了赋值和发出更改事件不再起作用的方法的支持

任何想法发生了什么变化以及我如何解决这个问题?

谢谢

编辑:- 修正代码

import { Directive, AfterViewInit, OnDestroy, Optional } from '@angular/core';
import { NgModel } from "@angular/forms";
import { MatAutocompleteTrigger } from '@angular/material/autocomplete';


@Directive({
    selector: '[tabSelect][ngModel]',
    providers: []
})

export class TabSelectDirective implements AfterViewInit, OnDestroy {

    observable: any;
    onChange: any;      

    constructor(@Optional()        
        private autoTrigger: MatAutocompleteTrigger,            
        private ngModel: NgModel) { }

    ngAfterViewInit() {

        console.log(this.ngModel);
        this.observable = this.autoTrigger.panelClosingActions.subscribe(x => {
            if (this.autoTrigger.activeOption && this.autoTrigger.activeOption.value) {
                if (this.ngModel.model !== this.autoTrigger.activeOption.value) {
                    this.ngModel.update.emit(this.autoTrigger.activeOption.value);
                    this.autoTrigger.autocomplete.optionSelected.emit();
                }
            } else {
                console.log(this.ngModel);
                console.log(this.autoTrigger);

                if (!this.ngModel.viewModel || this.ngModel.viewModel === "")
                    this.ngModel.update.emit(null);
            };
        });
    }
    ngOnDestroy() {
        this.observable.unsubscribe();
    }
};

【问题讨论】:

  • 我正在我的开发笔记本电脑上积极调试这个完全相同的问题,并试图找出解决方案。 this.ngModel.update.emit 确实不再更新期望值。我很高兴我不是唯一一个......

标签: angular angular-directive ivy angular-ngmodel


【解决方案1】:

@Directive 属性中删除providers: [NgModel] 应该可以解决问题。

另见github issue 35594

【讨论】:

  • 谢谢,很好的发现!我将选择器更改为 [tabSelect][ngModel],它再次完美运行
猜你喜欢
  • 2017-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-27
  • 1970-01-01
相关资源
最近更新 更多