Skip to main content

Sub-DAG (Node Group)

Sub DAG means a node render can be a DAG view which is generated by Nice-DAG as well. Here is to give a sample which can explain how to generate a sub DAG. To simply the illustratation, the example extends Read-Only DAG.

Step 1: Adapt Node List

Sub-DAG can be regarded as a group of nodes. Before the render adaption, you need to know how a data structure can be represented a node group. There are two ways to define a node group. modelType of useNiceDag is used to indicated which structure should be used.

Hierarchical Structure

const NodeData = [
{
id: "start",
},
{
id: "task",
dependencies: ["start"],
children: [
//children is an array of nodes which can represent a node group
{
id: "sub-task-1",
},
{
id: "sub-task-2",
dependencies: ["sub-task-1"],
},
],
},
{
id: "end",
dependencies: ["task"],
},
];

In this example, the task is a node which contains a sub DAG view because the node has a children definition with an array.

If you use the hierarchical structure, you don't need any change of useNiceDag parameters because modelType is HIERARCHY in default.

Flatten Structure

const NodeData = [
{
id: "start",
},
{
id: "task",
dependencies: ["start"],
},
{
id: "sub-task1",
parentId: "task",
},
{
id: "sub-task2",
parentId: "task",
dependencies: ["sub-task1"],
},
{
id: "end",
dependencies: ["task"],
},
];

In this example, the task is a node which contains a sub DAG view. The difference between flatten structure and hierarchical structure is that the flatten one uses parentId to grouping nodes. In this sample, sub-task1 and sub-task2 have the same parentId task so that they are in the same group.

Notes: Whether to use hierarchical structure or flatten structure, the node id MUST be unique. This is due to the NiceDagNodes is unaware of the node layers. It is called by a Teleport component which is associated to a DOM node by the unique id.

If you use the flatten structure, you don't need any change of useNiceDag parameters but set modelType to FLATTEN.

<script>
export default() {
setup() {
//call useNiceDag
const { niceDagEl, niceDagReactive } = useNiceDag(
{
initNodes: NodeData,
modelType: 'FLATTEN'
},
false
);
return {
niceDagEl,
niceDagReactive,
};
},

...
}
</script>

Step 2: Adapt the node render

The size of a node group isn't controlled by getNodeSize because it is determined by the content (children) of the node. Usually, you can call useNiceDag with a parameter subViewPadding object for a node group

Nice-DAG gives a default sub DAG padding object.

{
top: 40,
bottom: 20,
left: 20,
right: 20,
}

For this example, we can leave the default value. Once the node group has the paddings, you can leverage the padding to add some DOM nodes (e.g. button, <a/>) to control the group.

const GroupControl = {
props: ["node", "niceDag"],
emits: ["update:node", "update:niceDag"],
components: [ShrinkSvg, MyButton],
render() {
return (
<div className="my-first-dag-node-group-content">
<div>
{this.node.data?.label || this.node.id}
<button onClick={() => this.node.shrink()}>-</button>
</div>
</div>
);
},
};

const NodeControl = {
props: ["node", "niceDag"],
emits: ["update:node", "update:niceDag"],
render() {
return (
<div className="readonly-sample-node-content">
<span>{this.node.data?.label || this.node.id}</span>
{this.node.children?.length > 0 && (
<button onClick={()=>this.node.expand()}>-<button>
)}
</div>
);
},
};

export const SampleNode = {
props: ["node","niceDagReactive"],
emits: ["update:node","update:niceDagReactive"],
render() {
return (
<div className="my-first-dag-node">
{this.node.children?.length > 0 && !this.node.collapse ? (
<GroupControl node={this.node} niceDag={niceDagReactive.use()} />
) : (
<NodeControl node={this.node} niceDag={niceDagReactive.use()} />
)}
</div>
);
},
};

Notes Whether to use hierarchical structure of flatten structure, it should use children to indicate if it is a node group. This is due to Node objects is converted or IViewNode objects once it sets to the useNiceDag.