hi all,
i am learning elm and on the port program example.
i understand it but now want to send json data through the port instead of strings.
i am however confused about how to change the update function as well as change the general model from a list of strings to a list of JSON objects.
this is the paste of the code
this is the format of the model
-- MODEL
type alias Model =
{ draft : String
, messages : List Quote
}
type alias Quote =
{ quote : String
, source : String
, author : String
, year : Int
}
is this correct??
also is there a way to output debugging data to the elm console.
like a debug of the model in the view code.
thanks.
Debugging
In reverse order, you can log debug info with Debug.log "some label msg" data, e.g. you could in your view code write something like
view model =
let
_ = Debug.log "my model" model
in
and in your browser dev tools console you’ll see
my model <your model data>
Ports
To send JSON through ports you’ll first want to install elm/json, i.e. elm install elm/json. Then you can write
import Json.Decode
import Json.Encode
port fromElm : Json.Encode.Value -> Cmd msg
port toElm : (Json.Encode.Value -> msg) -> Sub msg
-- example usage
init : () -> ( Model, Cmd Msg )
init () =
let
initModel = { listStr = [ "hello", "world" ] }
in
( initModel
, fromElm (Json.Encode.list Json.Encode.string initModel.listStr)
)
subscriptions : Model -> Sub Msg
subscriptions model =
toElm SomeMsg decodeValue
decodeValue : Json.Decode.Decoder SomeValue
decodeValue =
-- implement decoder here for your value
Your decoder does look great btw!
@wolfadex thanks!!.
will implement the changes and get back to you.
hi,
@wolfadex i have made some progress but running into some errors.
this is the new code.
but i am getting some errors when i try to run the code.
find below
-- TYPE MISMATCH .../PortTest.elm
The 1st argument to `messageReceiver` is not what I expect:
85| subscriptions model = messageReceiver quoteDecoder
^^^^^^^^^^^^
This `quoteDecoder` value is a:
Decoder msg
But `messageReceiver` needs the 1st argument to be:
Json.Encode.Value -> msg
-- TYPE MISMATCH .../PortTest.elm
Something is off with the body of the `quoteDecoder` definition:
106|> map4 Quote
107|> (field "quote" string)
108|> (field "source" string)
109|> (field "author" string)
110|> (field "year" int)
This `map4` call produces:
Decoder Quote
But the type annotation on `quoteDecoder` says it should be:
Decoder msg
seems the issue is from the quotedecoder function.
i tried changing the type signature of the quotedecoder from
quoteDecoder : Json.Decode.Decoder msg
to
quoteDecoder : Json.Decode.Decoder Quote
but got a different error
-- TYPE MISMATCH /opt/erlang/monitor_erl/monitor_erl_elm/elm_test_project/src/PortTest.elm
The 1st argument to `messageReceiver` is not what I expect:
85| subscriptions model = messageReceiver quoteDecoder
^^^^^^^^^^^^
This `quoteDecoder` value is a:
Decoder Quote
But `messageReceiver` needs the 1st argument to be:
Json.Encode.Value -> msg
any ideas.
thanks!!
Nice work! Looks like maybe there was a slight miscommunication between us. Your decoder should be Json.Decode.Decoder Quote and then you’ll want subscriptions model = messageReceiver Recv quoteDecoder. Hopefully that helps. If not, let me know!
thanks for the hints!.
tried it and now getting this error in the code
-- TYPE MISMATCH .../PortTest.elm
The 1st argument to `messageReceiver` is not what I expect:
85| subscriptions model = messageReceiver Recv quoteDecoder
^^^^
This `Recv` value is a:
Quote -> Msg
But `messageReceiver` needs the 1st argument to be:
Json.Encode.Value -> msg
-- TOO MANY ARGS /opt/erlang/monitor_erl/monitor_erl_elm/elm_test_project/src/PortTest.elm
The `messageReceiver` function expects 1 argument, but it got 2 instead.
85| subscriptions model = messageReceiver Recv quoteDecoder
^^^^^^^^^^^^^^^
Are there any missing commas? Or missing parentheses?
this is the new paste of the code.
do i need to change the signature/body of the quoteDecoder function from
quoteDecoder : Json.Decode.Decoder Quote
to something else.
thanks for help!!.
I’m so sorry! I was writing that example without actually testing it. Here is an Ellie with the fixed subscription https://ellie-app.com/mx5dmWvzSp9a1. Again, sorry for not testing my example first.
@wolfadex thanks!!.
its finally get it working thanks to the changes.
hooked it up to the web-socket js code using JavaScript and all is well.
the data is coming in from the server through the websocket and i am able to process it on the elm side.
is there some sort of way to view the flow of types through the elm code and how it transforms from as it gets to one function then another.
i get the feeling it will get easier to see as i do more stuff in elm.
is there a way to make the map4 function accept other data types or combinations of data types in the quoteDecoder function.
anyway thanks again!!.
is there some sort of way to view the flow of types through the elm code and how it transforms from as it gets to one function then another.
If you compile in debug mode (if you’re using just the Elm cli then you’d add --debug like elm make src/Main.elm --debug --output=elm.js) then you can click on the blue debug button in the bottom right of the screen and you’ll be able to see every Msg that gets sent to your update function as well as the new value of your Model after that Msg has been processed.
You can also add Debug.logs to your code. E.g. if I have a List Int and I wanted to log intermediate values I could do something like
[ 3, 6, 2, 8 ]
|> Debug.log "initial value"
|> List.sort
|> Debug.log "sorted"
|> List.filter (\n -> modBy 2 n == 0)
|> Debug.log "odds filtered out"
and I could view those logs in the browser dev tools.
is there a way to make the map4 function accept other data types or combinations of data types in the quoteDecoder function.
Yes, though an example of what you’re trying to decode might help. The Json.Decode.oneOf might be useful, though it depends on what you’re trying to decode.
I will try the debug mode out and learn some stuff from there and the decoder also.
for the decoder i need to make the integer value float instead of an int.
so the part of the model which is an int will need to be changed to a float.
quoteDecoder : Json.Decode.Decoder Transaction
quoteDecoder =
map4 Transaction
(field "responsecode" string)
(field "time" string)
(field "tname" string)
(field "amount" int)
can become
quoteDecoder : Json.Decode.Decoder Transaction
quoteDecoder =
map4 Transaction
(field "responsecode" string)
(field "time" string)
(field "tname" string)
(field "amount" **float**)
thanks a lot for your help !!.