Передать обработчик событий из elm в JS через порт - PullRequest
2 голосов
/ 30 июня 2019

В JS у нас есть такая функция:

const handleClick = event => {
  event.preventDefault();
  // some more code
}

<button onClick={this.handleClick}>Add to bag</button>

Код моего вяза:

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>

Пока я могу получить значение params, но не знаю, как передать обработчик событий (например, event в коде JS) из файла Elm в JS через port (передать это значение в btnSelector), так что я могу использовать это значение для старого кода. Кто-нибудь может мне помочь?

Большое спасибо!

1 Ответ

2 голосов
/ 03 июля 2019

Вы можете извлечь полный объект события как Value и передать его через порт.

port toJS : Value -> Cmd msg

onClickWithValue : (Value -> msg) -> Attribute msg 
onClickWithValue toMsg =
    on "click" (Json.map toMsg Json.value)

и в update есть что-то вроде

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        SomeTag value ->
            ( { model | count = model.count + 1 }, toJS value )

в примечании, если значения, которые вы передаете в JS, являются базовыми (Bool, Int, Float, String, Maybe, Json.Decode.Value и List, Array, кортежи или записи предыдущих типов), вы можете просто передайте их как запись. Итак, в вашем случае вы можете иметь:

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 ) )
...