I try to get my head around elm-parts. My goal is to have 3 levels of nested components: A -> B -> Counter
I base my attempts on https://github.com/debois/elm-parts/tree/master/examples I have added the following function to Counter: render1 : Parts.Get Model c -> Parts.Set Model c -> (Parts.Msg c -> m) -> c -> Html m render1 g s = Parts.create1 view update g s and defined a B component to have : type alias Model = { counterA : Counter.Model, counterB : Counter.Model } type Msg = Reset | CounterMsg (Parts.Msg Model) view : Model -> Html Msg view model = div [] [ Counter.render1 .counterA (\m c -> {c | counterA = m}) CounterMsg model , Counter.render1 .counterB (\m c -> {c | counterB = m}) CounterMsg model --, Counter.render CounterMsg [1] model , button [ onClick Reset ] [ text "RESET" ] ] Question: How do I define an A component to again have pair of B components and its model to be: type alias Model = { bA : B.Model, bB : B.Model } Such example would actually be very useful to compose component based apps (and libs) Many thanks, Daniel On Thursday, 19 May 2016 10:33:51 UTC+1, debois wrote: > > They both have been already: > > http://package.elm-lang.org/packages/debois/elm-mdl/4.0.0/ > http://package.elm-lang.org/packages/debois/elm-parts/2.0.0/ > > > On Thursday, May 19, 2016 at 11:27:46 AM UTC+2, Daniel Kwiecinski wrote: >> >> Any plans to update elm-mdl and elm-parts to 0.17? >> >> On Thursday, 19 May 2016 07:32:23 UTC+1, debois wrote: >>> >>> As I understand it, you want to write a function which takes a list of >>> TEA components, then wires up and renders those. As Peter pointed out, this >>> can be done when your "components" are really just view functions. If they >>> are actual TEA components, each with (view, update, Model, Message, >>> Subscription), there's a problem in that you'll need, someplace, a type >>> that can host "Model" for any such component. I don't think Elm has such a >>> type. >>> >>> I wrote a library for treating TEA-components uniformly ( >>> https://github.com/debois/elm-parts); elm-mdl uses that. It gets most >>> of the way, but in the end, to use it, you have to make a record that >>> contains every type of Model you are treating. Elm-mdl does it like so: >>> https://github.com/debois/elm-mdl/blob/master/src/Material.elm#L178-L190 >>> . >>> >>> I wrote a blog post about how this is achieved: >>> https://medium.com/@debois/elm-components-3d9c00c6c612#.x5mtskkmg. >>> (It's phrased in 0.16 terms, though.) >>> >>> >>> >>> On Wednesday, May 18, 2016 at 6:38:45 PM UTC+2, Daniel Kwiecinski wrote: >>>> >>>> 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 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.
