node-projects / dock-spawn-ts

A TypeScript HTML Docking Framework (fork of dock-spawn)
MIT License
123 stars 27 forks source link

Not Compatible with Angular 17.x #86

Closed dinobot71 closed 4 months ago

dinobot71 commented 4 months ago

Hi, we recently had to upgrade to Angular 17 from 15, and at the same time I thought it would be a good idea to update our Dock Spawn. But the latest Dock Spawn doesn't work properly with Angular any more. When you "dockLeft()" on a panel; like "solution_window", it inserts it into the top level container for dialogs (i.e. ) instead of putting it under its panel-content-wrapper div, inside the dock window.

This creates all kinds of problems, because the dock spawn div is inside an angular component, so when the panel is left dangling out in the body; when Angular routing happens, and ONLY the content of the anuglar component changes...that orphaned panel is still there. Plus, CSS stuff gets messed up, because the panel expects to be a child of the component, not of <body>.

Screenshot 2024-03-06 130709

I'm attaching a screen shot so you can see. If you look at the bottom, you can see that "solution_window"; which I did a "dockLeft()" on, has been left dangling out in <body> level with its container panel-element-content-container. What should have happened during doickLeft() is that panel-element-content-container should have been reparented under panel-content-wrapper...but it wasn't :(

I'm trying now to single step through the code and understand what is wrong, but it looks like I may have to go back to an older version.

The legacy version we were using: 2.60.0 (was working fine)

The version I'm trying to use now: 2.535.2 (does not work with Angular 17.x)

There are now exceptions or errors reported in the web console, Dock Spawn just doesn't re-parent the panel properly.

The HTML template for the angular component involved:

<div id="dock_div" >

  <div id="my_dock_manager" class="my-dock-manager" style="position: relative;">
  </div>

  <div id="solution_window"
       class="solution-window window-panel"
       hidden>
    <div id="projecttree" style="overflow: hidden;"></div>
  </div>

inside the angular component:

    ...
    ...
    const divDockContainer: JQuery<HTMLElement>   = $('#dock_div');
    const divDockManager: JQuery<HTMLElement>     = $('#my_dock_manager');

    const config: DockConfig = new DockConfig();
    config.moveOnlyWithinDockConatiner = true;

    this.dockManager   = new DockManager(divDockManager.get(0), config);

    // @ts-ignore
    window.dockManager = this.dockManager;

    this.dockManager.initialize();

    /* Let the dock manager element fill in the entire screen */

    window.onresize = (): void => {
      ...
    };
    window.onresize(null);

    /* create the project view */

    this._projectView    = new ProjectWindow('#solution_window', this.dockManager, this.services.ide, this.services.modals);

    const documentNode: DockNode = this.dockManager.context.model.documentManagerNode;

    this.dockManager.dockLeft(documentNode,  this._projectView.panel(),    0.20);
    ...
    ...

As far as I know this follows exactly what the demo does. So I don't see why its not working.

I will try to step through the dock spawn code line by line though and see if I can figure something out.

dinobot71 commented 4 months ago

Attaching an image that shows the problems with the Dock Spawn panels being outside of the angular component.

dock-spawn-dangling-panel

It happens because on routing, Angular only changes what is inside the ng-component.

I could likely add some extra code to try and do closure of panels before routing changes, but that creates other problems; what if you route to a different page, then come back? You expect to come back to what was there when you left...not...everything closed.

Really, this needs to be fixed. Panels should be children of their Dock Spawn host containers.

jogibear9988 commented 4 months ago

We've changed this in purpose, cause the containers were removed and added back to the dom when switching containers. Now we only change the size and leave them always in the dom.

So this will not be changed back, but maybe we could find another solution. Would it help if you could specify wich container is used for the elements? If so, you could try to set dialogRootElement of the config you hand over to the dockspawn constructor.

jogibear9988 commented 4 months ago

I think, due that change we used dialogRootElement for everything, but I'm not sure...

dinobot71 commented 4 months ago

Yes, I thought of trying that...I'll that in a few minutes, I'm a little concerned that this "floating" approach may have other impacts...but if the only issue is router related, then maybe its enough to just keep stuff within the component.

jogibear9988 commented 4 months ago

We've had huge views, and this change drastically increased performance. And also some components did not work correctly if removed and readded to dom

jogibear9988 commented 4 months ago

Yes, I thought of trying that...I'll that in a few minutes, I'm a little concerned that this "floating" approach may have other impacts...but if the only issue is router related, then maybe its enough to just keep stuff within the component.

Yeah if we still need to fix something, we can look for it. Maybe you can create a small angular sample where I could test? I've never used angular

dinobot71 commented 4 months ago

totally get it, and I can see how it would help for dialogs. Way back when (2 years?) I did offer to help with a proper angular example...I still owe you that :) I will find a way to make it happen. If you haven't already - can you add a "contributing" doc somewhere so I can go follow whatever your project's steps are for that?

dinobot71 commented 4 months ago

This seems to work fine :)

    let root: HTMLElement|null          = $(divDockContainer).parent(`ng-component`).get(0) ?? null;
    const config: DockConfig            = new DockConfig();
    config.moveOnlyWithinDockConatiner  = true;
    config.dialogRootElement            = root;

No more weirdness after that. To properly "embed" inside a generalized Angular component, it wouldn't be quite like this.

Let me give it some thought, I'm very sure its possible to come up with a standardized Angular wrapper. The tricky part is the recursion; "hosting" angular components inside PanelContainer...but I've already done it, its just that my implementation isn't entirely clean. I think there are better ways to do it.

Imediate issue is resolved. I'll open a separate issue for creating an Angular example (which I'll contribute to).

jogibear9988 commented 4 months ago

Maybe you could also use the wemcomponent, it keeps everything inside

dinobot71 commented 4 months ago

Hmm, yes I did notice that web component folder. Let me check it out...

jogibear9988 commented 4 months ago

there is also a example, and also my designer uses it: https://node-projects.github.io/web-component-designer-demo/index.html

jogibear9988 commented 4 months ago

p.s. on your homepage the link to webdevelopment does not work