excubo-ag / Blazor.Diagrams

https://excubo-ag.github.io/Blazor.Diagrams/
MIT License
136 stars 18 forks source link

NodeLibrary with Code generated Nodes #80

Closed Flow2606 closed 3 years ago

Flow2606 commented 3 years ago

Hi Stefan,

its me again and i have ran into another problem right now.

In my Project every Object of a Class represents a Node. Pretty much the same as you have done it in the Demo. Foreach Object in my List a Node is created.

Now i want to add a NodeLibrary to easily create an Object/Node from a template. The problem is that these template Nodes are not in my List and do not represent an Object. Its just a useless Node.

Maybe you know a solution on how to connect Code generated Nodes in a List with the NodeLibrary. Sorry for bothering you, i'm still a trainee.

Flow

stefanloerwald commented 3 years ago

HI @Flow2606,

I'm not sure I understand your requirements. Have you had a look at the example page for the node library? Can you share some code showing what you tried and what you expected it to do vs what you got?

Thanks Stefan

Flow2606 commented 3 years ago

Alright ill try to explain my Project a little bit. Its an ERD Designer which can later be translated into an actual Database. Here I have the Component DiagramBuilder which creates the Diagram itself and and has the Object DataBase as a Parameter. this Object contains Entities which are then generated as Nodes in the EntityBuilder.

DiagramBuilder

@using Excubo.Blazor.Diagrams

<div>
    <Diagram ShowGridLines="true">
        <OverviewSettings Position="Position.BottomLeft" />
        <NavigationSettings InversedZoom="true" />
        <NodeLibrary style="background-color: lightgray; border: 2px solid gray; height: 15%" Orientation="Orientation.Horizontal">
            @*Templates*@
        </NodeLibrary>
        <Nodes>
            <EntityBuilder DataBase="@DataBase" />
            <ReferenceBuilder DataBase="@DataBase" />
        </Nodes>
        <Links>
            <LinkBuilder DataBase="@DataBase" />
        </Links>
    </Diagram>
</div>

@code
{
    [Parameter]
    public DataBase DataBase { get; set; }
}

EntityBuilder

@foreach (Entity entity in DataBase.Entities)
{
    <CustomRectangleNode Id="@entity.Id.ToString()" @bind-X="entity.X" @bind-Y="entity.Y">
        <table>
            <tr>
                <th><center><h3>@entity.Name</h3></center></th>
            </tr>
            @if (entity.Attributes.Count > 0)
            {
                <tr>
                    <td>
                        <table class="table">
                            @foreach (ERM.Attribute attribute in entity.Attributes)
                            {
                                string name = attribute.Name;
                                string dataType = attribute.DataType.Type;
                                string args = GetArgumentsAsString(attribute);

                                <tr>
                                    <td>
                                        @if (IsPrimaryKey(attribute.Id, entity.PrimaryKey))
                                        {
                                            <Icons.PrimaryKey />
                                        }
                                        @if (IsForeignKey(DataBase, attribute))
                                        {
                                            <Icons.ForeignKey />
                                        }
                                    </td>
                                    <td>@name</td>
                                    <td>@dataType@args</td>
                                </tr>
                            }
                        </table>
                    </td>
                </tr>
            }
        </table>
    </CustomRectangleNode>
}

This allows to display the Object Entity as a Node. I dont have a user friendly way yet to create Entities on the front-end. So your NodeLibrary is pretty much perfect for this task. The problem is that the Node is not generated in the EntityBuilder and therefore I dont know how to manipulate the Node and store the new Entity in my DataBase Object. I have no code for the NodeLibrary Nodes as I have no idea how to approach this problem at all.

stefanloerwald commented 3 years ago

There is an OnAdd callback on the Nodes component, that you could use to be notified whenever an item is added from the Node library. What you put into the node library can be anything, e.g. just a CustomRectangleNode. But that introduces the inconvenience of now having a node that you'd ideally save into the DataBase.Entities, but if you do so, that will render a node, in addition to the node that you dragged onto the diagram.

So in your case, I'd suggest to take a different approach:

  1. Create your own overlay over the diagram.
  2. Put some UI component there for which you enable drag events (see https://docs.microsoft.com/en-us/aspnet/core/blazor/components/event-handling?view=aspnetcore-5.0)
  3. On the diagram, add the drop part of the drag event, and in the callback, add a new entity to your DB model programmatically.
  4. A new node should now be rendered in the diagram
Flow2606 commented 3 years ago

Alright thanks for the help. That definitely seems like a reasonable approach so I will try that out.

Flow2606 commented 3 years ago

Ok I'm back from the weekend and quite happy you left this Issue open. The Drag&Drop is easy to solve but there is one last problem. I can get the X/Y coordinates from the DragEventArgs but now i realized that theyre not accurate as soon as I move the Diagram in any direction. Is there any way to read out the current Mouse X and Y on the Diagram?

stefanloerwald commented 3 years ago

There's an extension method: https://github.com/excubo-ag/Blazor.Diagrams/blob/0081da732e1c5d5ac8d51bede42bb2f7b35bb1b7/Diagram/Extensions/MouseEventArgsExtension.cs#L8

So as soon as you include using Excubo.Blazor.Diagrams.Extensions, you should be able to perform e.RelativeToOrigin(diagram).

Flow2606 commented 3 years ago

Works perfectly. You ve been of great help. Thank you. My Issue is solved now.