I just wrote a new version of example here <https://gist.github.com/jinjor/cc9b74ccf0b24eb60dd2ed33e7b41d49>. This container view can also handle the messages of its children that have different kind of messages defined outside. I think this is more practical than previous one. (I haven't tried it in my app yet, though)
2016-05-19 1:38 GMT+09:00 Daniel Kwiecinski <[email protected]>: > Hi Peter, > > Just skimmed on the gist, but can already tell this is great help. Many > thanks for your work. > > Cheers, > Dan > > On Wednesday, 18 May 2016 15:20:38 UTC+1, Peter Damoc wrote: >> >> This gist (previously posted) >> https://gist.github.com/pdamoc/aef6306a9001de109aeece37e5627d06 >> is a kind of minimalist example. It shows how to join together 2 >> different widgets (RandomGif and Counter). >> The process for extending the list with new widgets is mechanical, just >> add options to all the relevant types. >> >> >> >> >> >> On Wed, May 18, 2016 at 4:59 PM, Daniel Kwiecinski <[email protected] >> > wrote: >> >>> Sounds very promising. Could you please provide minimalist example? >>> >>> On Wednesday, 18 May 2016 13:47:16 UTC+1, Peter Damoc wrote: >>>> >>>> You just use regular Elm Architecture and compose the model of the >>>> autocomplete into the proper place, same with update and view. >>>> >>>> To speak in React terms, what you had above are components that have >>>> only props. These can be implemented with simple functions in Elm. >>>> >>>> If a component needs state and rest calls, it needs to follow the Elm >>>> Architecture. Please note that the component can be fully encapsulated in a >>>> module. The kind of boilerplate needed for state management is very small >>>> and very predictable. You can even extract it into some kind of Widget >>>> abstraction and have all the Widgets be updated by a single line of code. >>>> :) >>>> >>>> >>>> >>>> >>>> >>>> >>>> On Wed, May 18, 2016 at 3:16 PM, Daniel Kwiecinski < >>>> [email protected]> wrote: >>>> >>>>> This is fine. Big thanks for your effort. >>>>> But, how about instead of components being simple functions we have >>>>> components as {init, update, view, subscription} so they encapsulate their >>>>> logic. >>>>> Think in having a component similar to google places autocomplete. >>>>> From it's parent we still want to pass a configuration to it and react to >>>>> the commands coming from the autocomplete (such as place changed) but we >>>>> do >>>>> not want or need to interfere with the autocomplete component internal >>>>> state, rest calls etc? >>>>> >>>>> On Wednesday, 18 May 2016 13:08:21 UTC+1, Peter Damoc wrote: >>>>>> >>>>>> Oh, that's much easier: >>>>>> >>>>>> import Html exposing (..) >>>>>> import Html.Attributes exposing (class) >>>>>> >>>>>> helloComponent name = >>>>>> p [] [text ("Hello, " ++ name ++ "!")] >>>>>> >>>>>> sayHello = >>>>>> helloComponent "world" >>>>>> >>>>>> >>>>>> listHello names = >>>>>> div [] (List.map helloComponent names) >>>>>> >>>>>> >>>>>> -- GENERIC WRAPPING COMPONENT >>>>>> >>>>>> wrapComponents components = >>>>>> div [class "components-wrapped-in-pages-so-we-can-swipe-them"] >>>>>> (List.map (\c -> div [class "page"] [c]) components) >>>>>> >>>>>> >>>>>> names = ["Jim", "Bill", "Joe"] >>>>>> >>>>>> >>>>>> main = >>>>>> wrapComponents >>>>>> [ sayHello >>>>>> , helloComponent "Sandra" >>>>>> , listHello names >>>>>> ] >>>>>> >>>>>> There is no Signal anymore in Elm and if you use The Elm >>>>>> Architecture, all you get is regular values. >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> On Wed, May 18, 2016 at 1:15 PM, Daniel Kwiecinski < >>>>>> [email protected]> wrote: >>>>>> >>>>>>> Here is a sketch of how it would look like in reagent (ClojureScript) >>>>>>> >>>>>>> >>>>>>> ; -- SOME CONCRETE COMPONENTS >>>>>>> >>>>>>> ; a component taking a String as a model >>>>>>> (defn hello-component [name] >>>>>>> [:p "Hello, " name "!"]) >>>>>>> >>>>>>> ; a stateless component using another component >>>>>>> (defn say-hello [] >>>>>>> [hello-component "world"]) >>>>>>> >>>>>>> ; a component taking a ratom (it's a signal in elm speak) as a model >>>>>>> (defn reactive-hello-component [name] >>>>>>> [:p "Hello, " @name "!"]) >>>>>>> >>>>>>> ; a component taking list of Strings as a model >>>>>>> (defn list-hellos [names] >>>>>>> (for [n names] >>>>>>> [hello-component (str "hello " n)])) >>>>>>> >>>>>>> ; -- GENERIC WRAPPING COMPONENT >>>>>>> >>>>>>> >>>>>>> ; a wrapping components. take list of components as a parameter and >>>>>>> wraps them in pages >>>>>>> (defn wrap-components [components] >>>>>>> (fn [] >>>>>>> [:div {:class >>>>>>> "components-wrapped-in-pages-so-we-can-swipe-them"} >>>>>>> (for [c components] >>>>>>> [:div {:class "page"} c])])) >>>>>>> >>>>>>> >>>>>>> ; -- MAIN VIEW GLUING ALL TOGETHER >>>>>>> >>>>>>> >>>>>>> (defn main-view [] >>>>>>> (let [reactive-name (ratom "initial-name") >>>>>>> input-state (ratom "")] >>>>>>> [:div {:class "some-boilerplate"} >>>>>>> >>>>>>> ; the two lines below are not following re-frame pattern. >>>>>>> There are there just to express I have the state which changes. >>>>>>> [:input {:onchange (fn [value] (!reset input-state >>>>>>> value))}] ; react to inout changes and pass the value to model (in >>>>>>> re-frame instead of directly updating the model we would send a signal >>>>>>> (as in elm) and have subscription react to the signal but for >>>>>>> simplicity I ommit the patern) >>>>>>> [:button {:onclick #(!reset reactive-name @input-state)}] ; >>>>>>> copy the states on button click >>>>>>> >>>>>>> [:span {:class >>>>>>> "here-come-generic-swipe-able-pages-wrapping-any-components"} >>>>>>> >>>>>>> ; here is the usage of the wrapping container >>>>>>> (wrap-components [ >>>>>>> say-hello ; stateless component >>>>>>> #(hello-component "some-fancy-name") ; >>>>>>> #(...) is lambda in clojure, here we close over some static state >>>>>>> #(reactive-hello-component >>>>>>> reactive-name) ; #(...) here we close over some reactive state, so the >>>>>>> component re-renders when the model (state) changes >>>>>>> #(list-hellos ["a" "b" "c"]) ; component >>>>>>> taking list as a state (model) >>>>>>> ])]])) >>>>>>> >>>>>>> ; -- MOUNT VIEW TO DOM >>>>>>> >>>>>>> ; bind the main-view to DOM and start observing deltas to render if >>>>>>> needed >>>>>>> (defn ^:export run [] >>>>>>> (r/render [main-view] (js/document.body))) >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> On Wednesday, 18 May 2016 08:42:45 UTC+1, Peter Damoc wrote: >>>>>>>> >>>>>>>> Can you mock some code that would show how would you like to use >>>>>>>> this? >>>>>>>> Imagine that it is already implemented in some library and write >>>>>>>> against that imaginary library. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> On Tue, May 17, 2016 at 5:36 PM, Daniel Kwiecinski < >>>>>>>> [email protected]> wrote: >>>>>>>> >>>>>>>>> The problem is that the generic container component (Let's call it >>>>>>>>> C) do not know about it potential children (let's call them X, Y, Z) . >>>>>>>>> There is top level component (Let's call it T) which has a knowledge >>>>>>>>> about >>>>>>>>> all of them (it is the app). The C is in self contained package, you >>>>>>>>> can >>>>>>>>> consider it to implement material design list view. How Can I >>>>>>>>> implement C >>>>>>>>> so T can use T with X, Y, Z ? >>>>>>>>> >>>>>>>>> On Tuesday, 17 May 2016 15:09:36 UTC+1, Peter Damoc wrote: >>>>>>>>>> >>>>>>>>>> Hi Daniel, >>>>>>>>>> >>>>>>>>>> If you have a limited number of components you can unify them >>>>>>>>>> into one kind of a component. >>>>>>>>>> >>>>>>>>>> Here is a self contained example that unifies Counter and >>>>>>>>>> RandomGif and then uses them in a single list. >>>>>>>>>> https://gist.github.com/pdamoc/aef6306a9001de109aeece37e5627d06 >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On Tue, May 17, 2016 at 3:47 PM, Daniel Kwiecinski < >>>>>>>>>> [email protected]> wrote: >>>>>>>>>> >>>>>>>>>>> So let me expand my scenario a little bit. Lets assume that the >>>>>>>>>>> CounterList component is very feature heavy. It makes lots of work >>>>>>>>>>> to >>>>>>>>>>> layout its children, manages drag to sort or whatever fancy stuff >>>>>>>>>>> you can >>>>>>>>>>> imagine. Now in my app I have many instances of usage of >>>>>>>>>>> CounterList and I >>>>>>>>>>> want to apply the complex behaviour not only to counters but also >>>>>>>>>>> to gif >>>>>>>>>>> and to mixed counters with gifs and many many other possible >>>>>>>>>>> configurations >>>>>>>>>>> (think in hundreds). I don't really want to implement dedicated >>>>>>>>>>> CounterList, GifList, 2GifsWith3CountersList and other few hundreds >>>>>>>>>>> SomethingBlaBlaList. >>>>>>>>>>> Is it possible in elm at all? If yes how so? >>>>>>>>>>> >>>>>>>>>>> P.S. It is not imaginary question. I try to port existing >>>>>>>>>>> application implemented in Re-Frame (ClojureScript framework) in >>>>>>>>>>> which this >>>>>>>>>>> scenario is trivial. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On Tuesday, 17 May 2016 13:33:27 UTC+1, Wil C wrote: >>>>>>>>>>>> >>>>>>>>>>>> Daniel, >>>>>>>>>>>> >>>>>>>>>>>> I think normally, you don't. I think the constraint here is >>>>>>>>>>>> that you need to explicitly set the types of each of the >>>>>>>>>>>> sub-components for >>>>>>>>>>>> every component that you make for a page. In the example that you >>>>>>>>>>>> give, >>>>>>>>>>>> you'd actually need to create 4 types of components: TopLevel, >>>>>>>>>>>> Counter, >>>>>>>>>>>> CounterList, and Gif. >>>>>>>>>>>> >>>>>>>>>>>> TopLevel component would include CounterList and Gif. And then >>>>>>>>>>>> CounterList would contain Counters. It is CounterList's job to >>>>>>>>>>>> dynamically >>>>>>>>>>>> keep track of the number of Counters. That way, you don't need a >>>>>>>>>>>> generic >>>>>>>>>>>> component to contain an unknown number of things with unknown >>>>>>>>>>>> types. And >>>>>>>>>>>> then if those components need to talk to each other (Like once you >>>>>>>>>>>> add 5 or >>>>>>>>>>>> more counters, you see a funny cat gif), I believe you can send >>>>>>>>>>>> messages >>>>>>>>>>>> through Cmds (in 0.17) or Effects (in <0.17). >>>>>>>>>>>> >>>>>>>>>>>> With the hierarchical thinking of laying out components, I >>>>>>>>>>>> found that Thinking in React >>>>>>>>>>>> <https://facebook.github.io/react/docs/thinking-in-react.html> >>>>>>>>>>>> helps. >>>>>>>>>>>> >>>>>>>>>>>> If you find that you really need the flexibility of having >>>>>>>>>>>> different components in a container, it's doable. But it comes at >>>>>>>>>>>> a cost. >>>>>>>>>>>> Generally, if you're making a web app of some sort, it's not >>>>>>>>>>>> needed. I >>>>>>>>>>>> cover entity component systems recently in another thread, and >>>>>>>>>>>> it's for >>>>>>>>>>>> games. >>>>>>>>>>>> >>>>>>>>>>>> https://groups.google.com/forum/#!topic/elm-discuss/c9MhBzVPbr8 >>>>>>>>>>>> >>>>>>>>>>>> Wil >>>>>>>>>>>> >>>>>>>>>>>> On Tuesday, May 17, 2016 at 5:13:56 AM UTC-7, Daniel Kwiecinski >>>>>>>>>>>> wrote: >>>>>>>>>>>>> >>>>>>>>>>>>> Hi Elmers, >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> Here is my scenario. Say I have Main.elm which defines main >>>>>>>>>>>>> view form my application. I also have bunch of other components >>>>>>>>>>>>> (with their >>>>>>>>>>>>> corresponding model and message types) say Counter and Gif. >>>>>>>>>>>>> ( >>>>>>>>>>>>> https://github.com/evancz/elm-architecture-tutorial/blob/master/nesting/Gif.elm >>>>>>>>>>>>> ) >>>>>>>>>>>>> ( >>>>>>>>>>>>> https://github.com/evancz/elm-architecture-tutorial/blob/master/nesting/Counter.elm >>>>>>>>>>>>> ) >>>>>>>>>>>>> Now I'd like to create new generic component which as a >>>>>>>>>>>>> parameter (initial value of its model?) takes list of any type of >>>>>>>>>>>>> component >>>>>>>>>>>>> (say two counters, then one gif and another three counters) and >>>>>>>>>>>>> wraps them >>>>>>>>>>>>> into some decorating html. >>>>>>>>>>>>> The scenario serves as a illustration of the question, how do >>>>>>>>>>>>> I implement components which can wrap lists of arbitrary >>>>>>>>>>>>> component types. >>>>>>>>>>>>> >>>>>>>>>>>>> -- >>>>>>>>>>>>> Regards, >>>>>>>>>>>>> Daniel >>>>>>>>>>>>> >>>>>>>>>>>> -- >>>>>>>>>>> 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 [email protected]. >>>>>>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> -- >>>>>>>>>> There is NO FATE, we are the creators. >>>>>>>>>> blog: http://damoc.ro/ >>>>>>>>>> >>>>>>>>> -- >>>>>>>>> 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 [email protected]. >>>>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>>>> There is NO FATE, we are the creators. >>>>>>>> blog: http://damoc.ro/ >>>>>>>> >>>>>>> -- >>>>>>> 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 [email protected]. >>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>> >>>>>> >>>>>> >>>>>> >>>>>> -- >>>>>> There is NO FATE, we are the creators. >>>>>> blog: http://damoc.ro/ >>>>>> >>>>> -- >>>>> 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 [email protected]. >>>>> For more options, visit https://groups.google.com/d/optout. >>>>> >>>> >>>> >>>> >>>> -- >>>> There is NO FATE, we are the creators. >>>> blog: http://damoc.ro/ >>>> >>> -- >>> 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 [email protected]. >>> For more options, visit https://groups.google.com/d/optout. >>> >> >> >> >> -- >> There is NO FATE, we are the creators. >> blog: http://damoc.ro/ >> > -- > 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/sJl8iB_3EXQ/unsubscribe. > To unsubscribe from this group and all its topics, send an email to > [email protected]. > 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 [email protected]. For more options, visit https://groups.google.com/d/optout.
