Proposal: Refactor overlay
See original GitHub issue@jelbourn While trying to use Overlay as the underlaying container for my angular2-modal component I found myself playing with the structure a bit to get better WebWorker support, less DOM interaction and more flexibility (custom classes, pane, container).
This is a bit long, I wanted to make sure I’m clear.
I ended up with a nice solid design for the overlay that reduces DOM interaction to almost nothing. This design will also work in native script, for example…
I didn’t post PR since it pointless, so I put up a proposal, you can review my branch to get an idea.
Bug, feature request, or proposal: feature
What is the expected behavior?
Reduce DOM interaction, support WebWorker and make the overlay container and pane more “angularish”
What is the current behavior?
Overlay service is using the DOM to manually insert both overlay container
and overlay pane
s
This in turn “forces” all implementations PositionStrategy
to use direct DOM access.
What is the use-case or motivation for changing an existing behavior?
Support universal, reduce DOM access, use one position strategy for all platforms (layout will apply using bindings), support declarative overlay component. Use angular component’s for the overlay container and for panes… In short the angular way.
Is there anything else we should know?
Basic design:
The Overlay
service should be platform agnostic. The overlay-container and overlay-pane children are both angular components.
The generic Overlay
service expects an overlay-container to be declared in a template (1 only, inside app root template). This means an OverlayContainer
component is used, which publish it’s creation/destruction to the Overlay
service.
The ContainerComponent
is in charge of adding panes to itself which reduce the complexity of the Overlay
service, aligns with SRP and also with angular since only components should add child components to their tree (manually), since only they have access to the ViewContainerRef
, i.e: AppElement
.
This can be done using a CompoenentFactory
or by letting angular do the work via *ngFor
of plain Pane objects (more complex since addPane() need to return the pane element)
I used the manual approach in my branch.
Browser specific design:
In a browser, a DOMOverlay
service (extends Overlay
) is used (override via provider config).
The DOMOverlay
reflects the original behavior, which is - material needs to insert the overlay container manually into the DOM.
The DOMOverlay
apply 2 changes to the the base Overlay
service while not changing logic or flow, we still have the container and panes as angular Components.
Change 1: Hook to the request overlay-container process, add it to the DOM (appendChild), return control. From here Overlay
will take it, the OverlayContainer
component will identify our newly added element that matches it’s selector and create itself + let Overlay
know about it. There is a catch, see change 2.
Change 2: After creating a Pane, fire a change detection on the container tree to reflect ID and class (bindings). This is mandatory since our root overlay container is not connected, in any place, to the root host view (app root component). This results in it not being a part of change detection and life cycle hooks. This change will make sure to trigger change detection.
Here is a link to a commit with the implementation of the above, with all unit tests passing and demo updated to use DOMOverlay
Note1: Implementation in the link does not refactor the
PositionStrategy
implementations, if the proposal turns into a PR I will update allPositionStrategy
implementations to binding expression instead of direct DOM manipulation, this will eliminate allElement
usage within the overlay service, we will only deal withComponentRef
sNote2: this proposal doesn’t not care about
Portal
implementation, it assumes its platform agnostic as well.
Issue Analytics
- State:
- Created 7 years ago
- Reactions:2
- Comments:11 (9 by maintainers)
Top GitHub Comments
@jelbourn would you mind sharing more info about the solution you are working on? I guess we all feel like there is sth missing in the core to properly handle overly-like use-cases.
I’ve briefly discussed this with both @mhevery and @tbosch and opened https://github.com/angular/angular/issues/9293 as the result.
@shlomiassaf I’ve got a PR in the works on angular core that would let you get a
ViewContainerRef
without explicitly passing one.