LexiFi / ocaml-vdom

Elm architecture and (V)DOM for OCaml
MIT License
197 stars 13 forks source link

how do i add new elements and attributes? #4

Closed martindemello closed 7 years ago

martindemello commented 7 years ago

I'm trying to add an SVG rectangle element:

module Svg = struct
  let svg ?key ?a l = elt "svg" ?key ?a l 
  let rect ?key ?a l = elt "rect" ?key ?a l

  let a_class xs = class_ (String.concat " " xs) 

  let px_prop k v = str_prop k (sprintf "%fpx" v)
  let a_width  = px_prop "width"
  let a_height = px_prop "height"
  let a_x = px_prop "x" 
  let a_y = px_prop "y" 
end

type model = { 
  size : float;
}

type action = Foo | Bar 

let init = return { size = 42.0 }

let update model (action : action) = return model

let view model =
  let open Svg in
  div [
     svg ~a:[a_width 600.0; a_height 600.0]
       [ rect ~a:[a_class ["hello"; "world"];
                  a_x 100.0; a_y 100.0;
                  a_height model.size; a_width model.size] []
       ]   
  ]

but the rendered HTML only contains the existing class_ attribute:

<div><svg><rect class="hello world"></rect></svg></div>

the other attributes I tried to add via str_prop get silently dropped.

alainfrisch commented 7 years ago

(Side note: How do you look at the generated HTML? The library creates DOM nodes and set DOM properties, not HTML attributes. It would not be very difficult to support setting attributes if needed, but most attributes have some property counterpart (sometimes with a different name), so I'm not sure this is strictly required.)

I suspect the problem is related to the fact that one should use createElementNS with the correct SVG namespace to create SVG elements, while the library currently always use createElement (which is fine for HTML elements). The namespace should be an extra argument to the elt "constructor" (taken into account when comparing tags during vdom synchronization), or perhaps one could encode it as part of the tag itself (e.g. "namespace:local_name" to avoid comparing two strings during the diffing).

alainfrisch commented 7 years ago

So it seems that SVG attributes really need to be handled as attributes, there is no corresponding DOM properties as for (most) HTML attributes.

martindemello commented 7 years ago

you're right, it's technically the generated DOM rather than the generated HTML. i view it in chrome by calling "inspect" from the right-click menu.

does your second comment mean that svg is currently not supported? i'd offer to help add it but i didn't even know dom properties and attributes were different things, so i suspect i wouldn't get very far :)

alainfrisch commented 7 years ago

My previous comments indeed meant that SVG was not supported at the time they were written. Now, it is (since the last commit one minute ago).

martindemello commented 7 years ago

that was fast! thanks for the quick fix.