Weird behavior. Updating value of one input also updates value of another input

I am seeing a weird behavior. The relevant code is below. Essentially I have the following setup: I have two input elements, one for entering date and one for entering time. Initially these are populated with the current date and current time from Elm. Then the user can change them using materializecss datepicker and timepicker. When the value is chosen I subscribe to the changes from Elm and update the relevant value in the model containing the timestamp. Based on the logged values, these updates are all occurring correctly. The problem is with the display of the date variable. The date changes to the time variable when I update the time variable using the timepicker. This should not be the case because the Html.Attributes.Value sets it to dateRepr which has the correct date value as logged to the console (screenshots for both are shown below). The code:

viewStartDateTime : Time.Zone -> Int -> Html.Html Msg
viewStartDateTime currZone startDateStamp = 
let
    timePosix = Time.millisToPosix startDateStamp

    day = Time.toDay currZone timePosix
    year = Time.toYear currZone timePosix
    mon = monthAsStr (Time.toMonth currZone timePosix)

    hour = Time.toHour currZone timePosix
    mins = Time.toMinute currZone timePosix

    dateRepr = Debug.log "dateRepr" (mon ++ " " ++ (String.fromInt day) ++ ", " ++ (String.fromInt year))  --- This has the correct value.
    timeRepr = (String.fromInt hour) ++ ":" ++ (String.fromInt mins)
in

Html.div 
    [ A.class "row" ]
    [ Html.div 
        [ A.class "col s9"]
        [ viewLineHeader "Start Date and Time"

        , Html.br [][]

        , Keyed.node "div"
                        []
                        [ viewStartDate dateRepr
                        , viewStartTime timeRepr]

        ]
    ]

viewStartDate : String -> (String, Html.Html Msg)
viewStartDate dateRepr = 
    ("startDate"
    , Html.input 
        [ A.type_ "text"
        , A.placeholder "Start Date"
        , A.class "col s3 start-datepicker"
        , A.id "start-date"
        , A.style "margin-right" "2em"
        , A.style "text-align" "right"

        , A.value dateRepr
        ]
        []
    )

viewStartTime : String -> (String, Html.Html Msg)
viewStartTime timeRepr = 
    ("startHrMin"
    , Html.input 
        [ A.type_ "text"
        , A.placeholder "Start Time"
        , A.class "col s3 start-timepicker"
        , A.id "start-hr-min"
        , A.value timeRepr
        -- , Evts.on "blur" (JD.map UpdateDispname Evts.targetValue)
        ]
        []
    )

elm_incorrect_value_updatevalue_dateRepr_in_console

1 Like

It would be nice to have the example as an Ellie file, I’m really having trouble debugging this just from the code snippet you provided.

Hello Lucas,

I have created an Ellie file here https://ellie-app.com/5Zh5ZrhpgPBa1

It is giving me uncaught reference error saying the Elm is not defined. But the code compiles fine on my end.

I don’t know how to include Elm in Ellie, since it does not have the reference to compiled JS code. But other than that all the relevant parts are in this Ellie. I hope you or someone can help.

This particular problem is because of elm/time and ellie running in debug mode.

There’s a compiler bug that’s causing this issue, and isn’t that easy to get around currently.

I’l try to take a look at it offline and see if that helps.

Thank you @Libbum. That would be helpful.

This is a tough one, not really sure what it is at the moment.

What I can say however, for those who want to pick this apart, is that the port callback in the startTimeOptions onSelect method triggers the issue, regardless of whether that event does something or not.

For example, I created a new port:

port newtime : (( Int, Int ) -> msg) -> Sub msg

Msg =
         ...
         | UpdateTime ( Int, Int )

Sub.batch
         [ startdatesub StartDateHrMin
         , newtime UpdateTime
         ]

update model msg =
         ...
         UpdateTime ( hr, min ) ->
               ( model, Cmd.none )

And now the javascript side looks like:

var startTimeOptions = {
   autoClose: true,
   twelveHour: false,
   onSelect: function(hr, min) {
      app.ports.newtime.send([hr, min]);
   }
};

This triggers the datepickers odd change to the display, but the values on the Elm side aren’t altered at all.
Commenting out the app.ports call doesn’t change the display. Of course it also doesn’t update the Elm model either.

My best guess from here is that the fact that the input blocks are Keyed, and materialize.js seems to like selecting all elements, there is a fight between the two inputs that is fired when the Elm runtime call the port. Exactly how to fix that though - no idea at the moment.

Perhaps separate the time and date pickers entirely? Store a date int and a time int rather than storing them in the one value as you do currently?

Thank you very much for looking into this @Libbum. I have been thinking of work-arounds and one thing I thought was to try and separate them as you suggested.

Another possibility is to let the JS side handle all the display for this element (not changing the input value) attribute from Elm. For this possibility, I would like to send the initial timestamp from Elm to JS, which can then handle the display (and send any updated value back to Elm just to store in the Model). However, I am having some issues sending the initial value (written in a question here.

In short, I think when the Elm sends the initial timestamp, the JS is not yet ready to receive it. If I send it with some time delay after the page loads, things work. But instead of adding an arbitrary time delay (which may or may not work), is there a DOMContentLoaded or DOM ready event on Elm that I can use to send the value? Thank you again for taking to look at this.

1 Like

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