Reputation: 13
I am using a port to pass an object from javascript to elm, and I want to update my model based on the value received from JS. Heres my code:
type alias Model = { x: String, y: String }
type Action = Received { x: String, y: String }
update : Action -> Model -> Model
update action model =
case action of
Received rec -> { model | x = rec.x, y = rec.y }
port rec : Signal { x: String, y: String }
result = Signal.map update (Received rec)
However, I get a type mismatch compiler error on the last line, saying that update
is receiving an argument of type Signal { x: String, y: String }
when it should be receiving { x: String, y: String }
Upvotes: 1
Views: 324
Reputation: 1207
So it looks like what you'd like to do is go from a Signal of incoming records from your port to a Signal of the current state of your model. There was mention of foldp
in the comments, and it'll come into play so I'll be sure to address it. In order to get a Signal of the current model state from your port, this is what your code could look like:
initialModel : Model
initialModel =
{ x = "0"
, y = "0"
}
result : Signal Model
result =
rec
|> Signal.map Received
|> Signal.foldp update initialModel
Let's go over this one step at a time now.
initialModel : Model
initialModel =
{ x = "0"
, y = "0"
}
With this assignment we set up an initial state from which to proceed. Elm's Signals must always have an initial value, regardless of whether that initial value is relevant to your program. If you don't care what your initial model is, you can assign the record's fields to be whatever you'd like.
result : Signal Model
result =
rec
|> Signal.map Received
-- ...
Here we use Signal.map to go from the { x : String, y : String }
records coming from your port to a Signal of Action
s, namely, the Recieved
action. So at this stage we have a Signal Action
.
|> Signal.foldp update initialModel
In this final step we take that Signal Action
from the previous step and fold it into the previous model with Signal.foldp
. The first argument is a function that accepts some type a
representing incoming new values from another Signal (in this case it's our Signal Action
), and the last available value of our state (which is initialModel
at the outset and then the last return value of update
going forward) and returns the next state. This is how any statefulness is acquired in an Elm application.
result
ends up as the Signal for the most recent incarnation of the application's model, which you can then map on to a Signal of Html
or Graphics.Element
or whatever you'd like using Signal.map
again in order to produce some user interface that reacts to updates in your application.
Upvotes: 1