Possible Platform Bug With multi-select submitOnChange enum inputs

I made a very simple app to reproduce the behavior that I believe is the root cause of something people were reporting in Hubitat Package Manager.

definition(
    name: "SubmitOnChange Test",
    namespace: "dcm.test",
    author: "Dominick Meglio",
    description: "Reproduces a bug",
    category: "My Apps",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
    iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")


preferences {
	page(name: "page1", title: "Page1")
	page(name: "page2", title: "Page2" )
}

def page1() {
	def options = [1,2,3,4,5,6,7,8,9,10]
	return dynamicPage(name: "page1", title: "Page 1", nextPage:"page2", uninstall:false, install: false) {
		section {
			input("opt", "enum", title: "Options", description: "Options", options: options, multiple: true, required: true, submitOnChange: true)
			if (opt != null) {
				log.debug "before pause execution"
				pauseExecution(10000) // something to take a while
				log.debug "after pause execution"
			}
		}
	}
	
}

def page2() {
    dynamicPage(name: "page2", title: "Page2", install: true, uninstall: false) {
        section {
			paragraph "The value of opt is: " + opt
		}
    }
}

Create a new user app with that code. Ensure the live log is running when you go through the preference pages. This testing was done in Chrome 81, unsure if it affects other browsers.

1.) Open live log
2.) Click add new user app and choose SubmitOnChange Test
3.) While on the first page, select a few options in the dropdown
4.) Do NOT click out of the dropdown such that the dropdown with the checkmarks remains open
5.) Click the Next button
6.) Observe that you immediately move to page 2
7.) Look in the live logs, you will see "before pause execution" is logged, but the "after pause execution" is not. Wait the 10 seconds and you will see it occurs AFTER you're already on page 2


1.) Repeat steps 1-4 except this time click OUT of the dropdown
2.) Notice that a spinner appears in the top right corner of the screen
3.) Attempt to click the next button
4.) Observe you can NOT click the next button until the spinner stops and the "After pause execution" log message appears

What I believe is happening here is, while the dropdown is open on an enum input(didn't test if it affects non-multiple fields), the Next button is NOT disabled when it SHOULD be if the input has submitOnChange = true.

In my HPM app this is leading to a situation where people click too quickly and the logic I have never finished executing causing the app to be in a bad state and displaying a blank page.

@bravenel @chuck.schwer - not sure which one of you handles these kinds of issues.

You're stepping on page refresh timing. Why don't you hide the Next button until you are ready to move forward? This can be done with some simple javascript.

That's a good solution, I wasn't sure if that was a good idea though. I figure when I start doing things like that I'm kind of tinkering with some of the inner workings of HE by requiring you guys to have specific ids/classes on your HTML elements. Though in fairness, HPM is already tinkering with some of the inner workings that you could easily break on me!

Rule Machine relies on this approach (for different reasons), and we aren't likely to change this. It's a kludge, but we do what it takes...

if(something) paragraph "<script>\$('button[name=\"_action_previous\"]').show()</script>"  
else paragraph "<script>\$('button[name=\"_action_previous\"]').hide()</script>"
1 Like

Thanks for the snippet! I was just poking in the code to make sure jQuery was available (assumed it was).

Another thing I make extensive use of is forcing a page refresh to update rendering. This has to be done with care to avoid an infinite refresh loop. I use a state variable test to protect it, and set that to false before the refresh.

      paragraph "<script>{changeSubmit(this)}</script>"

I can kinda use your code to fix it, meaning I can say if my input == null, hide. However, if someone goes, checks stuff off, clicks out. Goes back into the dropdown, checks different stuff, I don't have a way to trigger JS at that point so I think the bug could still occur.

You can always force the user to click an Update button. There are many ways around the issue you have.

Sure, I'm pretty sure I can get creative and come up with something. But it still seems to me like a bug. There is no way to just disable the next button automatically when a submitOnChange enum is "open"? It just feels wrong when the user (me) has to inject JavaScript to prevent a race condition. I'm certainly going to do it because I want it to work, but having to inject JS defintely seems clunky and can cause problems if you guys ever decide to change the frontend (which, as you know, many of us -- and I'm sure you guys too would like to see something a bit prettier down the road) my app would break. Even if I still have to show/hide the next button myself (I still think in this scenario it should be automatic), a hideNext: true setting on a dynamicPage would feel a lot cleaner than having to inject JS.

Yes, it's a clunky UI framework. Users can mess things up in many ways, and you can add this to the list. A new UI framework would entail reworking all of the built-in apps, so this is not a near term project for us.

Understood it’s not near term, though you can get around having to redo everything at once by making it opt-in per app by like having newLook: true. Kind of like how MS moved everything to UWP but not all at once and there are still many classic apps included with windows that are classic. It’s how I’ve handled things like this in large enterprise apps I’ve designed before. Just a thought...

1 Like