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 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.
