# Hooks for nodejs smart actions

**URL:** <https://community.forestadmin.com/t/hooks-for-nodejs-smart-actions/7368>\
**Category:** Help me!\
**Tags:** smart-action\
**Created:** [July 30, 2024, 6:18pm UTC](https://community.forestadmin.com/t/hooks-for-nodejs-smart-actions/7368 "2024-07-30T18:18:42Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![nike1v](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/nike1v/32/7190_2.png) [@nike1v](https://community.forestadmin.com/u/nike1v)\
**Post date:** [July 30, 2024, 6:18pm UTC](https://community.forestadmin.com/t/hooks-for-nodejs-smart-actions/7368/1 "2024-07-30T18:18:42Z")

</div>

## Feature(s) impacted

I’m trying to use @forestadmin nodejs library to implement smart-actions and I found out that load hook is not available there for some reason, so I can’t manipulate with fields array after I open smart-action for a new row.

## Observed behavior

In console I see call to the POST /\_actions/collection/1/smart-action-name/hooks/load, but I can’t see any documentation or usages in the source code.

## Expected behavior

Able to use load hook to modify the smart-action.

## Context

- Project name: not sure it is needed in context of this question
- Team name: …
- Environment name: local
- Agent technology: nodejs
- Agent (forest package) name & version: “@forestadmin/agent”: “^1.41.7”, “@forestadmin/datasource-customizer”: “^1.45.6”, “@forestadmin/datasource-sql”: “^1.14.11”, “@forestadmin/datasource-toolkit”: “^1.34.4”,
- Database type: postgresql
- Recent changes made on your end if any: ?

# Question

How can I use hooks that are called from smart-action?  
Either I’d like to be able to use hooks for the smart-action, or be able to achieve creating fields dynamically while the form loads. Haven’t found a solution to this so far.

---

<div class="post-metadata">

**Author:** ![anon7284711](https://avatars.discourse-cdn.com/v4/letter/a/ac8455/32.png) [@anon7284711](https://community.forestadmin.com/u/anon7284711)\
**Post date:** [July 31, 2024, 6:59am UTC](https://community.forestadmin.com/t/hooks-for-nodejs-smart-actions/7368/2 "2024-07-31T06:59:18Z")

</div>

Hello @nike1v and welcome to the community !

The documentation for the `@forestadmin/agent` is located in a different url that you might be familiar with, [here it is](https://docs.forestadmin.com/developer-guide-agents-nodejs). And more specifically you will be able to find everything you need to create your dynamic actions in [this section](https://docs.forestadmin.com/developer-guide-agents-nodejs/agent-customization/actions/forms-dynamic).

Best regards,

---

<div class="post-metadata">

**Author:** ![nike1v](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/nike1v/32/7190_2.png) [@nike1v](https://community.forestadmin.com/u/nike1v)\
**Post date:** [July 31, 2024, 7:54am UTC](https://community.forestadmin.com/t/hooks-for-nodejs-smart-actions/7368/3 "2024-07-31T07:54:47Z")

</div>

Thank you for a quick reply, I do know that documentation, but there is no such a thing about smart-action hooks, so I’m here asking about them. With current Dynamic actions section I see only 3 properties for an action (execute, scope, form), but the library does calls /hooks/load request. So how can I access that one?

---

<div class="post-metadata">

**Author:** ![anon7284711](https://avatars.discourse-cdn.com/v4/letter/a/ac8455/32.png) [@anon7284711](https://community.forestadmin.com/u/anon7284711)\
**Post date:** [July 31, 2024, 8:10am UTC](https://community.forestadmin.com/t/hooks-for-nodejs-smart-actions/7368/4 "2024-07-31T08:10:41Z")

</div>

The call that you see is what will trigger the different function properties in your form definition. This allows to have specific handling functions per field and field property (`isRequired`, `isReadOnly`, `value`…)

> I can’t manipulate with fields array after I open smart-action for a new row.

If you wish to display a field based on a condition you can look at the [example 2](https://docs.forestadmin.com/developer-guide-agents-nodejs/agent-customization/actions/forms-dynamic#example-2-conditional-field-display-based-on-record-data) of the documentation.

---

<div class="post-metadata">

**Author:** ![nike1v](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/nike1v/32/7190_2.png) [@nike1v](https://community.forestadmin.com/u/nike1v)\
**Post date:** [July 31, 2024, 8:17am UTC](https://community.forestadmin.com/t/hooks-for-nodejs-smart-actions/7368/5 "2024-07-31T08:17:10Z")

</div>

The example 2 will be suitable when I have pre-defined form fields for the smart-action. But in my case I want them to be created based on a record field. Is it possible with current API?

---

<div class="post-metadata">

**Author:** ![anon7284711](https://avatars.discourse-cdn.com/v4/letter/a/ac8455/32.png) [@anon7284711](https://community.forestadmin.com/u/anon7284711)\
**Post date:** [July 31, 2024, 8:24am UTC](https://community.forestadmin.com/t/hooks-for-nodejs-smart-actions/7368/6 "2024-07-31T08:24:00Z")

</div>

Does this implementation not work out for you ?

````javascript
   {
        label: 'A field',
        type: 'String',
        if: async context => {
          const user = await context.getRecord(['firstName', 'lastName']);

          return user.firstName && user.lastName;
        },
   },
```
````

---

<div class="post-metadata">

**Author:** ![nike1v](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/nike1v/32/7190_2.png) [@nike1v](https://community.forestadmin.com/u/nike1v)\
**Post date:** [July 31, 2024, 8:31am UTC](https://community.forestadmin.com/t/hooks-for-nodejs-smart-actions/7368/7 "2024-07-31T08:31:55Z")

</div>

That’s not quite what I’m looking for. That implementation works fine in a case where I do need to show a field from existing form array, but in my case I’m trying to generate form array whenever the smart-action loads.  
Example:

```javascript
  private async generateDynamicFields(context: ISmartActionContext<TSchema, 'PdfForm'>) {
    if (context.getRecordId() === undefined) {
      this.form = this.defaultForm;
      return true;
    }

    const [contextFields, prefillVariables] = await Promise.all([
      context.getRecord(['fields']),
      this.prefillFormService.getPrefillVariables(),
    ]);
    const fields: FormField[] = contextFields.fields;
    const items = fields.map((field) => this.createActionFieldFromFormField(field, prefillVariables));

    this.form = [this.defaultForm[0], ...items];
    return false;
  }

```

In the example I’m trying to populate this.form array  
(which has type of `DynamicField<ISmartActionContext<TSchema, 'PdfForm'>>[]`)  
with new fields that will be generated based on a record of a current opened row.  
This is a Single scope smart-action.

---

<div class="post-metadata">

**Author:** ![nike1v](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/nike1v/32/7190_2.png) [@nike1v](https://community.forestadmin.com/u/nike1v)\
**Post date:** [July 31, 2024, 8:34am UTC](https://community.forestadmin.com/t/hooks-for-nodejs-smart-actions/7368/8 "2024-07-31T08:34:09Z")

</div>

The current implementation does work in some way, but I do have to reload a page 2 times before fields will be displayed, this is also gives some unclear thoughts when you open another record, but the smart-action populated with old fields (because it doesn’t reset itself when you close it by canceling and I do not have options to reset it manually or pre-populate the form array before form is displayed.

---

<div class="post-metadata">

**Author:** ![anon7284711](https://avatars.discourse-cdn.com/v4/letter/a/ac8455/32.png) [@anon7284711](https://community.forestadmin.com/u/anon7284711)\
**Post date:** [July 31, 2024, 9:01am UTC](https://community.forestadmin.com/t/hooks-for-nodejs-smart-actions/7368/9 "2024-07-31T09:01:51Z")

</div>

Thanks for the detailed information. As you’ve probably guessed this is not possible with the current implementation.

By digging with the team I have found both an ugly way to override the behaviour of actions and a draft PR to support dynamic field creation in action forms.

The override is not a suitable solution and direction I would like to push. I will bring back the subject of native support of dynamic forms to the team.

---

<div class="post-metadata">

**Author:** ![nike1v](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/nike1v/32/7190_2.png) [@nike1v](https://community.forestadmin.com/u/nike1v)\
**Post date:** [July 31, 2024, 9:06am UTC](https://community.forestadmin.com/t/hooks-for-nodejs-smart-actions/7368/10 "2024-07-31T09:06:48Z")

</div>

Ok, got it! Thanks for a productive conversation!

---

<div class="post-metadata">

**Author:** ![anon7284711](https://avatars.discourse-cdn.com/v4/letter/a/ac8455/32.png) [@anon7284711](https://community.forestadmin.com/u/anon7284711)\
**Post date:** [August 5, 2024, 9:58am UTC](https://community.forestadmin.com/t/hooks-for-nodejs-smart-actions/7368/11 "2024-08-05T09:58:29Z")

</div>

Hello @nike1v,

We have decided to release the ability to dynamically create the action form. You should be able to use it with `@forestadmin/datasource-customizer` 1.46.0

However I would like to inform you that there initially was a good reason that made the team hesitant to proceed with it.  
Every time the load hook is called on your action the form will be recomputed. This could lead to performance issues depending on your implementation as well as stability issues in the usage of the action if you handle the lifecycle of a field in multiple hooks.

When using the dynamic form creation;

- I would suggest limiting the use of dynamic properties inside of a field definition, even more so if it does some DB calls. Centralising the form lifecycle in your initial function would be the best in terms performance.
- If your form is dynamic only in its creation and remains the same afterwards, you can make use of the `context.formValues` which would contain the form after the first render. Avoiding unnecessary calls to your DB.

I hope you will find this satisfying.

Best regards,
