In JS we have a function like this:
const handleClick = event => {
event.preventDefault();
// some more code
}
<button onClick={this.handleClick}>Add to bag</button>
My Elm code:
main.elm
port addToBag : Value -> Cmd msg
type Msg
= ClickBag Item
update msg model =
case msg of
ClickBag item ->
let
data =
Encode.object
[ ("price", Encode.string item.price)
, ("sku", Encode.string item.sku)
]
in
( model, addToBag data )
view model =
button [onClick ClickBag model.item] [text "Add to bag"]
index.html
<div id="elm"></div>
<script type="text/javascript">
const addToBag = (params, btnSelector = null) => {
console.log('json data', params)
}
const ElmApp = Elm.Main.init(document.getElementById('elm'))
ElmApp.ports.addToBag.subscribe(addToBag)
</script>
For now, I can get the params
value but don't know how to pass the event handler(like event
in JS code) from Elm file to JS through port
(pass that value to btnSelector
),
so I can use that value for the legacy code. Anyone can help me?
Thanks a lot!
You can extract the full event object as a Value
and pass that through the port.
port toJS : Value -> Cmd msg
onClickWithValue : (Value -> msg) -> Attribute msg
onClickWithValue toMsg =
on "click" (Json.map toMsg Json.value)
and in update
have something like
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
SomeTag value ->
( { model | count = model.count + 1 }, toJS value )
on a side note, if the values you pass to JS are basic values (Bool, Int, Float, String, Maybe, Json.Decode.Value and List, Array, tuples or records of the previous types) , you can just pass them as a record. So, in your case, you can have:
type alias Item =
{ price: String
, sku: String
}
port addToBag : (Item, Value) -> Cmd msg
type Msg
= ClickBag Item Value
view model =
button [onClickWithValue (ClickBag model.item)] [text "Add to bag"]
update msg model =
case msg of
ClickBag item value ->
( model, addToBag ( item, value ) )