After update, previous onClick msg sent automatically

After sending a message to update the model a second message is automatically being sent to keep the menus that were the source of the first message open instead of allowing them to close as intended. Please see the current state of affairs here and the source code here.

Note that I have edited this question to reflect a better understanding of the problem that was not apparent when I originally posted.

It would help a lot if you could give full working example in ellie.

Try adding some debug statements to see what is happening with the model.

You could do it like this:

Rename update to innerUpdate, then

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model = Debug.log "updateResult" (innerUpdate (Debug.log "msg" msg) (Debug.log "model" model)

And read the console output to check if the model is really changed or not, and then drill down from there with more debug statements until you figure it out.

You could also use the time travel debugger, but its UI is sometimes awkward. Debug statements are more precise as you can target the problem area more exactly.

In AddNewToDo it gets the current time and then goes through with GetID <time>, but in GetID it doesn’t insert the new todo into the Dict.

https://ellie-app.com/3ZnrfqqWdDfa1

I apologize for the icons. I just grabbed links to things that were roughly the right size as I did not have time to upload the actual icons to a shareable site. The red icon on the bottom opens the main menu. The far left icon on that menu adds an item. Once an item is added clicking the item opens the item menu. The top menu choice there is to edit the item. The middle is to mark it complete and the last to delete it. The complete and delete actions should result in the item menu closing and the view re-rendering, but it does not.

This is intentional. If you grab a new ID but don’t submit a name/description then the Dict should not be updated. This is why GetID changes the view to the Editing screen.

I tested this a bit, and both of those does seem to cause model to update and view to re-render, BUT do not cause menu to close, until you move mouse out of the menu item. So this seems to be a bug of menu not closing, and not of model not updating.

I don’t know elm-ui so I have no idea why menu isn’t closing here.

The model isn’t updating correctly. The Complete and Delete update functions should set model.openMenu to None, but it remains at ItemMenu. Using the Debugger on Ellie it appears that the LaunchItemMenu message is being sent after the UpdateToDo message completes. But I can’t figure out why.

I think I figured this out. I tested clicking the middle menu option to complete the task. Messages in debug are:

  1. LaunchItemMenu ; model.CurrentToDoID = Just …
  2. CompleteToDo ; model.CurrentToDoID = Nothing
  3. LaunchItemMenu ; model.CurrentToDoID = Just …

So with CompleteToDo you change model.CurrentToDoID, which then changes selected value of your radio button (see code below), triggering its onChange event of LaunchItemMenu:

listTasksView : Model -> Element Msg
listTasksView model =
    column []
        [ Input.radio [ Font.size 24, Font.color (Element.rgb255 200 200 200) ]
            { onChange = \id -> LaunchItemMenu id
            , selected = model.currentToDoID --Nothing
            , label = Input.labelAbove [] (text "")
            , options =
1 Like

That makes total sense now. THANK YOU! This has been driving me crazy. I now just have to figure out a way around that.

I think it should be considered a bug in elm-ui. Maybe try filing a bug report?

When you use the core elm/html library you do not expect to trigger the messages assigned to onChange, onChecked or onInput if you internally modify the value of an element (such as when dynamically removing disallowed characters typed into a text input).

A quick check confirms this is true in the specific case of radio buttons:
https://ellie-app.com/3Zsv5FjD8NWa1
Note how the message counts don’t increase when the values of the radio buttons are altered by internal logic rather than by clicking on them directly. (Note that if I was writing something like this for real I’d not rely on my internal logic but rather a union type to stop more than one radio being selected, I was just coding up something quickly that would show individual message counts for each radio).

2 Likes

@mdgriffith: Do you agree this is a potential elm-ui bug? If so I can set up an issue on github.

I don’t think that’s it after all. I just changed from radio buttons to a list of Input.buttons and the same behavior persists. The buttons do not have an intrinsic onChange so something else is triggering it. The root issue is something triggers the model.currentToDoID to revert back to the previously selected item ID. This leads to the item menu staying open.
Ellie without radio buttons below:

https://ellie-app.com/3ZzbLSCHY2Ma1

I have edited the original post in this thread to reflect my new understanding of the problem with link to the full source code on github and the current version compiled with --debug.

Disclaimer from embarassment

I am aware that some code is redundant and other code is “dead” because I was in the middle of changing my layout and approach when I uncovered this problem. I plan to do some heavy refactoring once the bugs are cleared up.

The way I debug this is to first change LaunchItemMenu message from LaunchItemMenu Int to LaunchItemMenu Int String.

Then I add different string to each place where that message can be generated, and in update change LaunchItemMenu id -> to LaunchItemMenu id _ -> so that extra string is just ignored. (It’s just for debug output so I’ll know the exact location where problematic message is generated.)

In this case problem is line 310:

listTasksView model =
...
                Input.button
...

                    { onPress = Just (LaunchItemMenu id "310")
                    , label = Element.text (task.name)
                    }
...

According to documentation of button, onPress can be fired at Enter-key press or onClick. I’m not pressing any keys here so it must be onClick. Only click I’m doing is clicking the item at ItemMenu. But as it happens, you are creating ItemMenu as a child element of the button (see code below), so when clicking any item in ItemMenu, that event will propagate also to button and fire its onPress handler.

listTasksView model =
...
                Input.button
...
                    , Element.onLeft
                        (if Just id == model.currentToDoID then
                            (launchItemMenu model)
                         else
                            Element.none
                        )
...

Possible fix might be to prevent that event propagation, but I don’t know how to do that in elm-ui, or whether that is even possible.

1 Like

Actually just removing the onPress event handler while ItemMenu is being shown seems to work:
https://ellie-app.com/3ZJVjNF5LbKa1

                    { onPress =
                        (if Just id == model.currentToDoID then
                            Nothing
                         else
                            Just (LaunchItemMenu id)
                        )                    

Going back to your earlier version with radio button, unfortunately onChange of radio button doesn’t accept Maybe msg like onPress does, but you can just generate message there that is ignored:
https://ellie-app.com/3ZK3CSNGjCRa1

listTasksView : Model -> Element Msg
listTasksView model =
    column []
        [ Input.radio [ Font.size 24, Font.color (Element.rgb255 200 200 200) ]
            { onChange =
                if model.currentToDoID == Nothing then
                    \id -> LaunchItemMenu id
                else
                    \_ -> Ignored
...
type Msg
    = AddNewToDo
...
    | Ignored

update msg model =
    case msg of
        Ignored ->
            ( model, Cmd.none )
...
2 Likes

Great explanation and solution. Hadn’t occurred to me that children of buttons would activate the button, but of course they should. A quirk that could actually lend itself to interesting design choices for UI at some point. Thanks again!

Hey! Sorry, I haven’t been following, but am definitely interested. If someone wants to put together a brief summary of what you all found and an SSCCEE in an issue on the repo, I’d definitely appreciate it :smiley:

I’m not sure if there’s a direct solution elm-ui can do, but at the very least I can include a note about it in the guide.

I don’t think it’s an em ui issue directly after all. If anything it might be considered an elm bug because one event propagates two Msgs somehow.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.