Skip to content

[Ivy] @ViewChild doesn't read me ElementRef #28643

Closed

Description

@wKoza

🐞 bug report

Affected Package

The issue is caused by package @angular/core

Is this a regression?

Maybe, it seems to be available if we read this status

Description

I'm testing Ivy on a little application with the beta.3 but I have a component like this:

@Component({
    selector: 'tracklist',
    templateUrl: './tracklist.component.html',
    styleUrls: ['./tracklist.component.css'],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class TracklistComponent implements AfterViewInit {
...
    @ViewChild('matTable', {read: ElementRef}) elRef;

constructor(private route: ActivatedRoute, private renderer: Renderer2) { }


ngAfterViewInit() {
...
  this.renderer.setStyle(this.elRef.nativeElement, 'overflow-y', 'hidden');
}

When I run ng serve --aot and I instantiate this component, I have this error:


Error TypeError : Cannot read property 'nativeElement' of undefined

elRef is always undefined.

🌍 Your Environment

Angular Version:


Angular CLI: 7.2.4
Node: 10.10.0
OS: darwin x64
Angular: 8.0.0-beta.3
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, platform-server, router
... service-worker

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.12.4
@angular-devkit/build-angular     0.12.4
@angular-devkit/build-optimizer   0.12.4
@angular-devkit/build-webpack     0.12.4
@angular-devkit/core              7.2.4
@angular-devkit/schematics        7.2.4
@angular/cdk                      7.3.1
@angular/cli                      7.2.4
@angular/material                 7.3.1
@ngtools/webpack                  7.2.4
@schematics/angular               7.2.4
@schematics/update                0.12.4
rxjs                              6.3.3
typescript                        3.2.4
webpack                           4.28.4

Activity

  1. added this to the needsTriage milestone on Feb 11, 2019
  2. alexzuza commented on Feb 11, 2019

    @alexzuza
    Contributor

    Can you please create a small reproducible example?

    Seems it works well for me with simple component

    @Component({
      selector: 'child',
      template: `<h2>Child</h2>`
    })
    export class ChildComponent {}
    
    
    @Component({
      selector: 'my-app',
      template: `<child #matTable></child> `
    })
    export class AppComponent {
       @ViewChild('matTable', {read: ElementRef}) elRef;
    
       ngAfterViewInit() {
         console.log(this.elRef.nativeElement);
       }
    }
    

    https://alexzuza.github.io/ivy-jit-preview/#hVLNasJAEL7nKQZ6SAJRoUcV0aoHD22hlF6K0DUZden.hN1VK5LH6kP0rTrZmBBR2lM2s9_PfjPDZa6NgxNMNZ0UKpfAjBtMHd9jAguV76jy8y2Z.aS6OwKz0Pwk8LR51NlOEHS.J_JccufQJPC8c575xvEw3XKREUCgJMgLrqGAtdESwjFTm51gppdqg.Eg4PVrcsHcWhv5YPTBopkdFZM8vebVuM6qAnayCtnWOmtU7_xfgqhBMG7aEZ0CAIuCOqJNH8K0DBMmVHQoSy724WO4vR_5lMMenT6CIg7wy9unglkL_q6RhFPxp4U8dlieX3l4Z7iTzL2ylcDRsOcrI7j2m.R5y410YNwMIgprhTCBk0GW9VujKWJAQV9qArHUZrKmcZbcheIuiisxgFQrqwV2hd5Ebstt15O6ipVrc1aLByW2CHzYek981mo0tg_vF7NZlokzpAiGdMiBAN6uHSfxlcuGUslzV1o76wzLidjmLG816LwP5Sxub1sUdxvB8.MbGmX7BQ

    (You need to run Start and see console)

  3. wKoza commented on Feb 11, 2019

    @wKoza
    ContributorAuthor

    Two things about my problem:

    • Ivy and ViewRenderer don't seem to have the same behavior when an error is thrown:
    @Component({
      selector: 'app-root',
      template: `
          <div #matTable>
            <app-error></app-error>
          </div>`
    })
    export class AppComponent implements OnInit, AfterViewInit {
    
      @ViewChild('matTable', {read: ElementRef}) elRef;
    
      ngAfterViewInit(): void {
        console.log(this.elRef.nativeElement);
      }
    }
    
    @Component({
      selector: 'app-error',
      templateUrl: './error.component.html',
      styleUrls: ['./error.component.css']
    })
    export class ErrorComponent implements OnInit {
    
      constructor() { }
    
      ngOnInit() {
        throw new Error('error')
      }
    
    }

    With ViewRenderer, I can recover my elRef and I can see this error in the console

    AppComponent_Host.ngfactory.js? [sm]:1 ERROR Error: error
        at ErrorComponent.push../src/app/error/error.component.ts.ErrorComponent.ngOnInit (error.component.ts:13)
    

    With Ivy, I can't recover my elRef and I can see this error in the console:

    ERROR TypeError: Cannot read property 'nativeElement' of undefined
        at AppComponent.push../src/app/app.component.ts.AppComponent.ngAfterViewInit (app.component.ts:23)
    

    It's expected ? The behavior is really not the same.

    BTW, my initial problem is more a problem with material / ivy-ngcc I think. This is a small repo Github of my problem :

    https://github.com/wKoza/ivy28643

    If you comment changeDetection: ChangeDetectionStrategy.OnPush , you can see the real exception (which should not happen) .

    ERROR TypeError: Cannot read property 'toArray' of undefined at mergeQueryListAndSet (VM65620 vendor.js:23925) at MatTable.push../node_modules/@angular/cdk/esm5/table.es5.js.CdkTable._cacheRowDefs (VM65620 vendor.js:23275) at MatTable.push../node_modules/@angular/cdk/esm5/table.es5.js.CdkTable.ngAfterContentChecked (VM65620 vendor.js:22732) at callHooks (VM65620 vendor.js:38913) at executeHooks (VM65620 vendor.js:38879) at refreshDescendantViews (VM65620 vendor.js:43954) at checkView (VM65620 vendor.js:46260) at componentRefresh (VM65620 vendor.js:45890) at refreshChildComponents (VM65620 vendor.js:44012) at refreshDescendantViews (VM65620 vendor.js:43957)
    You're right @alexzuza, it works well in absolute and kudo for your application
  4. alexzuza commented on Feb 11, 2019

    @alexzuza
    Contributor

    @wKoza Thank you for the repo.

    You're right that the error Cannot read property 'toArray' of undefined at mergeQueryListAndSet can't be seen with OnPush since that error is eaten by this code.

    try {
    namespaceHTML();
    creationMode && executeViewQueryFn(hostView, hostTView, component);
    templateFn(getRenderFlags(hostView), component);
    refreshDescendantViews(hostView);
    !creationMode && executeViewQueryFn(hostView, hostTView, component);
    } finally {
    leaveView(oldView);
    }

    And you are also right that the error has something to do with ngcc.

    It doesn't generate features: [InheritDefinitionFeature] for component definitions like MatTable, CdkRowDef, etc.

    cc: @petebacondarwin

  5. gkalpak commented on Feb 11, 2019

    @gkalpak
    Member

    FYI: I just run in the inheritance issue myself and working on a fix for ngcc.

  6. wKoza commented on Feb 13, 2019

    @wKoza
    ContributorAuthor

    @pkozlowski-opensource , What do you think about the first point ?

  7. pkozlowski-opensource commented on Feb 13, 2019

    @pkozlowski-opensource
    Member

    @wKoza hmm, seems like a super-corner case but @marclaval was looking into exception thrown during lifecycle hooks processing - I don't remember the details but hopefully @marclaval has better memory :-)

  8. wKoza commented on Feb 19, 2019

    @wKoza
    ContributorAuthor

    @marclaval , our master brain, can you tell me whether this behavior (the first point) is expected ?

  9. marclaval commented on Feb 19, 2019

    @marclaval
    Contributor

    In #28239, I did a fix to ensure that init hooks are called once and only once, even if one of them throws, or if one of them is triggering a new change detection process. Not sure it helps for this issue.

    About the ngOnInit's exception being swallowed, @wKoza is correct. @jelbourn already triggered an initiative to review the usage of finally in Ivy, that's a good case.

  10. naveedahmed1 commented on Mar 16, 2019

    @naveedahmed1
    Contributor

    While compiling my app with IVY I'm receiving this error ERROR in @ViewChild options must be an object literal.

  11. added
    area: coreIssues related to the framework runtime
    and removed on Apr 2, 2019
  12. modified the milestones: needsTriage, Backlog on Apr 18, 2019
  13. omairaslam817 commented on Oct 10, 2019

    @omairaslam817

    using ChangeDetectorRef Service in Constructor ,we can access the Viewchild refrence element in view Template,

    Constructor(private ref : ChangeDetectorRef){
    }
    //call detectChanges function before where to ViewChild  element Native Element attribute
    
    this.ref.detectChanges();
    
  14. pkozlowski-opensource commented on Feb 8, 2020

    @pkozlowski-opensource
    Member

    I believe that the original issue is fixed in v9. This ticket starts to accumulate several unrelated comments so it is hard to see what still needs attention.

    If there are still outstanding problems in v9, please open a new issue with a minimal reproduce scenario. Thnx!

  15. angular-automatic-lock-bot commented on Mar 10, 2020

    @angular-automatic-lock-bot

    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.

  16. locked and limited conversation to collaborators on Mar 10, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: coreIssues related to the framework runtimefreq1: lowneeds reproductionThis issue needs a reproduction in order for the team to investigate furthertype: bug/fix

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions