I have created the example myself but not sure if it is idiomatic. Please comment. https://github.com/lambder/elm-parts/tree/master/examples
On Thursday, 16 June 2016 17:01:44 UTC+1, Lambder wrote: > > 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.
