Cannot use encodeURIComponent in a dynamic value

Hello, in our project we have a destination for a link using a dynamic value. (In this case it’s actually a destination for a button onclick handler with a “Go to page” action, in case that matters.) My desired destination is something like /my-path?field1=value1&field2=value2. Note that value1 and value2 come from the current item of our CMS Data Fetcher. The fields field1 and field2 are both free text input fields in Plasmic CMS, allowing our content creators to enter spaces and special characters like & and /.

The problem we are having is that these fields are not properly URL-encoded, so, for example, the value “Cats & Dogs” becomes /my-path?field1=Cats%20&%20Dogs. See the problem? The space gets encoded to %20 (not sure how) but the ampersand remains unencoded. It should become %26 but it’s not. Since the browser uses an ampersand to delimit the query param key/value pairs, when our form pulls the query param values from the URL (and trims them) the value of field1 becomes just “Cats”.

Here’s what we have currently in the data picker (code view) for field1:

$ctx.plasmicCmsMyModelItem.data.field1.name

I did some googling, and the solution seems straightforward: I should use the native JavaScript function encodeURIComponent() (doc page: encodeURIComponent() - JavaScript | MDN ), like this:

encodeURIComponent($ctx.plasmicCmsMyModelItem.data.field1.name)

But when I try this I get a ReferenceError in the preview window.

Here is the error object:

{
  "name": "ReferenceError",
  "message": "encodeURIComponent is not defined",
  "__plasmicIgnoreError": true,
  "stack": "ReferenceError: encodeURIComponent is not defined\n    at Object.get (https://studio.plasmic.app/static/js/index.69ae4f1b.js:7137:300)\n    at Object.eval (eval at <anonymous> (https://studio.plasmic.app/static/js/index.69ae4f1b.js:7132:51545), <anonymous>:5:11)\n    at https://studio.plasmic.app/static/js/index.69ae4f1b.js:7137:378\n    at d (https://studio.plasmic.app/static/js/index.69ae4f1b.js:7137:575)\n    at p (https://studio.plasmic.app/static/js/index.69ae4f1b.js:7137:709)\n    at u (https://studio.plasmic.app/static/js/index.69ae4f1b.js:7137:829)\n    at m (https://studio.plasmic.app/static/js/index.69ae4f1b.js:10:101563)\n    at ld (https://studio.plasmic.app/static/js/lib-react.de9f53e7.js:2:127349)\n    at od (https://studio.plasmic.app/static/js/lib-react.de9f53e7.js:2:141652)\n    at i (https://studio.plasmic.app/static/js/lib-react.de9f53e7.js:2:189112)\n    at uI (https://studio.plasmic.app/static/js/lib-react.de9f53e7.js:2:167894)\n    at uM (https://studio.plasmic.app/static/js/lib-react.de9f53e7.js:2:167764)\n    at u_ (https://studio.plasmic.app/static/js/lib-react.de9f53e7.js:2:164869)\n    at r6 (https://studio.plasmic.app/static/js/lib-react.de9f53e7.js:2:113755)\n    at uk (https://studio.plasmic.app/static/js/lib-react.de9f53e7.js:2:161668)\n    at lH (https://studio.plasmic.app/static/js/lib-react.de9f53e7.js:2:132655)\n    at https://studio.plasmic.app/static/js/index.69ae4f1b.js:10:101695\n    at m (https://studio.plasmic.app/static/js/4865.04964446.js:519:559028)\n    at b (https://studio.plasmic.app/static/js/4865.04964446.js:519:559291)\n    at y (https://studio.plasmic.app/static/js/4865.04964446.js:519:559242)\n    at r (https://studio.plasmic.app/static/js/4865.04964446.js:467:317318)"
}

Is there a reason that encodeURIComponent() is not available in this context? It’s a standard browser global function. Or is there some other approach we should be taking?

Maybe Plasmic already is doing some URL encoding and just needs to do a little more? The fact that the spaces get encoded makes me wonder about this. Is this something you guys can fix/improve?

In the mean time, what work-around do you suggest? Thanks in advance!

As a work around while waiting for a response, I asked AI to come up with a RegEx that could mimic what encodeURIComponent() does, so we can manually encode the URLs inside Plasmic’s data picker context. Here’s what it gave me:

($ctx.plasmicCmsMyModelItem.data.field1.name || "").replace(/[^a-zA-Z0-9_.~-]/g, c => '%' + c.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0'))

This expression matches any character that isn’t a standard URL-safe character (a-z, A-Z, 0-9, -, _, ., ~) and converts its character code into hex percent notation. Seems pretty reasonable.

So for “Cats & Dogs” it ignores “Cats” and “Dogs” but catches spaces and the &:

  • Space becomes %20
  • Ampersand becomes %26
  • Result: Cats%20%26%20Dogs

This is working for me, and I wanted to put it here in case it helps someone else. But also it’s gross because it’s a funky regex that I never could have come up with on my own. (Plus the classic joke about regular expressions…now I have two problems).

Is this a terrible idea? Any thoughts on a better work around?

I think you can use encodeURIComponent directly, even though it errors in the editor. We have an allowlist for which global functions can be used and for some reason didn’t include it, but we’ll fix that!

We’ll also be fixing the root cause and encoding params properly!