Re: [elm-discuss] Elm Architecture in Vanilla JS
Thank you! Very informative and laugh-out-loud funny! Really helpful, thanks! - Bob On Sat, Feb 25, 2017 at 7:27 PM, Witold Szczerbawrote: > Hi, > so you want to carry The Elm Architecture (TEA) to the "vanilla JS" world. > I came across recently an article: "How I converted my React app to > VanillaJS". React is quite similar to TEA, actually it's React/Redux that > is similar, but still, I think you could find something useful there. > https://hackernoon.com/how-i-converted-my-react-app-to- > vanillajs-and-whether-or-not-it-was-a-terrible-idea- > 4b14b1b2faff#.zgqzwurva > > Regards, > Witold Szczerba > > > On Sun, Feb 26, 2017 at 12:52 AM, Robert Muller > wrote: > >> Greetings. I'm an OCaml guy, teaching Web Apps for the first time and >> finding my way through the insanity that is HTML + CSS + JS and trying to >> impart something sensible to students for how to structure their vanilla JS >> apps to conform to the the Elm Architecture (model-view-update). First time >> through, I'm not savvy enough to know how to properly fake the Elm >> Architecture in vanilla JS. >> >> IN PARTICULAR: I'd like to write a simple TODO app where the model is a >> record containing a list of todo items and a list of completed items. I'd >> like to write the app along the lines of: >> >> let app = { >> >> view : view, // : model -> element >> >> update : update // : model -> model >> >>} >> >> >> But I'm getting bollixed-up with the basic wiring. It's very basic stuff. >> E.g., let's say I have an addItem button; I assume that I want to wire-up >> the event listener to deliver the new item to the model (an update). >> Obviously these are executed asynchronously. But then what are the proper >> manners for displaying the model in the DOM? For a simple synchronous >> 8-queens solver example that I did, I wrote a reasonable runApp function >> using the JS setInterval function. But I'm not sure if this is kosher for >> the asynchronous case. >> >> Any advice here? Any pointers to Vanilla JS examples written using the >> Elm Architecture? >> >> Thank you! Your reply would help me and my 60 students! >> Bob Muller >> >> -- >> You received this message because you are subscribed to the Google Groups >> "Elm Discuss" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to elm-discuss+unsubscr...@googlegroups.com. >> For more options, visit https://groups.google.com/d/optout. >> > > -- > You received this message because you are subscribed to a topic in the > Google Groups "Elm Discuss" group. > To unsubscribe from this topic, visit https://groups.google.com/d/ > topic/elm-discuss/XJ6yP_Mq7M0/unsubscribe. > To unsubscribe from this group and all its topics, send an email to > elm-discuss+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Elm Discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [elm-discuss] Designing with sum and product types
Thanks for this discussion, these kinds of modelling decisions I feel like I struggle with over and over. And inevitably I get something not quite right and then later have a massive cleanup to do since everything else depends on the shape of the model :( I like your step by step procedure Rupert, it kind of puts in words what I've been doing, but in a more systematic way. I often do end up with "a product of sums of little products", -- several things that each have distinct states, each of which have some sets of fields in common and some not. In other words an attempt to deal with Brian's "'this is like that except for...' problem ... the core software design problem in messy domains." (And let's face it, *every* domain outside of general purpose tools is 'messy'). I would like to experiment more with encapsulation via opaque types in applications, it often feels like overkill to me in applications (vs. in libraries), but would help in terms of isolating changes to the model and its core API, obviously. On Thursday, February 23, 2017 at 6:22:59 PM UTC-5, Rupert Smith wrote: > > On Thursday, February 23, 2017 at 8:57:32 PM UTC, Brian Marick wrote: >> >> The first animal is in the Compact state, the second in Expanded, and the >> last in Editable. Would you be suggesting a `Mode` like the following? >> >> type Mode >> = Compact Animal >> | Expanded Animal >> | Editable Animal FormData >> > > Yes, that is the pattern I am working with at the moment. > > >> I had problems with that. I too often had view code that had to know both >> that it was given `FormData` and also had to take the whole `Mode` as an >> argument - or had to assemble a Mode from the pieces they were given. >> (Unfortunately the details are fuzzy in my memory.) >> > > I forgot to include my help functions in the Gist. Adding them now. > https://gist.github.com/rupertlssmith/c948f304ce0a99cd7ba9d6b6a061251a > > I also have situation where I need to write a function the uses >1 of the > little products that make up a state. I wrote a mapWhenCompose function for > that. I can also tell you that my first 7 attempt to write this function > each occupied about 20 lines of code and none of them compiled! Then almost > by chance, or was it a good nights sleep, the answer came to my no longer > young and brilliant mind: > > mapWhenCompose : (c -> d -> Maybe a) -> (a -> d -> Maybe b) -> c -> d -> > Maybe b > mapWhenCompose mapWhen1 mapWhen2 func state = > mapWhen1 func state > |> andThen ((flip mapWhen2) state) > > so if you follow my pattern and write the mapWhenWithAnimal and > mapWhenWithFormData functions, then you can do: > > editableView animal formData = ... > > and then call it with: > > mapWhenCompose mapWhenWithAnimal mapWhenWithFormData editableView mode > > Note also that mapWhenCompose also returns a mapWhen function so can be > further composed. > > > > What I really like about this pattern is that I have eliminated all Maybes > from my model. But now I am using Maybes to linearize the logic and to be > able to compose pieces of logic together, using Nothing to indicate a > failure of a logic flow to complete. This feels like a much better way to > use Maybes. > -- You received this message because you are subscribed to the Google Groups "Elm Discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [elm-discuss] Elm Architecture in Vanilla JS
Hi, so you want to carry The Elm Architecture (TEA) to the "vanilla JS" world. I came across recently an article: "How I converted my React app to VanillaJS". React is quite similar to TEA, actually it's React/Redux that is similar, but still, I think you could find something useful there. https://hackernoon.com/how-i-converted-my-react-app-to-vanillajs-and-whether-or-not-it-was-a-terrible-idea-4b14b1b2faff#.zgqzwurva Regards, Witold Szczerba On Sun, Feb 26, 2017 at 12:52 AM, Robert Mullerwrote: > Greetings. I'm an OCaml guy, teaching Web Apps for the first time and > finding my way through the insanity that is HTML + CSS + JS and trying to > impart something sensible to students for how to structure their vanilla JS > apps to conform to the the Elm Architecture (model-view-update). First time > through, I'm not savvy enough to know how to properly fake the Elm > Architecture in vanilla JS. > > IN PARTICULAR: I'd like to write a simple TODO app where the model is a > record containing a list of todo items and a list of completed items. I'd > like to write the app along the lines of: > > let app = { > > view : view, // : model -> element > > update : update // : model -> model > >} > > > But I'm getting bollixed-up with the basic wiring. It's very basic stuff. > E.g., let's say I have an addItem button; I assume that I want to wire-up > the event listener to deliver the new item to the model (an update). > Obviously these are executed asynchronously. But then what are the proper > manners for displaying the model in the DOM? For a simple synchronous > 8-queens solver example that I did, I wrote a reasonable runApp function > using the JS setInterval function. But I'm not sure if this is kosher for > the asynchronous case. > > Any advice here? Any pointers to Vanilla JS examples written using the Elm > Architecture? > > Thank you! Your reply would help me and my 60 students! > Bob Muller > > -- > You received this message because you are subscribed to the Google Groups > "Elm Discuss" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to elm-discuss+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Elm Discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[elm-discuss] Elm Architecture in Vanilla JS
Greetings. I'm an OCaml guy, teaching Web Apps for the first time and finding my way through the insanity that is HTML + CSS + JS and trying to impart something sensible to students for how to structure their vanilla JS apps to conform to the the Elm Architecture (model-view-update). First time through, I'm not savvy enough to know how to properly fake the Elm Architecture in vanilla JS. IN PARTICULAR: I'd like to write a simple TODO app where the model is a record containing a list of todo items and a list of completed items. I'd like to write the app along the lines of: let app = { view : view, // : model -> element update : update // : model -> model } But I'm getting bollixed-up with the basic wiring. It's very basic stuff. E.g., let's say I have an addItem button; I assume that I want to wire-up the event listener to deliver the new item to the model (an update). Obviously these are executed asynchronously. But then what are the proper manners for displaying the model in the DOM? For a simple synchronous 8-queens solver example that I did, I wrote a reasonable runApp function using the JS setInterval function. But I'm not sure if this is kosher for the asynchronous case. Any advice here? Any pointers to Vanilla JS examples written using the Elm Architecture? Thank you! Your reply would help me and my 60 students! Bob Muller -- You received this message because you are subscribed to the Google Groups "Elm Discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [elm-discuss] How up update sub-models ...
That worked!! Good to know!! I will do that next time. Thank you! -- You received this message because you are subscribed to the Google Groups "Elm Discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [elm-discuss] How up update sub-models ...
Hi, that would be so much easier to help you if you would have prepared an executable using runelm.io or ellie-app.com. Taking a quick look at your update function I would suggest: InputEmail email -> { model | email = StringField email (validateEmail email) } ! [] Regards, Witold Szczerba On Sat, Feb 25, 2017 at 10:08 PM, Michael Johnson < michael.a.johnson...@gmail.com> wrote: > Hello, new to elm and experimenting around with it and I'm not sure how to > update a sub model. I have not run across an example of this form yet. > Given the following: > > -- MODEL > > > type alias StringField = > { > value : String > , errors : List String > } > > > --> how to update value and errors fields for email and password in > this model > type alias Model = > { email : StringField > , password : StringField > } > > > initValue : String > initValue = "" > > > initErrors : List String > initErrors = [] > > > initEmail = StringField initValue initErrors > initPassword = StringField initValue initErrors > > > init : (Model, Cmd Msg) > init = > (Model initEmail initPassword, Cmd.none) > > > -- UPDATE > > > type Msg > = InputEmail String > | InputPassword String > | SubmitForm > > update : Msg -> Model -> (Model, Cmd Msg) > update msg model = > case msg of > InputEmail email -> > let > emailModel = model.email > in > > >> > { emailModel | value = email, errors = validateEmail email } > ( { model | email = emailModel }, Cmd.none) > > > InputPassword password -> > let > passwordModel = model.password > in > > >> > { passwordModel | value = password, errors = validatePassword > password } > ( { model | password = passwordModel }, Cmd.none ) > > > SubmitForm -> > ( model, Cmd.none) > > validateEmail : String -> List String > validateEmail model = > --put validation here > [] > > > validatePassword : String -> List String > validatePassword model = > --put validation here > [] > > I have worked through several iterations and got to this point but it > seems like there should be an easier and more direct way. Plus this is > still producing the following errors: > > -- TYPE MISMATCH --- > kitchensink.elm > > > You are giving an argument to something that is not a function! > > > 63| { passwordModel | value = password, errors = validatePassword > password } > > 64|>( { model | password = passwordModel }, Cmd.none ) > > > Maybe you forgot some parentheses? Or a comma? > > > -- TYPE MISMATCH --- > kitchensink.elm > > > You are giving an argument to something that is not a function! > > > 56| { emailModel | value = email, errors = validateEmail email } > > 57|>( { model | email = emailModel }, Cmd.none) > > > Maybe you forgot some parentheses? Or a comma? > > > -- > You received this message because you are subscribed to the Google Groups > "Elm Discuss" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to elm-discuss+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Elm Discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [elm-discuss] How up update sub-models ...
Thanks for the quick reply!! I'm not sure I'm following that. I'm trying that code and it does not know what the "emailModel" and "passwordModel" are. Cannot find variable `emailModel` 52| ( { model | email = { emailModel | value = email, errors = validateEmail email } }, Cmd.none ) ^^ How does model.email get placed into the field emailModel? -- You received this message because you are subscribed to the Google Groups "Elm Discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [elm-discuss] How up update sub-models ...
I think what you're looking for is this syntax: ( { model | email = { emailModel | value = email, errors = validateEmail email } }, Cmd.none ) and ( { model | password = { passwordModel | value = password, errors = validatePassword password } }, Cmd.none ) On Sat, Feb 25, 2017 at 2:08 PM, Michael Johnson < michael.a.johnson...@gmail.com> wrote: > Hello, new to elm and experimenting around with it and I'm not sure how to > update a sub model. I have not run across an example of this form yet. > Given the following: > > -- MODEL > > > type alias StringField = > { > value : String > , errors : List String > } > > > --> how to update value and errors fields for email and password in > this model > type alias Model = > { email : StringField > , password : StringField > } > > > initValue : String > initValue = "" > > > initErrors : List String > initErrors = [] > > > initEmail = StringField initValue initErrors > initPassword = StringField initValue initErrors > > > init : (Model, Cmd Msg) > init = > (Model initEmail initPassword, Cmd.none) > > > -- UPDATE > > > type Msg > = InputEmail String > | InputPassword String > | SubmitForm > > update : Msg -> Model -> (Model, Cmd Msg) > update msg model = > case msg of > InputEmail email -> > let > emailModel = model.email > in > > >> > { emailModel | value = email, errors = validateEmail email } > ( { model | email = emailModel }, Cmd.none) > > > InputPassword password -> > let > passwordModel = model.password > in > > >> > { passwordModel | value = password, errors = validatePassword > password } > ( { model | password = passwordModel }, Cmd.none ) > > > SubmitForm -> > ( model, Cmd.none) > > validateEmail : String -> List String > validateEmail model = > --put validation here > [] > > > validatePassword : String -> List String > validatePassword model = > --put validation here > [] > > I have worked through several iterations and got to this point but it > seems like there should be an easier and more direct way. Plus this is > still producing the following errors: > > -- TYPE MISMATCH --- > kitchensink.elm > > > You are giving an argument to something that is not a function! > > > 63| { passwordModel | value = password, errors = validatePassword > password } > > 64|>( { model | password = passwordModel }, Cmd.none ) > > > Maybe you forgot some parentheses? Or a comma? > > > -- TYPE MISMATCH --- > kitchensink.elm > > > You are giving an argument to something that is not a function! > > > 56| { emailModel | value = email, errors = validateEmail email } > > 57|>( { model | email = emailModel }, Cmd.none) > > > Maybe you forgot some parentheses? Or a comma? > > > -- > You received this message because you are subscribed to the Google Groups > "Elm Discuss" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to elm-discuss+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Elm Discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[elm-discuss] import Json.Decode problem, and creating commands
I use Elm 0.18. I have written the following, simple Elm program. It is supposed to accumulate values, sent from JS. I'd also like to get the accumulated value from the program, back to JS. port module App exposing (..) import Json.Decode import Task -- model type alias Model = { acc : Int } addNumber : Int -> Model -> Model addNumber n model = { model | acc = model.acc + n } init : (Model, Cmd Msg) init = (Model 0, Cmd.none) -- update type Msg = GetAcc () | AddNumber Int port toJS : Int -> Cmd msg update : Msg -> Model -> (Model, Cmd Msg) update msg model = case msg of GetAcc -> (model, toJS model.acc) AddNumber n -> (addNumber n model, Task.perform GetAcc <| Task.succeed ()) -- subscriptions port fromJS : (Int -> msg) -> Sub msg subscriptions : Model -> Sub Msg subscriptions model = fromJS AddNumber -- main main = Platform.program { init = init, update = update, subscriptions = subscriptions } There are two problems with the code: 1) Without the `import Json.Decode`, the code is compiled, yet I get the `ReferenceError: _elm_lang$core$Json_Decode$int is not defined` error after loading the result JS file, It's similar to this issue: https://github.com/elm-lang/core/issues/683 Is it an Elm bug? 2) The message type is defined as follows: type Msg = GetAcc () | AddNumber Int With such a definition, I can create a command to get the accumulator value using the `Task` module functions: Task.process GetAcc <| Task.succeed () Is it possible to create command for the following Msg definition: type Msg = GetAcc | AddNumber Int In this case, `GetAcc` has a type of `Msg`, while in my code, its type is `() -> Msg`, which was needed for the function `Task.process`. -- You received this message because you are subscribed to the Google Groups "Elm Discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [elm-discuss] Can I run Elm with/on Nodejs
I've also been using elm on the server side, and have some thoughts: In elm-0.18 you'll use a Platform.program or Platform.programWithFlags and pass command line arguments via the flags from a small javascript runner. Unlike Sonny Michaud's approach, I've used the normal init/update/subscriptions approach and it can also work well. The skeleton I made for elm on node is here: https://github.com/prozacchiwawa/elm-worker-runner-example You can use web side elm packages like Html (alongside elm-server-side-renderer) and elm-lang/http as well if you're willing to postprocess the elm output a small amount. On Friday, February 24, 2017 at 7:56:11 AM UTC-8, Tom F wrote: > > Hey guys, > > I'm also very interested in running elm server side (especially node.js), > and would appreciate to hear about your experiences & tips. > > Thx ! > > On Friday, January 9, 2015 at 6:09:11 PM UTC+1, Sonny Michaud wrote: >> >> Everything Joey said is spot on. I should have pointed out that my >> library simply takes care of running elm-compile for you and giving you >> access to the ports from your Elm code. Basically, the point is to reduce >> the friction of those additional build steps for you. There is also an >> interoperability layer between the ports from Elm and Node EventEmitter >> objects, so people familiar with the latter can concern themselves with the >> details less. >> >> - Sonny >> >> On 01/09/2015 11:59 AM, Joey Eremondi wrote: >> >> @robcuz the important thing to remember is that Elm is just a way to >> translate elm code into JavaScript. >> >> So really, you can run Elm with any platform that interacts with JS, >> because the result of elm-make is JavaScript. So you use the code Elm >> generates as part of a JS project. Ports makes this particularly elegant. >> >> Here's the tutorial on Ports: >> http://elm-lang.org/learn/Ports.elm >> >> As for importing libs into elm-repl, that's not possible because it would >> violate purity. It's easy to call Elm from JavaScript, but calling >> JavaScript from Elm is tough, because there's no guarantee that JS code is >> pure (performs no side-effects) or typesafe. So your best bet is to choose >> the functionality you want to import and set up ports for them. >> >> On Friday, January 9, 2015 at 5:24:53 PM UTC+1, Sonny Michaud wrote: >>> >>> I wrote a NPM module that goes in the opposite direction - allowing you >>> to import Elm code into your JS: >>> https://www.npmjs.com/package/elm-loader >>> >>> - Sonny >>> >>> On 01/09/2015 08:45 AM, robkuz wrote: >>> >>> I havent found anything to declare the contrary but also nothing that >>> says its possible. >>> And if it is possible can I import JS libs into the ELM Repl? or how is >>> that done? >>> >>> Thanks for clarification >>> >>> Rob >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Elm Discuss" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to elm-discuss...@googlegroups.com. >>> For more options, visit https://groups.google.com/d/optout. >>> >>> >>> -- >> You received this message because you are subscribed to the Google Groups >> "Elm Discuss" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to elm-discuss...@googlegroups.com. >> For more options, visit https://groups.google.com/d/optout. >> >> >> -- You received this message because you are subscribed to the Google Groups "Elm Discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[elm-discuss] Re: webpack hotloading: compile errror leads to loss of state
Aha, that's promising I have my own starter https://github.com/simonh1000/elm-hot-loading-starter and have tried https://github.com/halfzebra/create-elm-app and both experienced the issues I described. I will take a look at what you do Simon On Saturday, 25 February 2017 18:13:09 UTC+1, Austin Bingham wrote: > > Is this with elm-webpack-loader, or some other package? I use > elm-webpack-loader and the webpack-dev-server, and it definitely recovers > after a broken compilation. You can see my configuration here if that > helps: https://github.com/abingham/accu-2017-elm-app > > On Saturday, February 25, 2017 at 4:56:59 PM UTC, Simon wrote: >> >> I have tried webpack directly and some of the starters, but I can't find >> a way to use hotloading after making a change that led to a compiler error. >> It only works if you write perfect code and recompile. If you have an >> error, then when these have been fixed the page reloads with the default >> state. >> >> Are there any solutions for this? >> > -- You received this message because you are subscribed to the Google Groups "Elm Discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[elm-discuss] Re: webpack hotloading: compile errror leads to loss of state
This isn't really a "solution" to your problem, but because I had endless frustrating headaches with elm-webpack-starter I switched to the much simpler elm-live: https://github.com/tomekwi/elm-live and create-elm-app: https://github.com/halfzebra/create-elm-app/blob/master/template/README.md On Saturday, February 25, 2017 at 11:56:59 AM UTC-5, Simon wrote: > > I have tried webpack directly and some of the starters, but I can't find a > way to use hotloading after making a change that led to a compiler error. > It only works if you write perfect code and recompile. If you have an > error, then when these have been fixed the page reloads with the default > state. > > Are there any solutions for this? > -- You received this message because you are subscribed to the Google Groups "Elm Discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[elm-discuss] Re: webpack hotloading: compile errror leads to loss of state
Is this with elm-webpack-loader, or some other package? I use elm-webpack-loader and the webpack-dev-server, and it definitely recovers after a broken compilation. You can see my configuration here if that helps: https://github.com/abingham/accu-2017-elm-app On Saturday, February 25, 2017 at 4:56:59 PM UTC, Simon wrote: > > I have tried webpack directly and some of the starters, but I can't find a > way to use hotloading after making a change that led to a compiler error. > It only works if you write perfect code and recompile. If you have an > error, then when these have been fixed the page reloads with the default > state. > > Are there any solutions for this? > -- You received this message because you are subscribed to the Google Groups "Elm Discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[elm-discuss] Re: can't understand compiler error
I just did this exercise too! My solution was to perform the validation from the update function and to save the error messages in the model. On Saturday, 25 February 2017 06:55:06 UTC, Anurup Mitra wrote: > > Dear Alex, > > This is very elegant indeed! I am bowled over by the simplicity of it all. > So its like chaining mathematical functions... > > I'm off to read Learn You a Haskell. > > Thanks a ton mate! > > Best Regards > Anurup > -- You received this message because you are subscribed to the Google Groups "Elm Discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [elm-discuss] Elm and contenteditable
One trick I have learned when integrating date range picker is that you can push data from component to Elm using custom HTML events instead of sending data through a port(s). I have described it shortly here: https://www.reddit.com/r/elm/comments/5uqa13/those_fancy_date_pickers_in_elm_watch_this_no/ input [ class "form-control date-range" , value <| formatMaybeDuration item.duration , onDateRangePicker DurationChanged *-- see demo for details* ] [] Regards, Witold Szczerba On Fri, Feb 24, 2017 at 4:30 PM, Josh Szmajdawrote: > I'm working with http://github.com/Voog/wysihtml, integration has been > pretty alright.. Still very much in the figuring things out stage for my > app but here are some key snippets: > > Ports: > ``` > port startEditor : (String, String, String) -> Cmd msg > port stopEditor : String -> Cmd msg > port editorChanges : (String -> msg) -> Sub msg > port selectionChange : (Selection -> msg) -> Sub msg > ``` > > Selection: > ``` > type alias Selection = > { text : String > , t : Float > , r : Float > , b : Float > , l : Float > } > ``` > > WYSIHtml View: > ``` > module Wysihtml.View exposing (wysiToolbar, wysiEditor) > > import Html exposing (..) > import Html.Attributes exposing (id, attribute, class) > > wysiToolbar : a -> Html a > wysiToolbar msg = > div [ id "wysi-toolbar" ] > [ a [ class "bold", command msg "bold" ] [ text "B" ] > , a [ class "italic", command msg "italic" ] [ text "I" ] > , a [ class "h1", command msg "formatBlock", commandValue msg "h1" ] [ > text "H1" ] > , a [ class "p", command msg "formatBlock", commandValue msg "p" ] [ > text "P" ] > , a [ class "ul", command msg "inserUnorderedList" ] [ text "list" ] > ] > > wysiEditor : a -> Html a > wysiEditor msg = > div [ id "wysi-editor", dataPlaceholder msg "Start editing" ] [] > > > dataPlaceholder : a -> String -> Attribute a > dataPlaceholder msg data = > attribute "data-placeholder" data > > command : a -> String -> Attribute a > command msg command = > attribute "data-wysihtml5-command" command > > commandValue : a -> String -> Attribute a > commandValue msg value = > attribute "data-wysihtml5-command-value" value > ``` > > index.html wiring: > ``` > app.ports.startEditor.subscribe(function(){ > var editor = arguments[0][0]; > var toolbar = arguments[0][1]; > var initialText = arguments[0][2]; > // todo change setTimeout to MutationObserver > setTimeout(function(){ > console.log('start editor'); > window.x_editor = new wysihtml5.Editor(editor, { > toolbar: toolbar, > parserRules: wysihtml5ParserRules > }); > window.x_editor.setValue(initialText, true); > window.x_editor.on('interaction', function(){ > app.ports.editorChanges.send(x_editor.getValue()); > }); > }, 60); > }); > document.addEventListener("selectionchange", function(){ > console.log("selection changed, sending to elm"); > selection = window.getSelection(); > if(!selection.isCollapsed){ > for(var i = 0; i < selection.rangeCount; i++) { > range = selection.getRangeAt(i); > rect = range.getBoundingClientRect(); > app.ports.selectionChange.send({ text: selection.toString(), t: > rect.top, r: rect.right, b: rect.bottom, l: rect.left }); > } > } > }); > ``` > > I think that's the meat. Happy to chat more. > > > On Friday, February 24, 2017 at 3:38:33 AM UTC-5, Simon wrote: >> >> I'm also trying to work with contenteditable. I have a basic system >> working with pure Elm, in that I can click on a field to edit it and then >> click elsewhere with blur causing an update of the model. But the challenge >> I face is detecting an enter key and using that save the updated value and >> blur the current field. I seem to be getting some virtual DOM issues. >> >> Anyway I have an Ellie at https://ellie-app.com/tnXL92zwvka1/3 and if >> anyone can help, I'd love to know >> >> Simon >> >> On Tuesday, 27 September 2016 16:35:04 UTC+2, Girish Sonawane wrote: >>> >>> Instead of onChange, you can try using Events.on http://package.elm-l >>> ang.org/packages/elm-lang/html/1.1.0/Html-Events#on >>> >>> >>> On Tuesday, August 30, 2016 at 3:16:12 PM UTC+5:30, Peter Damoc wrote: I've tried a naive implementation in Elm but, for some reason, it doesn't work (events are not fired for divs that have content editable) import Html exposing (..) import Html.Attributes exposing (..) import Html.App exposing (beginnerProgram) import Html.Events exposing (on) import Json.Encode as JE import Json.Decode as JD exposing ((:=)) main = beginnerProgram { model = "", view = view, update = update } onContent tagger = on "input" (JD.map tagger ("innerHTML" := JD.string)) view model = div [] [ div [property "innerHTML" (JE.string model), onContent OnChange, contenteditable True][] ] type Msg =