# Angular

::alert
This guide is an extension of the [Basic](https://retejs.org/docs/guides/basic) guide and provides instructions for using the `rete-angular-plugin` instead of `rete-react-plugin`
::

::references
  :::ref-example{link="/examples/basic/angular" title="Basic"}
  :::

  :::ref-example{link="/examples/customization/angular" title="Customization"}
  :::

  :::ref-example{link="/examples/controls/angular" title="Controls"}
  :::

  :::ref-github{link="https://github.com/retejs/angular-plugin" title="Plugin"}
  :::

  :::ref-external{link="https://angular.io/" title="Angular"}
  :::

  :::ref-guide{link="/docs/guides/context-menu" title="Context menu"}
  :::

  :::ref-guide{link="/docs/guides/minimap" title="Minimap"}
  :::

  :::ref-guide{link="/docs/guides/reroute" title="Reroute"}
  :::
::

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, 18, 19, 20 and 21

This plugin is **exclusively** designed for Angular applications as it requires an `Injector` instance, unlike other render plugins. Additionally, the plugin supports Standalone mode in integration starting from Angular 19, with enhanced features in Angular 20 and 21.

## Install dependencies

::kit
::

```bash
npm i rete-angular-plugin rete-render-utils @angular/elements@21
```

**Please note**: this plugin relies on `@angular/elements`, which is based on Web Components. However, Web Components have a limitation - they [cannot be unregistered](https://github.com/WICG/webcomponents/issues/754){rel="nofollow"}. 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.

## Plugin connection

This is an example of integration in **Angular 21**, but you can specify a different version (12, 13, 14, 15, 16, 17, 18, 19, 20 or 21) in the import that matches the version of your application.

These versions have been compiled with Ivy.

```ts
import { AreaPlugin } from "rete-area-plugin";
import { AngularPlugin, Presets, AngularArea2D } from "rete-angular-plugin/21";

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).

## Use Legacy View Engine

Additionally, the plugin provides support for the legacy engine which can be imported in the following way

```ts
import { AngularPlugin, Presets, AngularArea2D } from "rete-angular-plugin";
```

## Controls

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

```ts
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.

```tsx
import { ControlComponent } from "rete-angular-plugin/21";
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() {} })
```

```ts
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](https://retejs.org/examples/controls/angular)

Make sure to specify `(pointerdown)="$event.stopPropagation()"` to prevent the area from intercepting events such as `click`.

## Customization

In a similar manner to the approach outlined above, you can replace node, connection, or socket components.

### Customization of all nodes

If you want to completely change the node structure, you can implement your own component similar to [node](https://github.com/retejs/angular-plugin/blob/next/src/presets/classic/components/node){rel="nofollow"} from the classic preset

```ts
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](https://retejs.org/examples/customization/angular) example.

### Specific nodes

You can add an extra condition to apply this component only to specific nodes.

```ts
import { NodeComponent } from "rete-angular-plugin/21";

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'))
```

### Connection customization

Use **connection** as a starting point from the [presets/classic/components](https://github.com/retejs/angular-plugin/blob/next/src/presets/classic/components){rel="nofollow"} directory of the plugin's source code.

```ts
import { CustomConnectionComponent } from './custom-connection.component'

render.addPreset(Presets.classic.setup({
  customize: {
    connection() {
      return CustomConnectionComponent
    }
  }
}))
```

### Socket customization

Use **socket** as a starting point from the [presets/classic/components](https://github.com/retejs/angular-plugin/blob/next/src/presets/classic/components){rel="nofollow"} directory of the plugin's source code.

```ts
import { CustomSocketComponent } from './custom-socket.component'

render.addPreset(Presets.classic.setup({
  customize: {
    socket() {
      return CustomSocketComponent
    }
  }
}))
```

## Customize context menu

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)

```scss
[rete-context-menu] {
  width: 320px;
  context-menu-search input.search {
    background: grey;
  }
  context-menu-item.block {
    background: grey;
  }
}
```

## Other presets

- [context menu](https://retejs.org/docs/guides/context-menu)
- [minimap](https://retejs.org/docs/guides/minimap)
- [reroute](https://retejs.org/docs/guides/reroute)

Check out the complete result on the [Customization for Angular](https://retejs.org/examples/customization/angular) example page.