-
-
Notifications
You must be signed in to change notification settings - Fork 18
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
Table layout #146
base: master
Are you sure you want to change the base?
Table layout #146
Conversation
by directly creating embedded view from component's template.
Remove intermediate <div ui-scroll> wrapping tag for ui-scroll component
# Conflicts: # src/component/processes/render.ts # src/ui-scroll.component.ts # src/ui-scroll.directive.ts
src/ui-scroll.component.ts
Outdated
constructor( | ||
public changeDetector: ChangeDetectorRef, | ||
public elementRef: ElementRef) { } | ||
public elementRef: ElementRef | ||
) { | ||
setTimeout(() => this.ngOnInit()); // 😢 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@markdBC To say I don't like this would be a considerable understatement... ngOnInit must be invoked implicitly, and I have no idea why it became broken. It has something to do with new approach of creating the component on the directive level. The demo we developed on stackblitz has the same issue.
It would be very nice if you could take a look and help with it. For testing in ngx-ui-scroll environment you may use http://localhost:4200/#/test (after npm start), which runs demo/app/samples/test.component.html template. There are multiple issues behind this one, so to see the result is still impossible, but the initialization could be handeled in a proper way
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dhilt The problem is that ngOnInit
is called after the first time ngOnChanges
is called (https://angular.io/guide/lifecycle-hooks#lifecycle-sequence).
However, while ViewContainerRef.createComponent
causes an invocation of ngOnChanges
, the same is not true for ComponentRef.create
.
You can find the definition of ViewContainerRef.createComponent
, at packages/core/src/view/refs.ts:180
of the Angular source code:
createComponent<C>(
componentFactory: ComponentFactory<C>, index?: number, injector?: Injector,
projectableNodes?: any[][], ngModuleRef?: NgModuleRef<any>): ComponentRef<C> {
const contextInjector = injector || this.parentInjector;
if (!ngModuleRef && !(componentFactory instanceof ComponentFactoryBoundToModule)) {
ngModuleRef = contextInjector.get(NgModuleRef);
}
const componentRef =
componentFactory.create(contextInjector, projectableNodes, undefined, ngModuleRef);
this.insert(componentRef.hostView, index);
return componentRef;
}
ViewContainerRef.createComponent
calls the ComponentRef.create
method, and then calls ViewContainerRef.insert
, which among other things causes change detection to occur inside the component.
A solution is to explicitly invoke change detection for the component, via ComponentRef.changeDetectorRef.detectChanges()
. This is probably only slightly better than explicitly invoking ngOnInit
, but at least we're not calling a lifecycle hook directly.
I've made a PR with this change at #147 and have a StackBlitz demo at https://stackblitz.com/edit/table-implicit-lifecycle-hook-invocation.
…nt and inputting values.
Explicitly invoke change detection after component creation
componentRef.instance.version = version; | ||
componentRef.instance.parentElement = this.templateRef.elementRef.nativeElement.parentElement; | ||
this.viewContainer.createEmbeddedView(componentRef.instance.uiScrollTemplateRef); | ||
setTimeout(() => componentRef.changeDetectorRef.detectChanges()); // 😢 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@markdBC I admire your deep insight of the Angular internal things and very grateful for your explanation regarding ngOnInit. As you can see I had to wrap changes detection into another setTimeout
, the problem is that the onInit
hook is being triggered (with manual approach) before the initial content of the component is rendered. Do you know, what can be done here? I tried to replace OnInit
with AfterViewInit
(the latest init hook), but it also runs too early.
The initialization, I need to run on the components first render, includes DOM parsing, in particular, the Scroller tries to find elements needed for virtualization. And immediate initialization (before DOM gets necessary elements during first render) just fails.
Also, calling componentRef.changeDetectorRef.detectChanges()
seems equal to calling componentRef.instance.ngOnInit()
, but I agree this is better than calling this.ngOnInit()
on the component's constructor.
That's what we have now... And it would be great to dig a little dipper and find a way to catch the time of the first render properly. The last thing I want to add is that the demo starts working, not perfect, but something can be seen running localhost:4200/#/test
# Conflicts: # src/component/classes/viewport.ts # src/component/processes/render.ts # src/ui-scroll.component.ts # src/ui-scroll.directive.ts
Based on issue #40