Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tabs(ivy): ivy-ngcc can't handle Inputs from an abstract class w/o a decorator like _MatTabGroupBase #17121

Closed
ErVishalM opened this issue Sep 16, 2019 · 32 comments · Fixed by #17228
Assignees
Labels
P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful regression This issue is related to a regression
Milestone

Comments

@ErVishalM
Copy link

Hi,

I am getting this error after upgrade in current cli in mat-tab-group.
Property 'selectedIndex' does not exist on type 'HTMLElement'

Example picking from Angular Website and run after the upgrade to latest then getting this error previously it was not giving any error.
HTML Code is -

<mat-tab-group [selectedIndex]="selected.value"
               (selectedIndexChange)="selected.setValue($event)">
  <mat-tab *ngFor="let tab of tabs; let index = index" [label]="tab">
    Contents for {{tab}} tab

    <button mat-raised-button
            class="example-delete-tab-button"
            [disabled]="tabs.length === 1"
            (click)="removeTab(index)">
      Delete Tab
    </button>
  </mat-tab>
</mat-tab-group>

Component Code is-

import {Component} from '@angular/core';
import {FormControl} from '@angular/forms';

/**
 * @title Tab group with dynamically changing tabs
 */
@Component({
  selector: 'tab-group-dynamic-example',
  templateUrl: 'tab-group-dynamic-example.html',
  styleUrls: ['tab-group-dynamic-example.css'],
})
export class TabGroupDynamicExample {
  tabs = ['First', 'Second', 'Third'];
  selected = new FormControl(0);

  addTab(selectAfterAdding: boolean) {
    this.tabs.push('New');

    if (selectAfterAdding) {
      this.selected.setValue(this.tabs.length - 1);
    }
  }

  removeTab(index: number) {
    this.tabs.splice(index, 1);
  }
}

Package.json is

{
  "name": "WFXERPAg",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^8.2.6",
    "@angular/cdk": "^8.2.0",
    "@angular/common": "~8.2.6",
    "@angular/compiler": "~8.2.6",
    "@angular/core": "~8.2.6",
    "@angular/forms": "~8.2.6",
    "@angular/material": "^8.2.0",
    "@angular/material-moment-adapter": "^8.2.0",
    "@angular/platform-browser": "~8.2.6",
    "@angular/platform-browser-dynamic": "~8.2.6",
    "@angular/router": "~8.2.6",
    "core-js": "^3.1.4",
    "jquery": "^3.4.0",
    "jquery-ui": "^1.12.1",
    "jquery-ui-dist": "^1.12.1",
    "moment": "^2.24.0",
    "rxjs": "~6.5.3",
    "tslib": "^1.9.0",
    "zone.js": "~0.9.1"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.803.0",
    "@angular/cli": "~8.3.4",
    "@angular/compiler-cli": "~8.2.6",
    "@angular/language-service": "~8.2.6",
    "@types/jasmine": "~2.8.8",
    "@types/jasminewd2": "~2.0.3",
    "@types/node": "^8.9.5",
    "codelyzer": "^5.0.1",
    "jasmine-core": "~2.99.1",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~4.0.0",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "~2.0.1",
    "karma-jasmine": "~1.1.2",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.4.0",
    "ts-node": "~7.0.0",
    "tslint": "^5.20.0",
    "typescript": "~3.5.3"
  }
}
@Splaktar
Copy link
Member

Please submit Angular Material and CDK questions here and issues here. This repo is for AngularJS Material.

I have transferred this issue to the correct repository for you.

@Splaktar Splaktar changed the title Property 'selectedIndex' does not exist on type 'HTMLElement' after upgrade in current angular cli in mat-tab-group. tabs: property 'selectedIndex' does not exist on type 'HTMLElement' Sep 17, 2019
@Splaktar Splaktar transferred this issue from angular/material Sep 17, 2019
@ErVishalM
Copy link
Author

@Splaktar Thank you sir. Previously i was not getting any error in this but i updated all my packages to latest then suddenly i got this error.

@Splaktar
Copy link
Member

@ErVishalM can you please provide the versions that you were at before?

@ErVishalM
Copy link
Author

@Splaktar I'm sorry buddy but is there any command to check previous version? But I remember it was not that much old because I update angular packages on daily basis. But I can give you my other machine package.json file in which I keep backup and in that version it is working fine but it may not be the last version I had because it's been 10-12 days I did not take backup of my project.

@ErVishalM
Copy link
Author

ErVishalM commented Sep 19, 2019

Hi @Splaktar I've found the previous version file please check my package.json file. In this it was working fine.

{
    "name": "Project",
    "version": "0.0.0",
    "scripts": {
        "ng": "ng",
        "start": "ng serve",
        "build": "ng build",
        "test": "ng test",
        "lint": "ng lint",
        "e2e": "ng e2e"
    },
    "private": true,
    "dependencies": {
        "@angular/animations": "^8.2.4",
        "@angular/cdk": "^8.1.4",
        "@angular/common": "~8.2.4",
        "@angular/compiler": "~8.2.4",
        "@angular/core": "~8.2.4",
        "@angular/forms": "~8.2.4",
        "@angular/material": "^8.1.4",
        "@angular/material-moment-adapter": "^8.1.3",
        "@angular/platform-browser": "~8.2.4",
        "@angular/platform-browser-dynamic": "~8.2.4",
        "@angular/router": "~8.2.4",
        "ag-grid-angular": "^21.2.0",
        "ag-grid-community": "^21.2.0",
        "ag-grid-enterprise": "^21.2.0",
        "angular-hammer": "^2.2.0",
        "core-js": "^3.1.4",
        "jquery": "^3.4.0",
        "jquery-ui": "^1.12.1",
        "jquery-ui-dist": "^1.12.1",
        "moment": "^2.24.0",
        "ngx-mat-select-search": "^1.7.2",
        "rxjs": "~6.5.2",
        "tslib": "^1.9.0",
        "zone.js": "~0.9.1"
    },
    "devDependencies": {
        "@angular-devkit/build-angular": "~0.803.0",
        "@angular/cli": "~8.3.2",
        "@angular/compiler-cli": "~8.2.4",
        "@angular/language-service": "~8.2.4",
        "@types/jasmine": "~2.8.8",
        "@types/jasminewd2": "~2.0.3",
        "@types/node": "^8.9.5",
        "codelyzer": "^5.0.1",
        "jasmine-core": "~2.99.1",
        "jasmine-spec-reporter": "~4.2.1",
        "karma": "~4.0.0",
        "karma-chrome-launcher": "~2.2.0",
        "karma-coverage-istanbul-reporter": "~2.0.1",
        "karma-jasmine": "~1.1.2",
        "karma-jasmine-html-reporter": "^0.2.2",
        "protractor": "~5.4.0",
        "ts-node": "~7.0.0",
        "tslint": "~5.11.0",
        "typescript": "~3.5.3"
    }
}

@ErVishalM
Copy link
Author

@Splaktar any update on this issue?

@Splaktar
Copy link
Member

Do you have or can you create a repository for us to reproduce and debug this issue?

@ErVishalM
Copy link
Author

@Splaktar I am sorry i dont know how to upload to github or any other website but yeah I have added project in my google drive and you can access it and
download it
and you have to just npm install and then ng serve you will get an error. i have attached ss also.
Annotation 2019-09-27 194029

@Splaktar
Copy link
Member

@ErVishalM is it OK if I post it on GitHub so that I can link to parts of the code for discussion?

@ErVishalM
Copy link
Author

@Splaktar yes Sir of course. Actually i did not know the process to do that, that is why i could not do that.

@Splaktar
Copy link
Member

OK, I did some minor refactoring since the project wasn't fully migrated to the Angular CLI version 8 format. But that wasn't causing this issue.

I also reverted to Angular Material 8.1.4 and this is still reproducible. I think that it's an issue with how your module import/exports are set up but I haven't figured out the fix yet.

The reproduction repo is here.

@Splaktar
Copy link
Member

If I disable Ivy here, then it builds just fine.

@Splaktar Splaktar changed the title tabs: property 'selectedIndex' does not exist on type 'HTMLElement' tabs(ivy): property 'selectedIndex' does not exist on type 'HTMLElement' Sep 27, 2019
@Splaktar Splaktar self-assigned this Sep 27, 2019
@Splaktar
Copy link
Member

Splaktar commented Sep 27, 2019

Updating to Angular 9.0.0-next.8 gives a little bit better error message with Ivy enabled (by default):

ERROR - error TS8002: 'selectedIndex' is not a valid property of <mat-tab-group>.

25         <mat-tab-group [selectedIndex]="1"
                          ~~~~~~~~~~~~~~~~~~~

@Splaktar
Copy link
Member

Splaktar commented Sep 27, 2019

With Ivy enabled, this still fails back to Angular Material 8.0.0. It does build with 7.3.7 though.

@Splaktar Splaktar added P2 The issue is important to a large percentage of users, with a workaround regression This issue is related to a regression labels Sep 27, 2019
@Splaktar
Copy link
Member

Note that using Angular Material 7.3.7 with Angular 8.2.8 with Ivy enabled fails at runtime with many of these exceptions:

ERROR TypeError: Cannot read property 'nativeElement' of undefined
    at MatTabGroup._removeTabBodyWrapperHeight (tabs.js:1809)
    at MatTabGroup_mat_tab_body_5_Template_mat_tab_body__onCentered_0_listener (tabs.js:119)
    at executeListenerWithErrorHandling (core.js:22181)
    at wrapListenerIn_markDirtyAndPreventDefault (core.js:22216)
    at core.js:35373
    at ZoneDelegate.invokeTask (zone-evergreen.js:391)
    at Object.onInvokeTask (core.js:39687)
    at ZoneDelegate.invokeTask (zone-evergreen.js:390)
    at Zone.runTask (zone-evergreen.js:168)
    at invokeTask (zone-evergreen.js:465)
    at ZoneTask.invoke (zone-evergreen.js:454)
    at timer (zone-evergreen.js:2650)
core.js:6014 ERROR TypeError: Cannot read property 'nativeElement' of undefined
    at MatTabHeader._checkPaginationEnabled (tabs.js:1272)
    at MatTabHeader.updatePagination (tabs.js:1083)
    at MatTabHeader.ngAfterContentChecked (tabs.js:942)
    at callHook (core.js:3097)
    at callHooks (core.js:3057)
    at executeHooks (core.js:3008)
    at refreshDescendantViews (core.js:11742)
    at checkView (core.js:13616)
    at componentRefresh (core.js:13359)
    at refreshChildComponents (core.js:11858)
    at refreshDescendantViews (core.js:11757)
    at checkView (core.js:13616)
    at componentRefresh (core.js:13359)
    at refreshChildComponents (core.js:11858)
    at refreshDescendantViews (core.js:11757)

@Splaktar Splaktar removed their assignment Sep 27, 2019
@Splaktar
Copy link
Member

Splaktar commented Sep 27, 2019

Note that this affects other @Inputs that use setter/getters like dynamicHeight:

ERROR in src/app/lib/tabs/tabs.component.ts(25,24): Property 'dynamicHeight' does not exist on type 'HTMLElement'.

If you don't use data binding, it doesn't fail to build

selectedIndex="0" dynamicHeight="true"

But if you do, it fails:

[selectedIndex]="selectedControl.value" [dynamicHeight]="'true'"
    ERROR in src/app/lib/tabs/tabs.component.ts(25,24): Property 'selectedIndex' does not exist on type 'HTMLElement'.
    src/app/lib/tabs/tabs.component.ts(25,64): Property 'dynamicHeight' does not exist on type 'HTMLElement'.

@Splaktar Splaktar changed the title tabs(ivy): property 'selectedIndex' does not exist on type 'HTMLElement' tabs(ivy): Inputs that are associated with setter/getters don't build when data binding is used Sep 27, 2019
@ErVishalM
Copy link
Author

@Splaktar how did you know it's not migrated correctly, May I know. And about this issue, this will be fix right?

@Splaktar
Copy link
Member

Splaktar commented Sep 27, 2019

@ErVishalM see this commit for related changes:

  • Extra browserslist in src/ removed
  • tsconfig.app/spec.json moved to root
  • tsconfig.app.json updated for Ivy w/ files and include
  • tsconfig.json updated for Ivy

Yes, we've identified the issue and will work on a fix or submit a bug to angular/angular if needed.

@ErVishalM
Copy link
Author

ErVishalM commented Sep 28, 2019

Not migrated completely that is also a mistake. I saw from here how to upgrade from 7 to 8. What there is mentioned I did everything but it was incomplete 😥

@Splaktar
Copy link
Member

@ErVishalM it looks like you either didn't run ng update @angular/cli @angular/core or the migration failed in some way. Not all of the items in that list are part of the 7->8 update, a couple are from the 8-9 update.

@ErVishalM
Copy link
Author

ErVishalM commented Sep 28, 2019

If this is the only command ng update @angular/cli @angular/core then i ran this command so many times after v7. I check daily basis of any update is coming in my project. But yeah it's a silly mistake. What I am doing now is I'll update ng update @angular/cli globally and then I'll create a new project and then copy all of my files into that project. This will be correct right?

@Splaktar
Copy link
Member

Splaktar commented Sep 29, 2019

@ErVishalM what you can do is ng update @angular/cli --migrate-only --from=7 --to=8 and it will try to re-run any migration schematics. Some of the very early 8.0.0 versions didn't include the full set of migrations needed.

@Splaktar
Copy link
Member

Splaktar commented Sep 29, 2019

As for debugging this issue, none of the mat-tab-group Inputs show up in the ngComponentDef generated from ngcc:

static ngComponentDef: ɵngcc0.ɵɵComponentDefWithMeta<MatTabGroup, "mat-tab-group", ["matTabGroup"], { 'color': "color", 'disableRipple': "disableRipple" }, {}, ["_tabs"]>;

So this looks like an issue with ngcc.

@Splaktar
Copy link
Member

Splaktar commented Sep 29, 2019

The associated ngcc bugs appear to be

There also appear to be some related errors mentioned in angular/angular#32466 (comment).

sebholstein/angular-google-maps#1647 (comment) mentions that the issue could be related to the way that decorators are emitted.

@JoostK
Copy link
Member

JoostK commented Sep 29, 2019

@Splaktar I don't think those are indeed the cause for this issue, but rather it's angular/angular#30080. The _MatTabGroupBase is an abstract base class without Angular decorator at the class-level, so currently it is compiled into an ngBaseDef which is not currently handled in the template type checker.

@Splaktar
Copy link
Member

Originally it looked like ngcc was ignoring a bunch of @Inputs when they were associated with get/set methods.

/** Whether the tab group should grow to the size of the active tab. */
@Input()
get dynamicHeight(): boolean { return this._dynamicHeight; }
set dynamicHeight(value: boolean) { this._dynamicHeight = coerceBooleanProperty(value); }
private _dynamicHeight: boolean = false;
/** The index of the active tab. */
@Input()
get selectedIndex(): number | null { return this._selectedIndex; }
set selectedIndex(value: number | null) {
this._indexToSelect = coerceNumberProperty(value, null);
}
private _selectedIndex: number | null = null;
/** Position of the tab header. */
@Input() headerPosition: MatTabHeaderPosition = 'above';
/** Duration for the tab animation. Will be normalized to milliseconds if no units are set. */
@Input()
get animationDuration(): string { return this._animationDuration; }
set animationDuration(value: string) {
this._animationDuration = /^\d+$/.test(value) ? value + 'ms' : value;
}
private _animationDuration: string;
/** Background color of the tab group. */
@Input()
get backgroundColor(): ThemePalette { return this._backgroundColor; }
set backgroundColor(value: ThemePalette) {
const nativeElement: HTMLElement = this._elementRef.nativeElement;
nativeElement.classList.remove(`mat-background-${this.backgroundColor}`);
if (value) {
nativeElement.classList.add(`mat-background-${value}`);
}
this._backgroundColor = value;
}

But now it is looking more like this could be due to MatTabGroup's @Inputs all coming from _MatTabGroupBase:

export class MatTabGroup extends _MatTabGroupBase {

@Splaktar Splaktar changed the title tabs(ivy): Inputs that are associated with setter/getters don't build when data binding is used tabs(ivy): ivy-ngcc can't handle Inputs from an abstract class w/o a decorator like _MatTabGroupBase Sep 29, 2019
@Splaktar
Copy link
Member

Splaktar commented Sep 29, 2019

It looks like we need to add something similar to the following for each Abstract Base Class that includes any kind of Decorator:

@Directive({selector: 'mat-tab-group-base'})

We can't use empty selectors (i.e. @Directive()) since those are only supported in Angular 9.0.0-next.3.

Angular Flex Layout had to do something similar in angular/flex-layout#1114 for Ivy support.

Ideally, this would be fixed in ivy-ngcc as this shouldn't be a breaking change to all libraries at final... I hope.

@Splaktar
Copy link
Member

Adding that causes the following build error:

Cannot determine the module for class _MatTabGroupBase in /Users/splaktar/Git/angular/material2/src/material/tabs/tab-group.ts! Add _MatTabGroupBase to the NgModule to fix it.

Adding that to MatTabsModule

  declarations: [
    _MatTabGroupBase,

Causes this build error:

tabs-module.ts(26,11): error TS2345: Argument of type '{ imports: (typeof CommonModule | typeof MatCommonModule)[]; exports: (typeof MatTabContent | typeof MatTabLabel | typeof MatTab | typeof MatTabGroup | typeof MatTabNav | typeof MatTabLink | typeof MatCommonModule)[]; declarations: (typeof MatTabContent | ... 9 more ... | typeof MatTabHeader)[]; }' is not assignable to parameter of type 'NgModule'.
  Types of property 'declarations' are incompatible.
    Type '(typeof MatTabContent | typeof MatTabLabel | typeof MatTab | typeof _MatTabGroupBase | typeof MatInkBar | typeof MatTabLabelWrapper | typeof MatTabNav | typeof MatTabLink | typeof MatTabBodyPortal | typeof MatTabBody | typeof MatTabHeader)[]' is not assignable to type '(any[] | Type<any>)[]'.
      Type 'typeof MatTabContent | typeof MatTabLabel | typeof MatTab | typeof _MatTabGroupBase | typeof MatInkBar | typeof MatTabLabelWrapper | typeof MatTabNav | typeof MatTabLink | typeof MatTabBodyPortal | typeof MatTabBody | typeof MatTabHeader' is not assignable to type 'any[] | Type<any>'.
        Type 'typeof _MatTabGroupBase' is not assignable to type 'any[] | Type<any>'.
          Type 'typeof _MatTabGroupBase' is not assignable to type 'Type<any>'.
            Cannot assign an abstract constructor type to a non-abstract constructor type.

@crisbeto crisbeto self-assigned this Sep 29, 2019
crisbeto added a commit to crisbeto/material2 that referenced this issue Sep 29, 2019
Along the same lines as angular#17022. Adds annotations to the various base classes that declare inputs, because the Ivy template type checker doesn't handle base defs at the moment.

Fixes angular#17121.
@SerkanSipahi
Copy link
Contributor

SerkanSipahi commented Sep 29, 2019

@crisbeto @Splaktar will be this fix only for Angular 9 Next available or do you guys will deploy this fix also for Angular 8.x.x (Ivy Enabled)?

@Splaktar
Copy link
Member

Splaktar commented Sep 29, 2019

Based on PR #17022 and PR #17228, it looks like you would actually need to either

  • create a whole new _MatTabGroupBaseModule to get this to compile
  • add them to declarations as any like _MatTabGroupBase as any,

It also looks like @jelbourn wants these module and selector names prepended with DoNotUse or do-not-use.

It looks like the combination of those 2 PRs should fix these issues for Angular Material w/ Ivy.

@Splaktar
Copy link
Member

@SerkanSipahi I believe that this can be fixed in Angular Material 8.2.x.

@jelbourn jelbourn added this to the 9.0.0 milestone Sep 30, 2019
@mmalerba mmalerba added P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful and removed P2 The issue is important to a large percentage of users, with a workaround labels Oct 1, 2019
mmalerba pushed a commit that referenced this issue Oct 1, 2019
Along the same lines as #17022. Adds annotations to the various base classes that declare inputs, because the Ivy template type checker doesn't handle base defs at the moment.

Fixes #17121.
mmalerba pushed a commit that referenced this issue Oct 8, 2019
Along the same lines as #17022. Adds annotations to the various base classes that declare inputs, because the Ivy template type checker doesn't handle base defs at the moment.

Fixes #17121.

(cherry picked from commit 8c98013)
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Nov 1, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful regression This issue is related to a regression
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants