BasicCustomizationControlsPluginAngularContext menuMinimapReroute
This plugin offers a classic preset that comes with visual components for nodes, connections, sockets, and input controls.
Compatible with Angular 12, 13, 14, 15, 16, 17 and 18
This plugin is exclusively designed for Angular applications as it requires Injector
instance, unlike other render plugins.
npm i rete-angular-plugin rete-render-utils @angular/elements@18
Please note: this plugin relies on @angular/elements
, which is based on Web Components. However, Web Components have a limitation - they cannot be unregistered. This limitation may result in the reuse of the initial Angular component instead of creating a new one when a node with the same identifier is added, potentially leading to the use of outdated data within a custom node, such as data from an injected service.
This is an example of integration in Angular 18, but you can specify a different version (12, 13, 14, 15, 16, 17 or 18) in the import that matches the version of your application.
These versions have been compiled with Ivy.
import { AreaPlugin } from "rete-area-plugin";
import { AngularPlugin, Presets, AngularArea2D } from "rete-angular-plugin/18";
type AreaExtra = AngularArea2D<Schemes>;
// ....
const render = new AngularPlugin<Schemes, AreaExtra>({ injector });
render.addPreset(Presets.classic.setup());
area.use(render);
where injector
is an instance of Injector
that can be obtained through dependency injection (DI).
Additionally, the plugin provides support for the legacy engine which can be imported in the following way
import { AngularPlugin, Presets, AngularArea2D } from "rete-angular-plugin";
This plugin provides built-in controls that are displayed based on the following objects:
ClassicPreset.InputControl
as <input type="number" />
or <input type="text" />
Simply add the control to the node
node.addControl('my-control', new ClassicPreset.InputControl("number", {
initial: 0,
readonly: false,
change(value) { }
}))
If you want to add different types of controls, you can return the necessary component in the control
handler of customize
property.
import { ControlComponent } from "rete-angular-plugin/18";
import { MyButtonComponent } from './my-button.component'
render.addPreset(Presets.classic.setup({
customize: {
control(context) {
if (context.payload.isButton) {
return MyButtonComponent
}
if (context.payload instanceof ClassicPreset.InputControl) { // don't forget to explicitly specify the built-in ControlComponent
return ControlComponent
}
}
}
}));
node.addControl('my-button', { isButton: true, label: 'Click', onClick() {} })
import { Component, Input } from "@angular/core";
@Component({
selector: "app-button",
template: `<button
(pointerdown)="$event.stopPropagation()"
(click)="data.onClick()"
>
{{ data.label }}
</button>`
})
export class ButtonComponent {
@Input() data!: { label: string, onClick: () => void };
}
This is a simplified version suitable for introductory purposes. For projects, it is recommended to follow the approach demonstrated in the example
Make sure to specify (pointerdown)="$event.stopPropagation()"
to prevent the area from intercepting events such as click
.
In a similar manner to the approach outlined above, you can replace node, connection, or socket components.
If you want to completely change the node structure, you can implement your own component similar to node from the classic preset
import { CustomNodeComponent } from './custom-node.component'
render.addPreset(Presets.classic.setup({
customize: {
node() {
return CustomNodeComponent
}
}
}))
The implementation of CustomNodeComponent
is available in the custom-node.component.ts file of the Customization for Angular example.
You can add an extra condition to apply this component only to specific nodes.
import { NodeComponent } from "rete-angular-plugin/18";
render.addPreset(Presets.classic.setup({
customize: {
node(context) {
if (context.payload.label === "Custom") {
return CustomNodeComponent;
}
return NodeComponent; // use built-in component
}
}
}))
await editor.addNode(new ClassicPreset.Node('White'))
Use connection as a starting point from the presets/classic/components directory of the plugin's source code.
import { CustomConnectionComponent } from './custom-connection.component'
render.addPreset(Presets.classic.setup({
customize: {
connection() {
return CustomConnectionComponent
}
}
}))
Use socket as a starting point from the presets/classic/components directory of the plugin's source code.
import { CustomSocketComponent } from './custom-socket.component'
render.addPreset(Presets.classic.setup({
customize: {
socket() {
return CustomSocketComponent
}
}
}))
In order to customize the context menu for this rendering plugin, one can override styles using selectors (and it's important to consider the specificity of selectors in CSS)
[rete-context-menu] {
width: 320px;
context-menu-search input.search {
background: grey;
}
context-menu-item.block {
background: grey;
}
}
Check out the complete result on the Customization for Angular example page.