# FAQ

::questions
  :::qa{#own-plugin question="How to develop my own plugin?"}
  Check out the [instructions](https://retejs.org/docs/development#create-plugin) for Rete Kit
  :::

  :::qa
  ---
  id: server-side
  question: Can the graph be processed on the server-side, such as Node.js?
  ---
  Yes, follow the [Dataflow](https://retejs.org/docs/guides/processing/dataflow) or [Control flow](https://retejs.org/docs/guides/processing/control-flow) guides
  :::

  :::qa
  ---
  id: processing-on-different-langs
  question: Can the graph be processed using Python or other server-side
    programming languages?
  ---
  The engine only supports JS runtime. You can either bind JS into your environment or implement your own engine, similar to `rete-engine` (it has a straightforward implementation)
  :::

  :::qa
  ---
  id: use-for-commercial
  question: Can the framework be used for commercial purposes?
  ---
  In short, yes. Refer to the [Licensing](https://retejs.org/docs/licensing) for details
  :::

  :::qa
  ---
  id: no-typescript
  question: Can I use the framework if I don't know TypeScript?
  ---
  It can be used in JS code, but not recommended because of poor DX
  :::

  :::qa{#save-to-json question="Is there a way to save a graph as a JSON file?"}
  Yes, follow the [Import/export](https://retejs.org/docs/guides/import-export) guide
  :::

  :::qa{#scroll-prevented question="How to disable scroll prevention?"}
  Replace zoom handler with `null` or use a custom one
  
  ```ts
  const area = new AreaPlugin(container)
  
  area.area.setZoomHandler(null)
  ```
  :::

  :::qa{#dynamic-zoom question="How to enable/disable zoom dynamically?"}
  Replace the zoom handler with `null` on some event and restore it on opposite (e.g. Ctrl press/release)
  
  ```ts
  import { Zoom } from 'rete-area-plugin'
  
  // call on init
  area.area.setZoomHandler(null)
  
  // call on Ctrl press
  area.area.setZoomHandler(new Zoom(0.1))
  
  // call on Ctrl release
  area.area.setZoomHandler(null)
  ```
  :::

  :::qa
  ---
  id: pan-middle-mouse-button
  question: How to pan the area using the middle mouse button?
  ---
  Replace the drag handler for a specific area by calling `setDragHandler`
  
  ```ts
    import { Drag } from 'rete-area-plugin';
  
    area.area.setDragHandler(new Drag({
      down: e => {
        if (e.pointerType === 'mouse' && e.button !== 1) return false
  
        e.preventDefault()
        return true
      },
      move: () => true
    }))
  ```
  :::

  :::qa{question="How can I retrieve the position of a node?"}
  The position is stored within a `NodeView` instance.
  
  ```ts
    const view = area.nodeViews.get(nodeId)
  
    if (view) {
      view.position // { x, y }
    }
  ```
  
  Keep in mind that the `NodeView` instance may not exist, for example if it hasn't yet been added. In such cases, it's preferable to handle this gracefully (throw an exception only when necessary)
  :::

  :::qa{question="How can I translate a node/change the position of a node?"}
  ```ts
    area.translate(nodeId, { x: 0, y: 0 })
  ```
  :::

  :::qa
  ---
  id: arrange-nodes
  question: How can I automatically arrange the position of nodes?
  ---
  Follow the [Arrange nodes](https://retejs.org/docs/guides/arrange) guide
  :::

  :::qa{#force-update question="How to force an update on nodes or controls?"}
  Call the following methods for the corresponding nodes or controls after making changes to the state
  
  ```ts
  const area = new AreaPlugin(container)
  
  area.update('node', node.id)
  area.update("control", control.id);
  ```
  :::

  :::qa
  ---
  id: various-render-plugins
  question: How to render various nodes or controls using Angular, React, and Vue
    in one editor?
  ---
  Check out the [Combining render plugins](https://retejs.org/docs/concepts/integration#combine) in the [Integration](https://retejs.org/docs/concepts/integration) article
  :::

  :::qa
  ---
  id: add-custom-elements-to-area
  question: How can I add my own elements to the editor area?
  ---
  Use the methods of `content` property of the area plugin
  
  ```ts
  const area = new AreaPlugin(container)
  
  area.content.add(element)
  
  area.content.remove(element)
  ```
  
  It's also possible to make this element draggable
  
  ```ts
  const dragHandler = new Drag()
  
  dragHandler.initialize(element, { /* getters */ }, { /* events */ })
  ```
  :::

  :::qa{#customize-node question="How to customize nodes?"}
  Check out the relevant customization guide for [React.js](https://retejs.org/docs/guides/renderers/react#customization), [Vue.js](https://retejs.org/docs/guides/renderers/vue#customization), [Angular](https://retejs.org/docs/guides/renderers/angular#customization), [Svelte](https://retejs.org/docs/guides/renderers/svelte#customization) or [Lit](https://retejs.org/docs/guides/renderers/lit#customization).
  :::

  :::qa
  ---
  id: collapse-node
  question: How to collapse the node (to minimize a node's size by hiding its controls)?
  ---
  Define how elements should be hidden when the node is collapsed by creating a custom node component.
  
  Check out the relevant customization guide for [React.js](https://retejs.org/docs/guides/renderers/react#customization), [Vue.js](https://retejs.org/docs/guides/renderers/vue#customization), [Angular](https://retejs.org/docs/guides/renderers/angular#customization), [Svelte](https://retejs.org/docs/guides/renderers/svelte#customization) or [Lit](https://retejs.org/docs/guides/renderers/lit#customization).
  :::

  :::qa
  ---
  id: new-render-plugins
  question: What are the steps to implement render plugin for other framework?
  ---
  - [Setup a plugin](https://retejs.org/docs/development/#create-plugin)
  - Use the source code of the following packages as a reference: [React.js](https://github.com/retejs/react-plugin){rel="nofollow"}, [Vue.js](https://github.com/retejs/vue-plugin){rel="nofollow"}, [Angular](https://github.com/retejs/angular-plugin){rel="nofollow"}, [Svelte](https://github.com/retejs/svelte-plugin){rel="nofollow"} or [Lit](https://github.com/retejs/lit-plugin){rel="nofollow"}
  :::

  :::qa
  ---
  id: prevent-node-movement-on-control
  question: Is there way to prevent nodes from being moved while interacting with controls?
  ---
  You need to stop propagation of the `pointerdown` event.
  
  Check the relevant render plugin guide for controls: [React.js](https://retejs.org/guides/renderers/react#controls), [Vue.js](https://retejs.org/guides/renderers/vue#controls), [Angular](https://retejs.org/guides/renderers/angular#controls), [Svelte](https://retejs.org/guides/renderers/svelte#controls), [Lit](https://retejs.org/guides/renderers/lit#controls)
  :::

  :::qa
  ---
  id: click-event-doesnt-work-on-control
  question: Why doesn't the control capture click/pointer events?
  ---
  By default, the area captures these events, so you need to stop the propagation of `pointerdown` event to prevent this
  
  Check the relevant render plugin guide for controls: [React.js](https://retejs.org/guides/renderers/react#controls), [Vue.js](https://retejs.org/guides/renderers/vue#controls), [Angular](https://retejs.org/guides/renderers/angular#controls), [Svelte](https://retejs.org/guides/renderers/svelte#controls), [Lit](https://retejs.org/guides/renderers/lit#controls)
  :::

  :::qa
  ---
  id: user-select
  question: Is there a way to make the text within a node selectable?
  ---
  By default, a node is configured with the CSS property `user-select: none` to prevent conflict between text selection and node dragging.
  
  Therefore, to enable text selection within a custom node component, you need to specify `user-select: all` property for the desired element within the node. Additionally, ensure you call `e.stopPropagation()` on the \`pointerdown\`\` event to prevent text selection interruptions while dragging.
  :::

  :::qa{#nodepicked question="How to detect click on the node?"}
  Whenever a user clicks on the node, the `nodepicked` event is fired:
  
  ```ts
  area.addPipe(context => {
    if (context.type === 'nodepicked') {
      const node = editor.getNode(context.data.id)
  
    }
    return context
  })
  ```
  
  In case you need to track not only click, but also node selections, you have the option [to extend the selector](https://retejs.org/docs/guides/selectable#extend-selector) to observe selected elements (not just nodes) within the editor
  :::

  :::qa
  ---
  id: add-inputs-outputs-controls-dynamically
  question: How to add inputs, outputs or controls dynamically?
  ---
  You can add them as usual using the `addInput`/`addOutput`/`AddControl` methods, and then force a node update
  
  ```ts
  const area = new AreaPlugin(container)
  
  area.update('node', node.id)
  ```
  :::

  :::qa{#add-control-to-output question="How to add a control to the output?"}
  The process of adding such elements requires the creation of a custom node.
  
  Check out the relevant customization guide for [React.js](https://retejs.org/docs/guides/renderers/react#customization), [Vue.js](https://retejs.org/docs/guides/renderers/vue#customization), [Angular](https://retejs.org/docs/guides/renderers/angular#customization), [Svelte](https://retejs.org/docs/guides/renderers/svelte#customization) or [Lit](https://retejs.org/docs/guides/renderers/lit#customization).
  :::

  :::qa
  ---
  id: undirected-graph
  question: How to create an undirected graph with nodes that don't have
    input/output sockets?
  ---
  You can use the classic preset with custom nodes and a unified socket for both input and output port.
  
  Check out the [Undirected](https://retejs.org/examples/undirected) example
  :::

  :::qa
  ---
  id: vertically-oriented-editor
  question: How to make an editor oriented vertically?
  ---
  Check out the [Vertical flow](https://retejs.org/examples/vertical-flow) example
  :::

  :::qa
  ---
  id: order-inputs-controls-outputs
  question: How to change the order of inputs/controls/outputs?
  ---
  The classic rendering preset offers the flexibility to specify an optional `index` field for inputs, outputs or controls. This feature enables you to change the order of these elements within their lists.
  
  ```ts
  const input = new ClassicPreset.Input(socket)
  const output = new ClassicPreset.Output(socket)
  const control = new ClassicPreset.InputControl('text')
  
  input.index = 0;
  output.index = 0;
  control.index = 0;
  ```
  :::

  :::qa
  ---
  id: align-inputs-outputs
  question: How to change the alignment of inputs/outputs?
  ---
  The process of changing the node layout requires the creation of a custom node.
  
  Check out the relevant customization guide for [React.js](https://retejs.org/docs/guides/renderers/react#customization), [Vue.js](https://retejs.org/docs/guides/renderers/vue#customization), [Angular](https://retejs.org/docs/guides/renderers/angular#customization), [Svelte](https://retejs.org/docs/guides/renderers/svelte#customization) or [Lit](https://retejs.org/docs/guides/renderers/lit#customization).
  :::

  :::qa
  ---
  id: render-vanilla-js
  question: Is it possible to render UI using vanilla JS exclusively, without
    resorting to frameworks?
  ---
  In short, it is possible, but there is no plugin available for this approach since it doesn't offer significant advantages in comparison to the development costs
  :::

  :::qa
  ---
  id: update-rete-deps
  question: What is the best way to update all `rete` related dependencies?
  ---
  If you don't want to update all of your dependencies at once with `npm update`, you can selectively update those that begin with `rete` using a regular expression
  
  ```bash
  npx npm-check-updates /^rete/ --target @latest -u
  ```
  :::

  :::qa{#loop-connections question="How to display a loop connection?"}
  All available rendering plugins can display a loop connection if it has specified `isLoop` property
  
  ```ts
  class Connection extends ClassicPreset.Connection {
    isLoop = false
  }
  
  const connection = new Connection(source, output, target, input)
  
  connection.isLoop = true
  ```
  :::

  :::qa
  ---
  id: minimum-ts-version
  question: What is the minimal TypeScript version required?
  ---
  The minimum required TypeScript version is 4.7.
  
  Otherwise, you might encounter the error `Type instantiation is excessively deep and possibly infinite. ts(2589)` when using the `use` method. If you can't use a later version for some reason, the only solution is to use `@ts-ignore`.
  
  For example, when creating an Angular 12 application with [Rete Kit](https://retejs.org/docs/development/rete-kit), a version 4.7 higher than the officially supported one is installed.
  :::

  :::qa
  ---
  id: zoom-area
  question: How can I change the editor's zoom level programmatically?
  ---
  Using the `area.zoom` method enables you to specify the desired zoom level and the offset points for aligning the zoom
  
  ```ts
  await area.area.zoom(0.8, 0, 0);
  ```
  
  In the given example, the zoom will be decreased with respect to the top left boundary. If you want to modify the zoom relative to the center of the viewport, refer to the following code
  
  ```ts
  const delta = 0.2;
  const { k } = area.area.transform;
  const box = area.container.getBoundingClientRect();
  const x = box.width / 2 / k;
  const y = box.height / 2 / k;
  
  area.area.zoom(k * (1 - delta), x * delta, y * delta);
  ```
  :::

  :::qa{#translate-area question="How can I modify the position of the area?"}
  By utilizing the `area.translate` method, you can change the coordinates as follows
  
  ```ts
  await area.area.translate(100, 20)
  ```
  
  Change in position relative to current coordinates
  
  ```ts
  const { x, y } = area.area.transform
  await area.area.translate(x + 100, y + 20)
  ```
  
  Change the editor's position considering the zoom factor
  
  ```ts
  const { k } = area.area.transform
  
  await area.area.translate(100 * k, 20 * k)
  ```
  :::

  :::qa
  ---
  id: different-stack
  question: What if my app uses different stack and isn't based on React.js,
    Vue.js, or Angular?
  ---
  In case you're using a framework other than React.js, Vue.js, Angular, Svelte or Lit (for which Rete.js provides a rendering plugin), you have the option to utilize the [React.js plugin](https://retejs.org/docs/guides/renderers/react) to render nodes and other editor elements.
  
  For a quick start, you can create a React.js application using [Rete Kit](https://retejs.org/docs/development/rete-kit), copy the code of the editor from `src/rete/default.tsx`, install the relevant dependencies in your project and call `createEditor`, providing the HTMLElement container created by your application.
  :::

  :::qa
  ---
  id: viewport-center
  question: How can I retrieve the coordinates of the viewport center?
  ---
  First of all, you need to obtain the viewport center in screen coordinates using `getBoundingClientRect`. Afterward, you should transform them into editor coordinates by applying the zoom factor `k` and offset it relative to area's position.
  
  ```ts
  const area = new AreaPlugin<Schemes, AreaExtra>(container)
  
  const { x, y, k } = area.area.transform
  const box = area.container.getBoundingClientRect()
  const halfWidth = box.width / 2 / k
  const halfHeight = box.height / 2 / k
  
  return { x: halfWidth - x / k, y: halfHeight - y / k }
  ```
  :::

  :::qa
  ---
  id: sockets-warning
  question: What does the warning 'Found more than one element for socket with
    same key and side' mean?
  ---
  The warning "Found more than one element for socket with same key and side" means that there are duplicate sockets in the editor that were not properly removed after an update, or due to an asynchronous approach when unmounting components by different UI frameworks, the lifecycle of old and new ones overlaps.
  
  In the first case, when the number of these warnings constantly accumulates, you most likely have a memory leak problem because some custom node was not correctly unmounted.
  
  In the second case, the warning can be avoided by adding a delay between removing the scheme/node and mounting a new one with the same identifiers. In the worst case, this warning should not indicate memory leak issues, so you can ignore it.
  :::

  :::qa
  ---
  id: select-deselect-event
  question: How to track the select or deselect event of a node?
  ---
  The framework does not have a reserved event for this. Instead, you can \[/docs/guides/selectable#extend-selector]\(extend the selector) by triggering events in the relevant methods.
  :::

  :::qa{#handle-dblclick question="How to handle double-click events on nodes?"}
  Create a custom node component with a `dblclick` event handler.
  
  Check out the customization guide for your renderer: [React.js](https://retejs.org/docs/guides/renderers/react#customization), [Vue.js](https://retejs.org/docs/guides/renderers/vue#customization), [Angular](https://retejs.org/docs/guides/renderers/angular#customization), [Svelte](https://retejs.org/docs/guides/renderers/svelte#customization) or [Lit](https://retejs.org/docs/guides/renderers/lit#customization).
  
  **Important:** If your custom node contains nested interactive elements (buttons, inputs, etc.), make sure to prevent event propagation to avoid conflicts with the node's double-click handler.
  :::

  :::qa
  ---
  id: dblclick-prevent-zoom
  question: How to prevent/disable zoom on dblclick?
  ---
  ```ts
    area.addPipe(context => {
      if (context.type ===  'zoom' && context.data.source === 'dblclick') return
      return context
    })
  ```
  :::
::