2016-08-05 56 views
2

我是榆樹新手,我真的很喜歡它,但我遇到了一個問題,我似乎無法將我的頭圍繞。變換Html DOM

我有一個HTML DOM,例如

div [] 
    [ h1 [] [text "Headline 1"] 
    , p [] [text "Some text"] 
    , h2 [] [text "Headline 2"] 
    ] 

我想增加一個鏈接各自爲H內[1-6]元件等將其轉換爲類似的信息(保持簡單)

div [] 
    [ h1 [] [ text "Headline 1" 
      , [a [name "headline"] [text "#"] 
      ] 
    , p [] [text "Some text"] 
    , h2 [] [text "Headline 2" 
      , [a [name "headline"] [text "#"] 
      ] 
    ] 

這在概念上不是很難。查看DOM,如果元素是h [1-6],則添加一個a-link作爲子元素。然而,我對榆樹的理解並不足以讓它起作用。

這是我一直在嘗試到目前爲止。

transform : Html a -> Html a 
transform node = 
    -- check if the tag is h1-h6 
    case node.tag of 
     -- add a-link to h1 children 
     "h1" -> { node | children = (a [name "headline"] [text "#") :: node.children } 
     "h2" -> { node | children = (a [name "headline"] [text "#") :: node.children } 
     -- do this for all nodes in the tree 
     _ -> { node | children = List.map transform node.children } 

這是行不通的。

The type annotation for `transform` does not match its definition. 

40| transform : Html a -> Html a 
       ^^^^^^^^^^^^^^^^ 
The type annotation is saying: 

    VirtualDom.Node a -> VirtualDom.Node a 

But I am inferring that the definition has this type: 

    { b | tag : String, children : List (Html a) } 
    -> { b | children : List (Html a), tag : String } 

我明白,我不能這樣做,因爲node.tag泛型類型a可能沒有那場。它不是安全的。例如,文本節點沒有標記字段,但仍是Html.Html a的實例。

> text "Hello World" 
{ type = "text", text = "Hello World" } : Html.Html a 

我的問題是,我該怎麼做?我可以這樣做嗎?或者我不應該這樣做?

回答

2

不可能修改Html msg類型的現有值。

它們是最終的內部結構,它們被Virtual DOM作爲程序的輸出呈現給實際的HTML節點。

Html msgVirtualDom.Node a

您正在嘗試使用它們作爲記錄的別名,但是這只是一個JavaScript對象。

榆樹REPL輸出這兒抽象數據結構的字符串介紹:

> text "Hello World" 
{ type = "text", text = "Hello World" } : Html.Html a -- not a record 

而是試圖改變Html msg -> Html msg的,你應該嘗試這樣的:

-- Input example: [ "#", "http://google.com/", "http://package.elm-lang.org/" ] 

linksView : List String -> Html msg 
linksView links = 
    links 
     |> List.map (\link -> a [ href link ] [ text link ]) 
     |> div [] -- Expected output: <div> with thre links 
+0

我懷疑產量的JavaScript。我的「Html msg」來自Markdown的輸出。toHtml',所以在從Markdown.toHtml返回'Html msg'之前,我沒有任何好的方法來處理它。太糟糕了,它不可能改變輸出。 –

1

在榆樹,Html a是真的僅作爲輸出有用。你永遠不會以你的transform函數嘗試的方式將它用作輸入。

通過創建一個模型來描述您的域名,然後將其傳遞給view函數來呈現html,將會更好地爲您服務。然後

type alias Article = 
    { priority : Priority 
    , headline : String 
    , body : String 
    } 

type alias Model = 
    List Article 

type Priority = First | Second 

你的看法可能是這個樣子:

view : Model -> Html msg 
view = 
    div [] << List.map viewArticle 

viewArticle : Article -> Html msg 
viewArticle article = 
    let 
    priorityTag = 
     case article.priority of 
     First -> h1 
     Second -> h2 
    in 
    div [] 
     [ priorityTag [] 
     [ text article.headline 
     , a [ name "headline" ] [ text "#" ] 
     ] 
     , p [] [ text article.body ] 
     ] 
+0

正如我對halfzebra所評論的,我有降價內容,我用'Markdown.toHtml'轉換爲'Html msg'。我不希望鏈接在我的降價內容中,顯然無法轉換「Markdown.toHtml」的輸出以添加鏈接。這是一個恥辱。 –

+0

哎呀。我打算推薦擴展Markdown庫,但顯然這只是JavaScript庫中的一個包裝器https://github.com/chjj/marked –

+0

@Mikael Lundin您可以在將Markdown傳遞給Markdown.toHtml之前以編程方式增加Markdown嗎? –