I am by no means an elm expert, but I did something very similar in a toy
project I am working on to learn the language/

I think this looks better than the approach using a Cmd. With a Cmd you're
basically asking elm to run something for you and to send you a message
with the result when it's done. Each component should process its own
messages and forward to the children their messages.

That's not what you were doing before the refactoring. The parent update
function was 'stealing' the message that was supposed to be for its child.

update msg model =
    case Debug.log "MSG: " msg of
     SearchForm SearchForm.Search -> -- this message is for the child
       model ! [ getRandomGif model.search ] -- but the parent is handling
it

This looks wrong because your SearchForm.update function is forced to
handle the SearchForm.Search message, which will never get there.

Your refactored code looks much cleaner because the parent is not stealing
the message anymore. Instead you're forwarding the event to where it should
be handled. In the case of your SearchForm, handling means that you just
signal to the parent that something interesting has happened.

While I looked at your code, I thought at another way we can possibly get
around this. What if we make it explicit that the SearchForm.view is not
producing a message for itself but rather a message for its parent?

We can do it this way. Note that I added two functions. One to create the
message that will be handled by the parent and another to wrap the message
we want to be propagated to the child. The second is the equivalent of
App.Map, but we do it in the child instead of the parent.

view : (Model -> a) -> (Msg -> a) -> Model -> Html a
view msgForParent msgForMyself model =
    Html.form [ class "SearchForm", onSubmit (msgForParent model) ]
                     [ input [ placeholder "search for gifs related to..." ,
onInput (msgForMyself UpdateQuery)] []

The parent could then do the following and it will receive a message
telling it that it needs to do a search (and what the query is). The
children is going to receive the UpdateQuery message. You don't need
anymore to add any logic to the update method. Messages will just get to
the right place.

type Msg
   = Search SearchForm.Model
   |  SearchForm SearchForm.Msg

view : Model -> Html Msg
 view model =
   div
     [ class "App" ]
     [ h1 [] [ text "Gimme a gif šŸ‘Š" ]
     , (SearchForm.view Search SearchForm model.search)
     , Error.view model.error
     , Gif.view model.gif
     , p [ class "giphy" ]
       [ text "Powered by "
       , a [ href "http://giphy.com"; ] [ text "giphy.com" ]
       ]
     ]

I'd be happy to hear the opinion of someone with more experience with elm,
just to be sure we're on the right track and we're not misunderstanding
something.

Mario

On Tue, May 17, 2016 at 10:07 AM JoaquĆ­n Oltra <[email protected]>
wrote:

> I've changed my previous attempt so that instead of App knowing about and
> acting on the Msg types from the child SearchForm component, now I'm making
> the SearchForm return an event as suggested in the docs (making the update
> function return extra info for parent).
>
> I'm liking it better than the thing I did before:
> https://github.com/joakin/gimme-gif/commit/d5ed1ef0296bb87f84b12eec0ad8ef95f1630008
>
> This way the parent routes all child msgs to the child, and after update
> sees if there is anything of interest for him:
>
> update msg model =
>   case Debug.log "MSG: " msg of
>     SearchForm sfmsg ->
>       let
>         (sfmodel, event) = SearchForm.update sfmsg model.search
>       in
>         ( { model | search = sfmodel }
>         , case event of
>             Just SearchForm.Search ->
>               getRandomGif model.search
>             Nothing ->
>               Cmd.none
>         )
>
>
> Is this any better?
>
> On Monday, May 16, 2016 at 9:59:05 PM UTC+2, JoaquĆ­n Oltra wrote:
>>
>> Hi, I'm trying to learn how to properly extract components that have a
>> model and update functions to standalone components, but I'm not sure if
>> I'm doing a good job.
>>
>> The guide I've found incomplete on nesting, the todomvc example is just
>> one file, and I can't find good info around. I'd really appreciate some
>> code review.
>>
>> It is the gif app, I'm trying to extract the search form, which has
>> internal state (the query in the input), but also has a message that the
>> parent is interested in (submit on the form) in order to trigger the gif
>> fetching.
>>
>>
>> https://github.com/joakin/gimme-gif/commit/a6bf98da1f7f018a29456930a1886c9fa908bde3
>>
>> Even if the SearchForm doesn't return Cmds, I'm trying to properly merge
>> them with the ones on the parent to get the idea. Would this be how you'd
>> do it?
>>
>> Thanks a lot, my brain hurts from learning, it is nice :)
>>
> --
> 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.
>

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

Reply via email to