Interpolating input fields inside JSON request body

Given a number input field and an OpenAPI operation that takes an arbitrary JSON object as its request body, I get some weird behavior when trying to use the value of the input field directly.

For example:

{
  "someNumber": {{ someNumberInput.value }}
}

Will report a parse error if the field doesn't have a value.

Then if I wrap the value in double quotes like so:

{
  "someNumber": "{{ someNumberInput.value }}"
}

It parses, but then I get inconsistent behavior between the JSON preview underneath the text box and what actually gets sent to the server. The preview shows { "someNumber": "" }, but then what gets sent to the server is { "someNumber": null }.

So this is broken on multiple levels as there is an inconsistency between:

  • how the JSON gets parsed
  • how it gets displayed in the preview
  • what actually gets sent to the server

Is there a workaround, or better way to do this altogether?

Hello @Joe_Betz, welcome to the forum! :wave:

We should make this work by adding a ternary. If we wanted the value to be "" instead of null:

{
  "someNumber": {{ someNumberInput.value ? someNumberInput.value : "" }}
}

Otherwise:

{
  "someNumber": {{ someNumberInput.value ? someNumberInput.value : null }}
}

That being said, ideally the preview would look just like what is sent to the server. I'll try reproducing this on my end and create a bug report for this issue.

Thank you for your feedback! :slightly_smiling_face:

When I tried reproducing with a REST API, even without a default value on the Number Input component, the expression evaluates to i 0 when there is no selection. On a a text input, no input evaluates to "":

What Open API endpoint are we trying to hit?

Hi @Paulo, thanks for taking a look. The solution you proposed does work but is somewhat unsatisfying since it requires referencing the variable twice. Would it be possible to have value take an argument that it provides as a default when the widget value is null?

E.g., someNumberInput.value(0) or someNumberInput.value("").

As for the inconsistency with the object preview and what actually gets sent to the server, here's a screenshot that exemplifies the problem:

You see how the JSON looks okay in the interpolated request body but there is a parse error when it's actually sent to the server.

When I tried reproducing with a REST API, even without a default value on the Number Input component, the expression evaluates to i 0 when there is no selection.

Your example isn't using the raw JSON input form, though, which I need in order to send nested objects.

What Open API endpoint are we trying to hit?

It's not a public API so you unfortunately won't be able to test with it. But any Open API endpoint that accepts an arbitrary JSON object in its request body should work.

We could use additionalScope to do something similar.
Here is a TLDR:
Js call Retool RPC with arguements - #5 by Paulo

On submit, we could run a script to trigger this query, using an if statement that evaluates if there was a value.

Something like:

let val = numberInput.value

if( val ){
 queryName.trigger({
    additionalScope: {
      number: val
  }
})
} else {
  queryName.trigger({
    additionalScope: {
      number: ""
  }
})
}

Did the above work for your use case?

It works, but what I already had works as well, so it doesn't really help to switch to a different workaround. But if you filed a bug report I guess this is the best we can do for now.

1 Like