Angular 9 - NgModel в пользовательской директиве изменил поведение с Angular 7 - PullRequest
1 голос
/ 20 февраля 2020

Я частично прошёл модернизацию большого приложения до Angular 9 с включенной компиляцией Ivy, и натолкнулся на то, что кажется изменением в поведении при введении NgModel в пользовательскую директиву

При использовании эта директива, внедряемая NgModel, отличается между версией 7 и версией 8/9, когда используется компиляция IVY.

ЭТОГО НЕ происходит, когда компиляция 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 мы видим имя элемента управления

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

1 Ответ

1 голос
/ 21 февраля 2020

Удаление providers: [NgModel] из атрибута @Directive должно решить проблему.

См. Также GitHub Issue 35594

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...