Skip to content

Making "args" accessible in the context for buttons with action type "inlineJS" #477

@voltel

Description

@voltel

Please fill out these Check-boxes

  • I checked for existing similar feature requests
  • I have read the docs and checked that the feature I am requesting is not already implemented
  • My feature request consists of only one feature

Is your Feature Request related to a Problem or Annoyance?

No response

Describe the Feature you'd like

Previously, I had stand-alone JS script files inside my vault notes which were run for the button action type js with the args option to pass an additional parameter to the script.

```meta-bind-button
actions:
  - type: js
    file: my.js
    args:
      myParam: value
```

Now, I moved everything inside a custom plugin, so instead of a stand-alone script, I have exposed public api and added Obsidian commands registered by the plugin.

For the former, I understand there is still no straightforward way to pass any custom parameters to Obsidian commands.

As for the option of calling a function defined in the plugin api, I have the following button action definition:

```meta-bind-button
actions:
  - type: inlineJS
    code: |-
        const api = app.plugins.getPlugin('my-plugin')?.api;
        if (! api) return `Error. No my plugin API found`;
        const f = api.command.createNote;
        f(this.globals);
    args:
      myParam: value
```

Unfortunately, the args config option is not currently supported for inlineJS action type (https://www.moritzjung.dev/obsidian-meta-bind-plugin-docs/reference/buttonactions/inlinejs/).

May I kindly request adding support for the args configuration option for inlineJS button action, so that the existing logic in the function could still be used without modifications, similar to what is described here:
https://www.moritzjung.dev/obsidian-meta-bind-plugin-docs/reference/buttonactions/runjavascript/

Alternatives

There is an opportunity to register additional Obsidian commands specifically for the variations of the arguments in question. This is not a good workaround, as the combinations even of 2 arguments with each having only 2 variations will make it necessary to register 4 additional Obsidian commands.

```meta-bind-button
actions:
  - type: command
    command: my-plugin:my-command--arg-1-value-1--arg-2-value-1
    command: my-plugin:my-command--arg-1-value-1--arg-2-value-2
    command: my-plugin:my-command--arg-1-value-2--arg-2-value-1
    command: my-plugin:my-command--arg-1-value-2--arg-2-value-2
```

The more realistic workaround is to change the function definition and introduce an additional argument for args.

Before:

// my plugin TS file 

export async function createNote (
    globalsOrPlugin: JsExecutionGlobals | MyPlugin
): Promise<void> 
{
    let currentNoteFile: TFile | undefined | null;
    let globals: JsExecutionGlobals | undefined; 

    if (globalsOrPlugin instanceof MyPlugin) {

        plugin = globalsOrPlugin;
        app = plugin.app;
        currentNoteFile = app.workspace.getActiveFile();
        jsEngineApi = libUtility.getJsEngineApi();

    } else {
        
        globals = globalsOrPlugin;

        if (! globals) {
            throw new InvalidArgumentError('Empty argument "globals". Did you forget to pass the js-engine "globals" object? ');
        }

        app = globals.app;
        plugin = libUtility.getMyPluginFromObsidianApp(app) as MyPlugin;
        currentNoteFile = globals.context.file;
        jsEngineApi = globals.engine; 
        
    }//endif 

    //...
    
    // Logic utilizing the context args
    const jsEngineContext = globals ? 
        globals.context as JsEngineExecutionContextForThisCommandType : undefined;

    if (jsEngineContext && jsEngineContext.args?.["myParam"] === MY_VALUE_1) {
        // ... configuration 1 
        
    } else if (jsEngineContext && jsEngineContext.args?.["myParam"] === MY_VALUE_2) {
        //... configuration 2

    } else {
       // ... default configuration 
    }//endif 

After:

```meta-bind-button
actions:
  - type: inlineJS
    code: |-
        const api = app.plugins.getPlugin('my-plugin')?.api;
        if (! api) return `Error. No my plugin API found`;
        const f = api.command.createNote;
        f(this.globals, {myParam: "myValue1"});
```
// my plugin TS file 

export async function createNote (
    globalsOrPlugin: JsExecutionGlobals | MyPlugin,
    args?: {myParam: "myValue1" | "myValue2"}
): Promise<void> 
{
   // ... the same as above

   // Logic utilizing the args  

    if (args?.["myParam"] === MY_VALUE_1) {
        // ... configuration 1 
        
    } else if (args?.["myParam"] === MY_VALUE_2) {
        //... configuration 2

    } else {
       // ... default configuration 
    }//endif 

Additional Context

As discussed before, I would not like a standalone script file (i.e., the one processing the button action of type "js", which can currently accept the "args" in the context) to live in the vault, as my intention is to make plugin updates as easy as possible, and for that I don't want to have to update potentially numerous additional standalone script files, while the logic can be hidden inside the plugin API wrapper.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions