Javascript 如何告诉elm有关外部DOM更改的信息

Javascript 如何告诉elm有关外部DOM更改的信息,javascript,interop,select2,elm,Javascript,Interop,Select2,Elm,我正在使用elm 0.17.1并尝试与select2 javascript库(版本4.0.3)进行互操作,下面是我的Main.elm: port module Main exposing (..) import Html exposing (Html,select,option,div,text,br) import Html.App as App import Html.Attributes exposing (id,value,width) -- MODEL type alias Mod

我正在使用elm 0.17.1并尝试与select2 javascript库(版本4.0.3)进行互操作,下面是我的Main.elm:

port module Main exposing (..)

import Html exposing (Html,select,option,div,text,br)
import Html.App as App
import Html.Attributes exposing (id,value,width)
-- MODEL

type alias Model =
  {
     country : String
  }


-- UPDATE

type Msg =
      Select String

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    Select str -> (Model str,Cmd.none)


-- VIEW

view : Model -> Html Msg
view model =
  div[]
  [
    select [id "myselect"]
    [
     option [value "US"] [text "United States"],
     option [value "UK"] [text "United Kingdom"]
    ],
    text model.country
  ]

-- SUBSCRIPTIONS

port selection : (String -> msg) -> Sub msg

subscriptions : Model -> Sub Msg
subscriptions _=
  selection Select


port issueselect2 : String -> Cmd msg

-- INIT

init : (Model, Cmd Msg)
init =
  ({country=""},issueselect2 "myselect")

main : Program Never
main = App.program {init=init,view=view,update=update,subscriptions=subscriptions}
javascript方面:

$(document).ready(function()
     {
        var app=Elm.Main.fullscreen();
        app.ports.issueselect2.subscribe(function(id)
        {
           $('#'+id).select2().on('change',function(e)
           {
              app.ports.selection.send(e.target.value);
           });
        })
     })
现在,当我选择一个国家/地区时,chromium控制台中会出现一个未捕获类型的错误,表示
domNode.replaceData
不是一个函数(它实际上未定义)

问题是select2向DOM添加了一个span,而Elm不知道,检查
domNode
会发现Elm在应该更新文本时尝试更新
span

我想我需要效果,但我不知道如何在我的特定用例中使用它们

如何解决我的问题

对于使用jquery 3的记录,我将我的elm程序编译成main.js,然后按照以下顺序加载js文件:jquery.min.js,选择2.min.js,main.js,然后是上面的js代码


我无法用elm reactor调试它,因为它似乎只适用于elm代码而不是js代码。

为了解决这个问题,我演示了将任何第三方JavaScript技术集成到elm应用程序中的所有核心思想

规则如下:

  • 让Elm拥有这个州
  • 不要变异由Elm's生成的DOM 看法
  • 如果Elm应用程序控制 初始化逻辑
  • 使用端口初始化和控制第三方代码
示例中的关注点:

  • -在JavaScript中设置端口订阅并选择2引导代码

  • -拥有select2的配置并订阅更改

该视图为所有jQuery魔术提供了一个容器:

view : Model -> Html Msg
view model =
    div []
        [ text (toString model)
        , div [ id "select2-container" ] [] -- The container, where select2 will live
        ]

非常欢迎任何反馈,如果您能告诉我缺少什么,我愿意改进这个答案。

我认为,要让它发挥作用,即使不是不可能,也是很困难的。Elm的虚拟DOM假定真实DOM始终同步。选择2会破坏此功能。也许在Elm中只管理选择列表的数据更好:在模型中保留选择的国家和选项列表。使用ap端口将选项发送到JavaScript,在JavaScript land中呈现
s,进行select2改造,然后将所选选项发送回Elm。