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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

ng-template not working in angular 9 with IVY #36238

Closed
kumaresan-subramani opened this issue Mar 25, 2020 · 10 comments
Closed

ng-template not working in angular 9 with IVY #36238

kumaresan-subramani opened this issue Mar 25, 2020 · 10 comments

Comments

@kumaresan-subramani
Copy link

@kumaresan-subramani kumaresan-subramani commented Mar 25, 2020

馃悶 bug report

ng-template is not working properly in angular 9 but working fine in angular 8

Is this a regression?

yes, working fine in angular 8

Description

I have created same application in both angular 8 and angular 9, my application working fine in angular 8.

馃敩 Minimal Reproduction

Working sample

  1. download below angular 8 sample
    angular8.zip

  2. Give "npm i" and "ng serve"

3.then chose any one row from grid and click "edit" button, you wiill see below

image

my template working fine.

issue sample

  1. download below angular 9 sample

angular 9.zip

  1. Give "npm i" and "ng serve"

3.then below screen occurs , then chose any one row from grid and click "edit" button, you wiill see below

image

Code snippet

<ejs-grid [dataSource]='data' allowPaging='true' [pageSettings]='pageSettings' [editSettings]='editSettings' [toolbar]='toolbar' (actionBegin)='actionBegin($event)' (actionComplete)='actionComplete($event)'>
      <e-columns>
          <e-column field='OrderID' headerText='Order ID' width='120' textAlign='Right' [isPrimaryKey]='true'></e-column>
          <e-column field='CustomerName' headerText='Customer Name' width='120'></e-column>
          <e-column field='Freight' headerText='Freight' width='120' format='C2' textAlign='Right'></e-column>
          <e-column field='OrderDate' headerText='Order Date' width='130' format='yMd' textAlign='Right'></e-column>
          <e-column field='ShipCountry' headerText='Ship Country' width='150'></e-column>
      </e-columns>
      <ng-template #editSettingsTemplate let-data>
          <div ngForm #orderForm="ngForm">
              <table class="e-table e-inline-edit" cellspacing="0.25">
                  <colgroup>`
                          <col style="width: 120px;">
                          <col style="width: 120px;">
                          <col style="width: 120px;">
                          <col style="width: 130px;">
                          <col style="width: 150px;">
                  </colgroup>
                  <tbody>
                      <tr>
                          <td style="text-align: right" class='e-rowcell'>
                              <div class="e-input-group" [ngClass]= "{'e-disabled': !data.isAdd}">
                                  <input class="e-input e-field" [(ngModel)]="orderData.OrderID" required [attr.disabled]="!data.isAdd ? '' : null" name='OrderID' type="text" (focus)="focusIn($event.target)"
                                      (blur)="focusOut($event.target)" #OrderID style="text-align: right"  />
                              </div>
                          </td>
                          <td class='e-rowcell'>
                              <div class="e-input-group">
                                  <input class="e-input e-field" name='CustomerName' [(ngModel)]="orderData.CustomerName" required type="text" (focus)="focusIn($event.target)"
                                      (blur)="focusOut($event.target)" #CustomerName />
                              </div>
                          </td>
                          <td style="text-align: right" class='e-rowcell'>
                              <ejs-numerictextbox name="Freight" id="Freight" [(ngModel)]="orderData.Freight" floatLabelType='Never'></ejs-numerictextbox>
                          </td>
                          <td style="text-align: right" class='e-rowcell'>
                              <ejs-datepicker id="OrderDate" name="OrderDate" required [(ngModel)]="orderData.OrderDate" floatLabelType='Never'></ejs-datepicker>                            
                          </td>
                          <td class='e-rowcell'>
                              <ejs-dropdownlist id="ShipCountry" name="ShipCountry" [(ngModel)]="orderData.ShipCountry" [dataSource]='shipCountryDistinctData' [fields]="{text: 'ShipCountry', value: 'ShipCountry' }" popupHeight='300px' floatLabelType='Never'></ejs-dropdownlist>
                          </td>
                      </tr>
                  </tbody>
              </table>
          </div>
      </ng-template>
  </ejs-grid>

馃實 Your Environment

Angular Version:


"@angular/animations": "~9.0.2",
    "@angular/common": "~9.0.2",
    "@angular/compiler": "~9.0.2",
    "@angular/core": "~9.0.2",
    "@angular/forms": "~9.0.2",
    "@angular/platform-browser": "~9.0.2",
    "@angular/platform-browser-dynamic": "~9.0.2",
    "@angular/router": "~9.0.2",
"@angular-devkit/build-angular": "~0.900.3",
    "@angular/cli": "~9.0.3",
    "@angular/compiler-cli": "~9.0.2",
    "@angular/language-service": "~9.0.2",

Anything else relevant?
Both angular 8 and angular 9, my template reference are same in my soure level"ngAfterContnctChecked" hook.

angular 8 reference:

image

angular 9 reference:

image

@JoostK

This comment has been minimized.

Copy link
Member

@JoostK JoostK commented Mar 25, 2020

In the Angular 8 screenshot, the ngAfterContentChecked is called with a ComponentBase instance as first parameter. This is not part of the signature of this method according to the AfterContentChecked interface, and it's not provided as such by Angular itself. I suspect that your decorators inject custom behaviour into how hooks are called, which had to be reworked because of #31495 which has broken this setup. The stack trace is missing in the Angular 8 screenshot so I can't know for sure, but there's likely an additional stack frame in the Angular 8 case.

@kumaresan-subramani

This comment has been minimized.

Copy link
Author

@kumaresan-subramani kumaresan-subramani commented Mar 25, 2020

HI @JoostK ,

We have used custom decarators to over-ride my angular componet hooks, it works tll anglar 9.

but in anglar 9 with IVY, it does not work due to this issue so that we have created new instance of my class which has all life cycle hook functionalities like below:

https://github.com/syncfusion/ej2-angular-ui-components/blob/master/components/grids/src/grid/grid.component.ts#L233

ans then i have passed current instace to newly created class instance which has all lie cycle hook functionalities like below

https://github.com/syncfusion/ej2-angular-ui-components/blob/master/components/grids/src/grid/grid.component.ts#L237

My issue is ng-template compilation not working fine in angular 9 but template reference are same i both angular 8 and 9

working fine in angular 8

not working in angular 9

@kumaresan-subramani

This comment was marked as off-topic.

Copy link
Author

@kumaresan-subramani kumaresan-subramani commented Mar 25, 2020

Finally i have validated and partially assumed issue is in node_modules@angular\core_ivy_ngcc_\fesm2015\core.js packages

when it comes to tickRootContext method, it has my template reference

image

and then it goes to renderComponentOrTemplate method, in here template function goes null

image

From renderComponentOrTemplate method it goes to refreshView method, in here component reference occurs in 19th index as like below image:
image

then i navigate to 19th component reference in there template not get compiled it shows undefined as like below image
image

So that i partially conclude there is some error in angular 9 ivy template compilation, Can you please provide any update on this.

But when it comes to my base hook, both [angular 8 and angular 9 ] has template reference but i think, template not get compiled

image

But for in angular 8, total architecture is different and working fine

@kumaresan-subramani

This comment has been minimized.

Copy link
Author

@kumaresan-subramani kumaresan-subramani commented Mar 26, 2020

HI @JoostK ,

I think, i found root cause, which is when i select anyone row and then click edit button, it triggers my component's [which is placed inside ng-template] life cycle hook in angular 8 so that component which has been placed inside ng-template grt rendered properly. refer below images:

row selection

image

click edit button

after clicking edit button, it triggers my life cycle hook from "callProviderLifecycles" angular method, from my lifecycle hook i called append method and there i append my component which has been placed inside ng-template has been get rendered properly.

image

my component inside ng-template rendering

image

in angular9, when i click edit button it doesn't trigger my life cycle hooks properly. so that ng-template not working

@alxhub

This comment has been minimized.

Copy link
Contributor

@alxhub alxhub commented Mar 27, 2020

One of the Ivy compatibility "changes you may see" on https://angular.io/guide/ivy-compatibility is:

It's no longer possible to overwrite lifecycle hooks with mocks on directive instances for testing (instead, modify the lifecycle hook on the directive type itself).

This is a performance optimization - reading a function from an arbitrary component is expensive, and so Angular only does it once from the component's prototype.

Unfortunately you'll need to rework your decorator logic to not rely on arbitrary overwriting of lifecycle hooks.

@alxhub alxhub closed this Mar 27, 2020
@kumaresan-subramani

This comment was marked as outdated.

Copy link
Author

@kumaresan-subramani kumaresan-subramani commented Mar 27, 2020

Hi,

If over-riding angular hook is not possible in ivy,how below works

#36238 (comment)

I have over-rided angular hooks here also.

@kumaresan-subramani

This comment has been minimized.

Copy link
Author

@kumaresan-subramani kumaresan-subramani commented Mar 30, 2020

HI @alxhub ,

I think you misunderstood my problem.

i found root cause, which is when i select anyone row and then click edit button, it triggers my component's [which is placed inside ng-template] life cycle hook in angular 8 so that component which has been placed inside ng-template get rendered properly

But in angular9, when i click edit button it doesn't trigger my life cycle hooks properly. so that ng-template not working

when i click "edit" button,
image

it triggers, my life cycle hook from angular core level like below image

image

@Achilles1515

This comment has been minimized.

Copy link

@Achilles1515 Achilles1515 commented Mar 31, 2020

It's no longer possible to overwrite lifecycle hooks with mocks on directive instances for testing (instead, modify the lifecycle hook on the directive type itself).

@alxhub But this will be changing "soon"...right?
#35464

@bryanrideshark

This comment has been minimized.

Copy link

@bryanrideshark bryanrideshark commented Mar 31, 2020

@alxhub , we're going to be merging #35464 and making it possible to override the prototype before startup right? It'll still be pretty efficient AFAIK, because the read will be cached once the first component of that type has been instantiated.

I think a lot of more advanced users of Angular are waiting with eager expectation for #35464 to be merged.

@alxhub

This comment has been minimized.

Copy link
Contributor

@alxhub alxhub commented Mar 31, 2020

@bryanrideshark that'd be a better question for @kara, I don't work on the core specifically. But that approach looks sound to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants
You can鈥檛 perform that action at this time.