A virtual DOM implementation that backs Elm's core libraries for HTML and SVG. You should almost certainly use those higher-level libraries directly.
It is pretty fast! You can read about that here.
The foundation of HTML and SVG in Elm.
Home Page: https://package.elm-lang.org/packages/elm/virtual-dom/latest
License: BSD 3-Clause "New" or "Revised" License
Given this code, it seems as though if you supply multiple event handlers with the same key in a list of properties, all but one will be clobbered.
https://github.com/elm-lang/virtual-dom/blob/master/src/Native/VirtualDom.js#L130-L135
if (key === ATTR_KEY || key === ATTR_NS_KEY || key === EVENT_KEY)
{
var subFacts = facts[key] || {};
subFacts[entry.realKey] = entry.value;
facts[key] = subFacts;
}
In theory, it would seem possible to do something sensible with multiple event handlers -- i.e. install each of them.
Now, it is, of course, possible -- and, indeed, often preferable -- for the event handlers to be "combined" at a higher level, and provided to VirtualDom
as a single handler. So, if the intention is to force that to happen, then this would not be a bug.
This example renders the same list of numbers twice; once using node
and once using keyedNode
. There are buttons to let you select one of two orderings for the list. Initially, both node
and keyedNode
render the list the same, but when you click the second button to change the order, you see that keyedNode
renders the list in the wrong order.
So, today I was creating a flex layout using elm, and turn out that, for flex to work, alot of divs in the three should have flex, so I found myself editing a lot of places and realized there is no way to mutate a Node.
For example, if I want a component renders a div and want to add some styles to that div in diferent contexts, I cant easily. So most of the time I found myself passing styles and children as parameters to my functions just to be able to extend it somewhere, cluttering with empty lists the places where no customization is needed, so I realized:
Why not being able to transform the Node data structure? Maybe with functions like:
addProperty : Property msg -> Node msg -> Node msg
changeProperty : (String msg -> String msg) -> String msg -> Node msg -> Node msg
addStyles : List (String msg, String msg) -> Node msg -> Node msg
It would be really easier to deal with those things without having to add a lot of parameters when there is no need to and without having to create a big DOM tree
What do you guys think?
Maybe I can try to make that work and submit a PR if people are interested in it.
I'm wanting to write an 0.18.0 Elm program and run it in a JavaFX WebView. When trying the first example from the Elm Architecture Tutorial (01-button.elm), the HTML is drawn correctly, but then when I hit e.g. the "+" button nothing happens (it's meant to update the counter). By adding Debug.log statements, I can see after hitting the button that update runs, but not the subsequent view.
I've tried running the latest version of Java 8 (1.8.0_112), as well as a few older versions all the way back to 1.8.0_51. They all exhibit the same behaviour. No errors are reported by the WebView or it's associated WebEngine.
The HTML file as produced by elm-make works just fine in all major browsers, as you'd expect. I've tried to look for which browser versions are supported by Elm, but can't find that information.
WebView is based on WebKit (in Java 1.8.0_122 it's WebKit 602.1) - is it supported in Elm?
The below creates the test case in JavaFX:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class WebViewPane extends Application {
@Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
WebView webView = new WebView();
WebEngine webEngine = webView.getEngine();
webEngine.load("http://localhost:5000/01-button.html");
root.getChildren().add(webView);
Scene scene = new Scene(root);
primaryStage.setTitle("WebView");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Thanks!
Windows 7
Chrome 54.0.2840.71
I see the following in the Chrome console after clearing the text from a contenteditable True
DIV. An example that reproduces the problem is included at the bottom of this comment.
which points to the following snippet from applyPatch
:
function applyPatch(domNode, patch)
{
switch (patch.type)
{
case 'p-redraw':
return applyPatchRedraw(domNode, patch.data, patch.eventNode);
case 'p-facts':
applyFacts(domNode, patch.eventNode, patch.data);
return domNode;
case 'p-text':
domNode.replaceData(0, domNode.length, patch.data);
return domNode;
Clear the text in either DIV to reproduce the error.
{-| This code reproduces the error in issue https://github.com/elm-lang/virtual-dom/issues/48 -}
import Html exposing (text)
import Html.App as App
import Html.Attributes exposing (contenteditable)
import Html.Events exposing (on)
import Json.Decode as Json
type Msg = HelloUpdate String | WorldUpdate String
update msg model =
case msg of
HelloUpdate txt ->
( { model | hello = txt }, Cmd.none )
WorldUpdate txt ->
( { model | world = txt }, Cmd.none )
initModel =
{ hello = "hello"
, world = "world"
}
view model =
Html.div
[]
[ Html.div
[ contenteditable True
, onInput HelloUpdate
]
[ text model.hello ]
, Html.div
[ contenteditable True
, onInput WorldUpdate
]
[ text model.world ]
]
onInput msg =
on "input" (Json.map msg innerHtmlDecoder)
innerHtmlDecoder =
Json.at ["target", "innerHTML"] Json.string
main =
App.program
{ init = (initModel, Cmd.none)
, update = update
, view = view
, subscriptions = (\_ -> Sub.none)
}
In particular case, elm-make --debug
generates invalid JavaScript. It causes a runtime error.
Uncaught TypeError: Cannot read property 'nativeBinding' of undefined
This is because _elm_lang$virtual_dom$Native_Debug
tries to use _elm_lang$core$Native_Scheduler
before initialization. This order seems to change according to the user name.
This is NG case. (user name = ell
)
{
"version": "1.0.0",
"summary": "helpful summary of your project, less than 80 characters",
"repository": "https://github.com/ell/project.git",
"license": "BSD3",
"source-directories": [
"."
],
"exposed-modules": [],
"dependencies": {
"elm-lang/core": "5.0.0 <= v < 6.0.0",
"elm-lang/html": "2.0.0 <= v < 3.0.0"
},
"elm-version": "0.18.0 <= v < 0.19.0"
}
... and this is OK. (user name = eln
)
{
"version": "1.0.0",
"summary": "helpful summary of your project, less than 80 characters",
"repository": "https://github.com/eln/project.git",
"license": "BSD3",
"source-directories": [
"."
],
"exposed-modules": [],
"dependencies": {
"elm-lang/core": "5.0.0 <= v < 6.0.0",
"elm-lang/html": "2.0.0 <= v < 3.0.0"
},
"elm-version": "0.18.0 <= v < 0.19.0"
}
Looks like if the user name is before elm-lang
the debugger crashes.
To be worse, if this module is published, the project that depends on it cannot use debugger either. I'm using elm-community/elm-material-icons
and ran into this.
Using nested tagger result in either an exception or the wrong domnode being modified
Patch indices are collapsed for nested tagger in diffHelp but not in addDomNodesHelp
import Html exposing (div, text, button)
import Html.App exposing (beginnerProgram, map)
import Html.Events exposing (onClick)
main =
beginnerProgram
{ model = Page1
, view = view
, update = update
}
type Page
= Page1
| Page2
view model =
case model of
Page1 ->
div []
[ div []
[ button [ onClick Click ] [ text "change page" ] ]
, text "page 1"
]
|> map (always (always IntermediateMsg))
|> map (always (ChangePage Page2))
Page2 ->
div []
[ button [ onClick Click ] [ text "change page" ]
, text "page 2"
]
|> map (always (always IntermediateMsg))
|> map (always (ChangePage Page1))
type Msg
= ChangePage Page
type IntermediateMsg
= IntermediateMsg
type SubMsg
= Click
update msg model =
case msg of
ChangePage page ->
page
A todo app is displaying a list of active todos. Click on a checkbox to mark it as complete, the todo is removed from the list, but the item below it is now checked but should be unchecked. Here's a short example which can be pasted into http://elm-lang.org/try to see the problem behavior: https://gist.github.com/dtsao/cf9544eeab85efbbb7157cabef71eaad
(I'm pretty new to Elm, so this may be a coding bug on my part.)
It doesn't look like elm diffs text when I call requestAnimationFrame
from a port and the next view's dom is the same structure.
For example, If I try rendering example
then use a port that calls requestAnimationFrame
then
change the view to broke
it'll keep all the text from example
and just add the new text.
example : Model -> Html Msg
example model =
pre [ onClick (Next Broke), id "elm" ]
[ code []
[ text """
module Main exposing (..)
import Html exposing (Html, div, text)
main : Html a
main =
"""
]
]
broke model =
pre [ onClick (Next StepBack), id "elm" ]
[ code []
[ text """
module Main exposing (..)
import Html exposing (Html, div, text)
main : Html a
main =
div [] [ text "Hello, World" ]
"""
]
]
An example of what it looks like in an app:
https://github.com/thecodethinker/elm-presentation/tree/broken
Sometimes its necessary to stopPropogation and preventDefault on certain events and not others. For instance it may be desired to restrict certain key-presses in a text-input field. Examples include:
Credit card entry, numbers and spaces
Phone numbers with international codes () and +
Hex editor, restrict to A-Z 0-5
and many more....
Currently Elm doesn't allow this behaviour because stopPropogation and preventDefault are specified at the time the event listener is registered, and before the event listener has received any events.
I suggest adding a new Options type, something like this:
type alias EventOptions = { stopPropagation : Json.Decoder Bool , preventDefault : Json.Decoder Bool }
and a companion method:
onWithEventOptions
This will allow stopPropogation and preventDefault flags to be based on the content of the event received.
Not sure if this is a bug or not, but depending on the code syntax, the resulting DOM is the same but not the mutations to render it.
Mostly, having Html.App.map
inside a Maybe.withDefault
will result on removing and adding a new node while having Maybe.withDefault
inside Html.App.map
will result on editing the node attributes and changing the text inside it.
Here is a repo reproducing the issue https://github.com/pauldijou/elm-dom-diff
IMO, since the final virtual DOM is the same, it should probably apply the same patch / mutation events.
Got the error above for this code: https://gist.github.com/gdotdesign/e5edb441a4be5d53841ad2b57ea6b21b
Once messages get a bit more complex than messages from simple examples, the restricted size of the sidebar makes their content unreadable.
Here's a screenshot of the debugger running in my app:
All those "MakeRequest" and "SaveAfter" messages have important content that, at the moment, I can't see unless I open the developer tools and inspect that HTML element, like so:
One approach to solving this issue might be making the sidebar resizable, as did @rtfeldman in #46.
Another idea, which could possibly offer better readability, would be inserting the selected message's information in the right-hand pane above the model. So each time I click on a message, I see that message's content displayed on the right hand side, and the state of the model at the time the message was intercepted.
I got the above error for this code: https://gist.github.com/gdotdesign/24926f96f1ad7f5b2af5a0189fe9111e
It's happening when lazy
function is any of the children, when debugging the patches
array seems empty.
This is just a question.
I don't understand this line:
type Node msg = Node
in virtual-dom.
I am not able to find any document on this also.
Can you answer the question and please update the document ( syntax part)
When using Html.Attributes.property
to set some properties, it doesn't work on the first render. The example property is scrollTop
, which has no effect on the first render, but works fine after the DOM node was inserted.
I'm reporting this here since elm-lang/html
isn't at fault, it just shows the problem easily.
I understand why this is happening – we're calling render
first, which calls applyFacts
, and only then inserting the node into the DOM. At the point when applyFacts
is called, the element doesn't overflow yet, so setting scrollTop
will have no effect and reset to 0
.
This can be further demonstrated for example by changing line 371 like so, which makes the example work on the initial render as well:
// for attributes that can and should be set before the node is inserted
applyFacts(domNode, eventNode, vNode.facts);
// for attributes that have to be set after the node is in the DOM
setTimeout(function() {
applyFacts(domNode, eventNode, vNode.facts);
}, 0);
Side note: More terrible things can be done with property
that totally break Elm, like property "innerHTML" (Json.string "borked!")
-- then the indexing of the nodes that actually should be inserted doesn't work anymore and Elm does odd things or breaks. I don't know what should be done with this, property
is an unsafe escape hatch anyways.
Still, I consider this to be a bug, as someone was just bitten by it in the #beginners channel on Slack and it takes a while to figure out why this is happening and I don't know how to work around it in plain Elm.
Many people have expressed interest in server-side rendering. For folks who do not know what that means, here are the basic facts that motivate it:
So server-side rendering means doing some additional setup work on the server. In practice this means,
The implementation should not be specific to node. People run lots of different kinds of servers, and this is useful with any of them.
I have a draft of VirtualDom
to HTML that has some nice properties. This will be the next large public project I work on. Remaining work includes:
elm-lang/core
and elm-lang/virtual-dom
aligned so that this functionality can be exposed appropriately.I think it is best to comment on this in a community forum. This issue is just intended to let people know what's up as of this writing.
The full state of my game is quite large and it can be difficult to see what's changed between messages if I didn't know what I was looking for. This isn't a problem most of the time because I know what to look for, but to aid in finding unexpected bugs, it would be great to show the change between two states as well as the full state dump.
This was actually mentioned in another issue: https://github.com/elm-lang/virtual-dom/issues/49#issuecomment-261569572 but I feel it deserves it's own place for discussion.
I was looking at this code, which is used while iterating through a list of properties:
https://github.com/elm-lang/virtual-dom/blob/master/src/Native/VirtualDom.js#L130-L135
if (key === ATTR_KEY || key === ATTR_NS_KEY || key === EVENT_KEY)
{
var subFacts = facts[key] || {};
subFacts[entry.realKey] = entry.value;
facts[key] = subFacts;
}
Now, it seems as though if you were to supply a list of properties with more than one attribute
with the same name, all but one of them would be clobbered. That seems reasonable -- what else are you going to do, after all?
However, it looks like this is also true if you supply more than one attributeNS
and they have the same name, but in a different namespace. In that case, the realKey
is the attribute name, and the namespace is part of the entry.value
. So, it looks as though an attributeNS
would clobber a previous attributeNS
with the same attribute name, even if they have different namespaces.
Of course, it is entirely possible that I'm misinterpreting this.
Also, if this is a bug, it seems that it probably would not be encountered often. It seems as though it would be unusual to need to supply two attributes which
But, I suppose it could happen.
Trying out lazy with this simple test case: https://gist.github.com/gdotdesign/6b79605e7f4e495e19f77930f61103e1 and running into the error above.
[Apologies if repeat or invalid bug or wrong repo]
The code at https://gist.github.com/maxf/efd173cf14a77f4af381cf8ad4c13a20 has a basic List String model and turns it into a ul with checkboxes for each string in the model, as so:
There's also a message that lets the user remove items by clicking the relevant checkbox. For instance, when clicking on the 3rd item, it removes "three" from the model and view renegerates the Html:
As you can see the 3rd checkbox is now ticked. But clearly shouldn't.
As reported by @pdamoc in https://github.com/elm-lang/html/issues/16 and further clarified by @debois.
import Html exposing (Html, button, div, text)
import Html.App as App
import Html.Events exposing (onClick)
main : Program Never
main =
App.beginnerProgram
{ model = 0
, update = always <| (+) 1
, view = view
}
view : Int -> Html ()
view model =
div
[]
[ text (toString model)
, button [ onClick () ] [ text "Inc" ]
]
|> App.map identity
|> App.map identity
Notes.
App.map
is necessary to trigger the error.text
(see below) suppresses the JS error, but causes updates to change the text on the left-most button instead of the text
element: [ button [ onClick () ] [ text "Inc" ]
, text (toString model)
, button [ onClick () ] [ text "Inc" ]
]
I'm currently missing something similar to document.createComment from Javascript.
Would be great if one could generate HTML comments using something similar like this:
Html.comment "comment begin",
Html.table [][],
Html.comment "comment end"
<!-- comment begin -->
<table></table>
<!-- comment end -->
I'm currently try to code an HTML e-mail template, and this would be very handy to support older e-mail clients 🙂 .
https://gist.github.com/colinmccabe/56abf3c8a602834401cac1933c38ba7f
The program above results in a TypeError: domNode.elm_event_node_ref is undefined
exception on this line: https://github.com/elm-lang/virtual-dom/blob/1.0.0/src/Native/VirtualDom.js#L914
It has something to do with this code that returns either a div or a table from a case and then (pointlessly) feeds the result into Html.App.map
.
view : Model -> Html.Html Msg
view model =
let html =
case model of
[] ->
Html.div [] [ Html.text "No items, displaying div with text" ]
xs ->
viewTable xs
in
Html.App.map (\_ -> NoOp) html
viewTable : Model -> Html.Html a
viewTable model =
Html.table ...
Removing the case so that html
is always a table or removing Html.App.map
makes the exception go away.
Interestingly, virtual-dom successfully renders the table on the first tick, and the exception occurs on the second tick.
In this example the tabindex 0 attribute stays on the element after beeing removed by clicking on the button.
Also some there is some wierd behavior
https://gist.github.com/gdotdesign/aa92bfa42c219e765eae65fa9ba6dbd4
While trying to reproduce an other bug I ran into this one: https://gist.github.com/gdotdesign/cc924f6e591efec979524fe643ee5c12, it renders fine at the first pass but after a change the style attribute gets removed.
Steps to reproduce
Expected behavior:
I used the latest version.
In the debugger, after I click on an event, there's no way to return to the app's "initial state" since there is no message that corresponds with that state.
Presently (as of 0.18), to use web components with Elm requires the full shadow DOM polyfill (or else child nodes aren't rendered in many cases). The Shadow DOM polyfill yields poor performance everywhere but Chrome.
This will hurt adoption of Web Components in Elm, but Web Components make it easier to move stateful UI bits out and seem to solve the elm-mdl ripple problem nicely.
I'd be interested in trying to help fix this issue, and just wanted to make sure that I could get some guidance or suggestions on whether the work would be in vain (i.e. if this problem is already on the radar / being worked on). Thoughts?
window.Polymer = { dom: 'shadow' }
) everything renders nicely but performance is poor in Firefox and Safari Mobile, at least.Here's a git repo reproducing the issue with polymer web components: knewter/elm_web_components_playground@72cdde0
it's not an SSCCE yet, but the view function itself is pretty easy to comprehend: https://github.com/knewter/elm_web_components_playground/blob/72cdde0e38030bf694fe1c85c229b2f049d72cce/src/App.elm#L36
If you open up src/index.html
and uncomment the shadow dom configuration, it works fine - but the shadow dom polyfill has poor performance everywhere but Chrome. If you open up the app in firefox and click the login button, you'll note that the ripple doesn't show up because firefox performs slowly with the full shadow dom polyfill. We have to use that polyfill at present, because otherwise we don't even render the app in this example!
Many projects simply cannot afford the Shadow DOM Polyfill, for the reasons given above. In particular, the performance costs on platforms like mobile Safari are nearly intolerable.
The above error is thrown in the following line in internet explorer 11 on Windows 7: https://github.com/elm-lang/virtual-dom/blob/1.1.1/src/Native/VirtualDom.js#L1306
The actual problem is that the elm_event_node_ref
is undefined. A SSCCE can be found here: https://gist.github.com/noobymatze/9b80606ccc69ad05e9b368b31532cc03
Typing any two letters into the rendered input element will result in the mentioned exception. Without opening the developer tools, nothing will happen. The typed text should be displayed right next to the input. Removing the App.map
in the view and changing the type of viewName
to Html Msg
will resolve that.
I am not sure about anything below IE 11, but IE Edge, Chrome, Firefox and Safari 5.1.7 (on Windows) and Opera seem all to be working fine.
With the change from 0.16 to 0.17, elm-lang/html
now depends on this repo which is not based on Matt-Esch/virtual-dom
anymore. The current implementation of this virtual DOM does not have support for hooks anymore: https://github.com/Matt-Esch/virtual-dom/blob/master/docs/hooks.md
The hooks allow us to invoke some Javascript once the VNode has been flushed to the DOM. This would include things like Leaflet markers on a Openstreet map, WYSIWYG editors, or whatever. That's the nice part, it gives us more fine-grained access to the DOM once we decide to go Native
for a piece of functionality.
Not having a way to know whether a VNode has been flushed to the DOM, causes us to write things like setTimeout(tryUntilElementVisible(var times = 5), 50)
etc. If it's about form inputs, you could use onFocus
, but that's not meant for non-form stuff. Sometimes you want to do something as soon as the element is visible, like attaching a WYSIWYG editor.
It would be nice if we could use "something" like hooks from Matt-Esch/virtual-dom. This is where the magic happens. It checks whether the property is a hook, and if so, it calls the prototype method hook
on it.
We could add a method Native.VirtualDom.hook
that adds a hook property to our VNode. This would allow us to opt into adding functionality once our element is flushed to the DOM, and it helps us to kill the pesky setTimeout
stuff we need to do otherwise.
Lets discuss!
Elm version: 0.18
Code:
import Html exposing (beginnerProgram, div, button, text)
import Html.Events exposing (onClick)
import Date
main =
beginnerProgram
{ model = Date.fromTime 1479238963
, view = view, update = update
}
view model =
div []
[ div [] [ model |> (Date.dayOfWeek >> toString) |> text ]
, button [ onClick (Increment model) ] [ text "+" ]
]
type Msg = Increment Date.Date
update msg model =
case msg of
Increment date ->
date
Steps to reproduce:
elm-make Main.elm --debug
Result:
The date from the import.json file is not deserialized and our model is now of type String instead of Date.
Edited by @evancz
The runtime behavior of justCirc
and symAndUse
is very different in the following code.
symAndUse
the browser is recalculating styles on every animation frame.justCirc
it does not do this.You can observe this by profiling the example with the Chrome timeline
import Html exposing (Html)
import Svg exposing (..)
import Svg.Attributes exposing (..)
import VirtualDom exposing (attributeNS)
import AnimationFrame
import Time exposing (Time)
-- PROBLEM
view : Model -> Html Msg
view model =
let
justCirc = [ circle [cx "50", cy "50", r "40", strokeWidth "8", stroke "red", fill "red"] [] ]
symAndUse =
[ symbol [id "sym01"] justCirc
, use [xlinkHref "#sym01", x "0", y "0", width "100", height "100"] []
]
in
svg [ viewBox "0 0 200 200", width "600px" ]
--justCirc
symAndUse
-- SETUP
main = Html.program { init = init, view = view, update = update, subscriptions = subscriptions }
type alias Model = Time
init : (Model, Cmd Msg)
init =
(0, Cmd.none)
type Msg = Tick Time
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
Tick newTime -> (0, Cmd.none)
subscriptions : Model -> Sub Msg
subscriptions model =
AnimationFrame.times Tick
Original Comment:
If you profile this example using the Chrome timeline, you can see that the browser is recalculating styles on every animation frame. Since the DOM isn't changing at all, this shouldn't be the case?
If you were to replace the last linesymAndUse
withjustCirc
, it does work as expected (no calculating restyles).
attributeNS
takes three parameters -- the namespace, the key and the value.
However, the documentation does not indicate which parameter is which.
Of course, one can read the native code to find out that the first parameter is the namespace, the second the key, and third the value. Also, it is probably the logical order for the parameters -- at least, it is the order I would have expected. Nevertheless, it might be helpful to some users to indicate in the documentation which parameter is which.
(Note that the documentation for attribute
also does not formally indicate which parameter is the key and which is the value. However, the documentation gives an example for attribute
which makes it pretty obvious).
onWithOptions
can be used to suppress the default keystroke events, but this is all or nothing for any key, where in javascript one could conditionally suppress defaults by key. This causes issues when trying to provide extra functionality around input
elements, say, a search box that raises a menu which is navigable with the Tab key.
Using onWithOptions
to suppress defaults in this scenario would require one to reimplement all of the features of the input element, otherwise the browser will move focus on the first Tab press and the widget will no longer receive those events.
A possible solution might be to allow a function parameter with on
which would return True
or False
based on a test against KeyCode
, maybe a new function like onWithKeyTest
.
This would also be nice with the global Keyboard.presses
and sibling subscriptions, but some kind of similiar test for subscriptions would need to be provided.
During last weeks I've been working on a app that initialize a map (leaflet) in a dom element created by a view function in elm. This has been working great. I wanted for elm to manage root dom element of the page and not to be embedded in a particular dom.
So far so good.
But after tidying things a little bit and using Html.App.map
in the view function, the virtual dom algorithm is unable to reuse the dom.
I've reduced as much as possible the sample in https://gist.github.com/bcardiff/d59fa6b70d4aa486534b485049c5be8e so it might look a bit cryptic . A #my-div
is mutated from JS, but there is always a #my-div
in the same location across life cycle of the application.
With the gist code, when rendering the view using Html.App.map
the #my-div
is recreated from scratch, loosing the previous mutation: http://g.recordit.co/GaF2HCbynG.gif
Oddly, if instead of using Html.App.map
the view is built directly with a wrapping a -> msg
function the problem goes away. That is, using https://gist.github.com/bcardiff/d59fa6b70d4aa486534b485049c5be8e#gistcomment-1887851 I got the expected behavior: http://g.recordit.co/Mflh3NmM6y.gif
Am I right in considering this a bug or is off the limits of the diff algorithm of virtual dom?
virutal-dom: 1.1.1
Not really a bug, only a thing I ran into by accident (and others might too 🙄 )
(using the --debug
flag for elm-make
in elm 0.18.0
):
When embedding an elm-app into a html page with no
<meta charset....
defined the debugger showed me â–¸
and â–¾
instead of ▸
and ▾
The fix was simply to specify
<meta charset="utf-8">
In the <head>
of the html document.
I apologize if this is not the right place to mention this and would ask for instructions/information on where to place/post this.
Currently line 14 of the LICENSE file:
In other elm-lang repos this line reads:
The latter is probably the intention.
Since there are contributors, but they are not mentioned here with name (and there is no CLA),
a file with contributors would be appropriate.
Seeing an odd behavior going through HTTP EXAMPLE in Elm guide.
Every time I click More Please!
the current gif resets before an update.
Seems like this is what happening:
onClick
produces MorePlease
messageupdate
receives MorePlease
and returns (model, getRandomGif model.topic)
, so it doesn't mutate model
view
should return unchanged VirtualDom.Node
compared to the previous stepimg
tag gets re-rendered anyway so gif gets resetIs it a bug in VirtualDom renderer? I thought it wasn't supposed to re-render elements if the model didn't change
OS: macOS Sierra Version 10.12.1 (16B2555)
Browser: Google Chrome Version 54.0.2840.98 (64-bit)
Elm: 0.18
Right know functions cannot be used in the Html.Lazy
bacause it throws a runtime error:
Equality error: general function equality is undecidable, and therefore, unsupported
To put this in context, consider the following example:
-- Component
type Msg
= Click
type alias Context msg =
{ mouseDownMsg : msg }
view : (Msg -> msg) -> Context msg -> Model -> Html.Html msg
view address context model =
div
[ onClick (address Click)
, onMouseDown context.mouseDownMsg
]
-- Parent
type Msg
= Component Component.Msg
| Click
view : Model -> Html.Html Msg
view model =
Component.view
Component
{ mouseDownMsg = Click }
model.component
This is a straightforward way of making components that can have messages from the parent or to have content that comes outside of them.
This is essentially the same as Signal.forwardTo
was, and the problem with that was that in every iteration a new function was created and made lazy useless, but in this case the generally functions are static and only created once.
This function comparison wasn't a problem in 0.16 because it was comparing identity not equality.
Having functions compared by identity is OK in my opinion, and it would solve this problem, however I understand the logic behind this change but having a cryptic runtime error is bad and it takes some time to find where it's coming from.
I can't find reference to any relevant changes in the rewrite which have resolved this issue: https://github.com/evancz/virtual-dom/issues/24
I wonder if a pleasant API for handling this scenario might be a function like this?
innerHtml : Html -> Attribute msg
Then you could define children as standard elm-lang/html elements, but under the hood, set the content of the contenteditable div using the DOM's Element.innerHTML
API, which will allow us to preserve the cursor position.
This happens when a node is inserted before the node that fired "mousedown" event.
SSCCE:
import Html exposing (div, text)
import Html.App exposing (beginnerProgram)
import Html.Events exposing (onMouseDown, onClick)
main =
beginnerProgram { model = "init", view = view, update = update }
view model =
div []
((if model == "changed" then [ text "" ] else []) ++
[ div
[ onClick Click
, onMouseDown Change
] [ text "click me" ]
, div [] [ text model ]
])
type Msg = Change | Click
update msg model =
case Debug.log "msg" msg of
Change ->
"changed"
Click ->
"clicked"
The first click causes Change
message but does not cause Click
. The second click causes the both.
So I am one of those people bullishly running elm in node (not super polished but here is an in progress example https://github.com/greyepoxy/elm-GameHostServer).
It works decently well and allows me to share code between the client and the server. Another cool advantage of doing this is that you can write all of your html in elm (even the page you embed your client program into).
With elm 0.16 I used to use vdom-to-html, now with elm implementing its own virtual dom in 0.17 this no longer works.
I wrote a really simple version that would suit my current purposes here. I would like to look into the possibility of writing a more official version but didn't want to just push out a pull request if it has no hope of getting merged.
module definition would be something like
module VirtualDom.ToString exposing (toHtml) ...
Currently this would have to be a native module unless the virtualDom exposes more of its structure in elm.
So here are a couple options,
In Elm 0.18:
import Html exposing (..)
import Html.Attributes exposing (..)
main =
select [ type_ "checkbox" ] []
It's a user mistake (select
tags should not have a type
attribute) that provokes a runtime error.
Edit: I updated the above for 0.18. Below is the original report, for Elm 0.15 -@rtfeldman
import Html exposing (..)
import Html.Attributes exposing (..)
main =
select [ type' "checkbox" ] []
Got the above error for this code: https://gist.github.com/gdotdesign/4d4985415b1d4daca4fb48aee01bbd50
Changing the oder of the style attribute changes the behavior, if it's at the top it's the #4 issue, if it's the middle or the bottom then the error above.
$ elm make Main.elm --output ../lib/public/browser.js
Problem in dependency elm-lang/virtual-dom 2.0.0
The elm-package.json constraints of 'elm-lang/virtual-dom' are probably
letting too much stuff through. Definitely open an issue on the relevant github
repo to get this fixed and save other people from this pain.
{
"version": "1.0.0",
"summary": "helpful summary of your project, less than 80 characters",
"repository": "https://github.com/user/project.git",
"license": "BSD3",
"source-directories": [
"."
],
"exposed-modules": [],
"dependencies": {
"elm-lang/core": "5.0.0 <= v < 6.0.0",
"elm-lang/html": "2.0.0 <= v < 3.0.0",
"elm-lang/http": "1.0.0 <= v < 2.0.0"
},
"elm-version": "0.18.0 <= v < 0.19.0"
}
I've noticed that elm-lang/virtual-dom isn't in my elm-package.json.
When the native debugger wants to serialize an object with {ctor: 'RawTexture', img: img}
the image is considered to be a record here, and this causes Uncaught RangeError: Maximum call stack size exceeded
.
The representation of the texture is either { ctor: 'RawTexture', img: img }
or { ctor: 'Texture', img: img }
, https://github.com/elm-community/webgl/blob/master/src/Native/WebGL.js#L38
The type is Texture
: https://github.com/elm-community/webgl/blob/master/src/WebGL.elm#L89
I can fix it by putting an image into a getter function () { return img; }
, then it will be serialized as XXX
. Not sure if this solution is acceptable.
Hello,
I found this to be a problem in other virtual dom implementation while I was searching for a solution. Not certain if this really needs fixing here.
Elm-version: 0.17.0
Browser: Chrome Version 51.0.2704.84 m
if a node with "contenteditable" set is meant to be updated and the new node does not have this property, I get the following error:
Uncaught SyntaxError: Failed to set the 'contentEditable' property on 'HTMLElement': The value provided ('null') is not one of 'true', 'false', 'plaintext-only', or 'inherit'
Fails in Edge as well, cannot test Firefox right now.
Try out the following Elm example that toggles between a div with contenteditable set to True and one with no contenteditable attribute.
import Html exposing (..)
import Html.Events exposing (..)
import Html.Attributes exposing (..)
import Html.App as Html
type alias Model =
{ content : String
, editable : Bool
}
type Msg = ToggleContentEditable
main =
Html.beginnerProgram
{ model = { content = "Hello", editable = False }
, view = view
, update = update
}
update msg model =
case msg of
ToggleContentEditable ->
{model | editable = (not model.editable)}
view model =
div []
[ Html.button [onClick ToggleContentEditable] [ text "Toggle" ]
, viewContent model
]
viewContent model =
if (model.editable)
then div [contenteditable True] [ text model.content ]
else div [ ] [ text model.content ]
Setting contenteditable explicitly to "False" in the alternative div resolves this problem.
However, in my use case, I have an app with several tabs (similar to the elm-mdl demo page), where I have a contenteditable div in one tab, and a completely different subtree to render another div, so I don't know how I should set contenteditable explicitly in this different subtree.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.