Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot interpolate custom functions parameters #6777

Open
masciugo opened this issue Aug 23, 2023 · 3 comments
Open

Cannot interpolate custom functions parameters #6777

masciugo opened this issue Aug 23, 2023 · 3 comments
Labels

Comments

@masciugo
Copy link
Contributor

Are you requesting a feature, reporting a bug or asking a question?

feature

What is the current behavior?

I have an async custom function called getRemoteObjectProp that return a remote object property. So the function run an http request to fetch the remote object and than provide the specified prop. The first parameter is the request url. I would like to build it dynamically:

{
  "name": "id",
   "type": "text"
},
{
  "name": "q1",
  "type": "expression",
  "expression": "getRemoteObjectProp('/misc/AIFAdrugs/{id}', 'ATCcode')")
}

My workaround at moment is replacing the placeholder $ with the last parameters in an orderly manner

{
  "name": "q1",
  "type": "expression",
  "expression": "getRemoteObjectProp('/misc/AIFAdrugs/$', 'ATCcode', {id})")
}

What is the expected behavior?

I'd like an interpolation like the one you can use in the choicesByUrl url property

thank you

@masciugo
Copy link
Contributor Author

.. or maybe having a function that interpolate a string like:

"expression": "getRemoteObjectProp(interpolateFunction('/misc/AIFAdrugs/{id}'), 'ATCcode')")

.. but I don't know if nested functions work

@masciugo
Copy link
Contributor Author

I am trying my custom interpolation solution to have my desired expressiongetRemoteObjectProp('/misc/AIFAdrugs/{id}', 'ATCcode')) working:

const getRemoteObjectProp = function(args) {
  let url = args[0],
    prop = args[1]

  if (url && prop) { // all params must be well defined

    url.match(/\{[A-Za-z0-9_\-.]+\}/g).every( ph => {
      let name = ph.slice(1,-1),
        value = this.survey.getVariable(name) || this.survey.getCalculatedValueByName(name) || this.survey.getQuestionByName(name)?.value  

      if (value) {
        url = url.replaceAll(ph,value)
        return true
      } else {
        url = undefined
        return false
      }

    })

  } else {
    url = undefined
  }

  if (url) {
    if (url.startsWith("/")) {
      url = window.location.origin + url
    }
    url = new URL(url)
  }

  [...]

but this work only for not nested questions. If I try to use it in a paneldynamic (for example)this.survey.getQuestionByName(name)?.value of course would not work. How can I reach all question values defined here

thanks a lot

@andrewtelnov
Copy link
Member

@masciugo You can check for this.row context if you are running expression inside the matrix and I have just added this.panel context for panel dynamic. Here is the PR.
Your code will be:

const context = !!this.row ? this.row ? (!!this.panel ? this.panel : this.survey);
const q = context.getQuestionByName(questionName);
if(!q && context !== this.survey) q = this.survey.getQuestionByName(questionName);

Regarding a new functionality, there is a high possibility that some developers requrie to pass "{val}" to a server.

Thank you,
Andrew

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants