Foblex / f-flow

Foblex Flow - is an Angular library designed to simplify the creation and manipulation of dynamic flow. Provides components for flows, nodes, and connections, automating node manipulation and inter-node connections.
https://flow.foblex.com/
MIT License
96 stars 19 forks source link

Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node. #67

Closed JamesMolina007 closed 4 weeks ago

JamesMolina007 commented 4 weeks ago

Description

I'm trying to create a multi-select element that also has upper and lower connections. The template looks like this:

@for(node of nodes; track node.id){
                      <div fNode fDragHandle [fNodePosition]="{ x: node.x, y: node.y }"
                        (fNodePositionChange)="onNodeDragEnd($event, node)"
                        [ngClass]="getNodeClasses(node)" (click)="selectNode(node)"
                        [style.height]="node.height" [style.width]="node.width" 
                        [attr.data-node-id]="node.id">
                        <div fResizeHandle (mouseup)="endResize(node)" [fResizeHandleType]="eResizeHandleType.LEFT_TOP"></div>
                        <div fResizeHandle (mouseup)="endResize(node)" [fResizeHandleType]="eResizeHandleType.RIGHT_TOP"></div>
                        <div fResizeHandle (mouseup)="endResize(node)" [fResizeHandleType]="eResizeHandleType.LEFT_BOTTOM"></div>
                        <div fResizeHandle (mouseup)="endResize(node)" [fResizeHandleType]="eResizeHandleType.RIGHT_BOTTOM"></div>
                        <div class="node-content">
                          <textarea *ngIf="node.elementType !== ElementTypes.SquareMultiOptions" 
                                  [(ngModel)]="node.text" 
                                  (blur)="disableEditing(node)" 
                                  [readonly]="!node.isEditing" 
                                  (dblclick)="enableEditing(node)" 
                                  autofocus
                                  class="dynamic-textarea">
                          </textarea>
                          <div *ngIf="node.elementType === ElementTypes.SquareMultiOptions">
                            <div class="multi-option-header">
                              <textarea 
                                  [(ngModel)]="node.text" 
                                  (blur)="disableEditing(node)" 
                                  [readonly]="!node.isEditing" 
                                  (dblclick)="enableEditing(node)" 
                                  autofocus
                                  class="dynamic-textarea">
                              </textarea>
                              <button class="multi-option-plus" (click)="addOptionToMultiOption(node)">
                                <i data-feather="plus" class="icon-plus"></i>
                              </button>
                            </div>
                            <div *ngIf="node.options" class="multi-option-options">
                                <div *ngFor="let option of node.options; let i = index" 
                                     fNode 
                                     [fNodePosition]="{ x: 0, y: (30 + i*35)}" >
                                  <div class="option-content">
                                    <input [(ngModel)]="option.text" class="input-option"/>
                                  </div>
                                  @for(IO of option.fOutput; track IO.id){
                                    <div fNodeOutput [fOutputId]="IO.id" [fOutputMultiple]="true" [ngClass]="IO.side"></div>
                                  }
                                  @for(IO of option.fInput; track IO.id){
                                    <div fNodeInput [fInputId]="IO.id" [fInputMultiple]="true" [ngClass]="IO.side"></div>
                                  }
                                </div>
                            </div>
                          </div>
                        </div>
                        @for(IO of node.fOutput; track IO.id){
                          <div fNodeOutput [fOutputId]="IO.id" [fOutputMultiple]="true" [ngClass]="IO.side"></div>
                        }
                        @for(IO of node.fInput; track IO.id){
                          <div fNodeInput [fInputId]="IO.id" [fInputMultiple]="true" [ngClass]="IO.side"></div>
                        }
                      </div>
                    }

I add it to my list of nodes like this. Captura de pantalla 2024-10-24 203700

The thing is, I only receive this exception when node.elementType === ElementTypes.SquareMultiOptions and try to add one node inside image image

Steps to Reproduce

Creating a component which has its own connections and inside has nodes with their own connections

Expected Result

No Exception

Actual Result

chunk-DERR6ZUE.js?v=99b808c1:81 ERROR NotFoundError: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node. at SortItemsByParentExecution2.moveChildrenItems (foblex-flow.mjs:9054:26) at foblex-flow.mjs:9034:12 at Array.forEach () at SortItemsByParentExecution2.handle (foblex-flow.mjs:9033:21) at Pipeline.handle (foblex-mediator.js:12:41) at _FMediator.send (foblex-mediator.js:33:23) at SortItemLayersExecution2.handle (foblex-flow.mjs:9091:20) at Pipeline.handle (foblex-mediator.js:12:41) at _FMediator.send (foblex-mediator.js:33:23) at Object.next (foblex-flow.mjs:10451:22)

Environment Details

Angular 18.0.7 Foblex Flow latest version

Screenshots or Videos

No response

Additional Context

No response

siarheihuzarevich commented 4 weeks ago

Hello. Your error occurs because you placed a node inside another node.

siarheihuzarevich commented 4 weeks ago

Also, I don't understand why you need a mouseup event on an element with the fResizeHandle attribute, you can see how to resize a node in our examples.

There is an event for resize in the nodeimage

JamesMolina007 commented 4 weeks ago

Okay the information about sizeChange really helpful thank you. I was reading the doc, saw the examples but I didnt find it so thats why I created that mouseEvent And, so Can´t I have nodes inside nodes? Basically Im trying to do a multi options component. But it needs to have its own connections because is a part of a support flow

siarheihuzarevich commented 4 weeks ago

the examples have all of this, both about resizing and about how to make child and parent nodes

JamesMolina007 commented 3 weeks ago

sorry but I havent found an example or in the documentation something that explains about resizing and an example of Node and Parent Nodes.

JamesMolina007 commented 3 weeks ago

This is my current component, it works but I would like to avoid that exception image

siarheihuzarevich commented 3 weeks ago

https://flow.foblex.com/examples/grouping/

JamesMolina007 commented 3 weeks ago

okay, understood. With grouping.