Passing parameter with href

I working on a app that does multiple functions. Selecting the functions is done via user input and calls to href with params

https://docs.smartthings.com/en/latest/smartapp-developers-guide/preferences-and-settings.html#href

href "mainAppPage", title: "Myapp" , description: "", params: ["myparam1": "value1"]

or

href "mainAppPage", title: "Myapp" , description: "", params: ["myparam1": "value2"]

and later:

def mainAppPage(params) {
}

In many cases I see params as null. If the user selects the option for "value1", then sets things and hits done (for that page), then selects the option that goes into href with "value2", it randomly is null, or "value1" passed.

An ugly workaround is to try not to use params, but a separate page for each value, such as:

mainAppPage1()
mainAppPage2()
...

ie one for each possible value of params. This gets ugly quick, and even uglier if params has multiple fields in the map.

Params are lost on page refresh, this is a known issue.
Don't shoot me if it isnt, but pretty sure this will be fixed in the next release.

thx, is the navigation from page(parms1), to page(parms2) considered a refresh?

Not following,
If you reference the page params after a browser refresh, or after a submitOnChange update they will be null.
In other words, they only exist on the pages initial rendering.

ok, but if you finish page with href....params(param1)

and go into page href....params(param2)

you are saying the first time the 2nd href call you should see params2 (until the refresh or submit on change). I'm not seeing that. I see params1.

So you load up page 1, said page has an href to page 2, the params being passed to the href are generated on page 1 and passed to page 2.
Page 2 gets the params.
User hits done and is sent back to page 1.
If page 1 now creates a different param value for the href, and the user goes to page 2, those new params will be there.

I am seeing this 2018-Nov issue today 2023-Aug-11.

Was the original issue fixed?

Is there a "right way" to avoid manual refreshes per change?

Issue Summary

  1. An href is used to open a page with a passed params map.
  2. The page loads with the passed params correctly.
  3. The page solicits client input.
  4. The client enters a value.
  5. The client (via tab | enter | selection of another field) registers the change.
  6. An error occurs:
    Error: Cannot get property '{param-name}' on null object
  7. Client reloads the page by brute-force (Google Chrome "↻")
  8. On reload, the page finds the params without issue and processing continues.

The results are the same irrespective of the submitOnChange input field.

The href-invoked pages always return to the calling page on Done without issue.

What you have to do is capture the passed in params map when the page is first called. Only the original call to the page from the href actually has the params present, otherwise they will be null.

Something like this works, where you put the params into state and pull them back out when they are null:

Map setSchedule(param) {
	if(param) state.schedNdx = param.n else param.n = state.schedNdx
    dynamicPage(name: "setSchedule", ...

Previously, I tried to go down the path you suggest, but ran into a Catch-22 that may be unique to my use case.

I have a Main Page that includes a loop for invoking href to collect multiple instances of highly patterned data.

Main Page

List<String> calledItems = ['A', 'B', 'C', ...]

settings.calledItems.each{ item ->
  href (
    title: "${item} Stuff",
    page: calledPage,
    param: [
      settingsPrefix: item,
    ],
    style: 'internal'
  )
}

The called pages use the passed parameter to create predictable, per-child settings keys.

Child Page

void solicitInput1 (String settingsPrefix) {
  input (
    name: "${settingsPrefix}-thing",
      :
  )
}

void solicitInput2 (String settingsPrefix) {
  input (
    name: "${settingsPrefix}-anotherThing",
      :
  )
}

def calledPage (param) {
  if (param) state.XXXXX = param.settingsPrefix
  else param.settingsPrefix = state.XXXXX
  dynamicPage(name: 'calledPage') {
    section {
      String item = param.settingsPrefix
      solicitInput1(item)
      solicitInput2(item)
      solicitInput3(item)
        :
    }
  }
}

The Conundrum

Each invocation of the child page needs its own unique XXXXX identifier (to avoid stepping on each other, right?). But, the child pages share a common template. The template could randomly generate XXXXX, but the value would regenerate on a page refresh.

For now, I may live with the manual refresh.

Yeah, you're going to have a problem disambiguating multiple hrefs. Perhaps you could use a state object to identify which one you're working on. That is, maybe use state instead of params.

Rule Machine (and other apps) have all sorts of contexts like this, where a single href is called to input various things. For example, selecting an action. RM always uses state for this, typically just using a simple counter. That counter is appended to input names, state names, whatever is needed to identify the particular action being worked on.