purescript-ocelot icon indicating copy to clipboard operation
purescript-ocelot copied to clipboard

Add `receiver` to typeaheads and dropdowns

Open davezuch opened this issue 6 years ago • 4 comments

Environment

  • Ocelot [v0.14.5]

Current behavior

Currently you can set the initial items for a dropdown or typeahead via either the parent's render function, or the parent's eval by sending the child component the appropriate query. However, the only way to update the items for a dropdown or typeahead is from the parent eval via a child query.

Expected behavior

There are two scenarios for managing the items for a component:

1. letting the child fully manage them

In this scenario, the parent fetches the items once and passes them to the child, or provides the child a function for fetching them itself—as with an async typeahead. In this scenario, the parent needn't ever hold on to the items in its own state. This scenario is currently supported by Ocelot.

2. the parent manages the items

In this scenario, the parent has reason to deal with the items and hold onto them in state, and the child should be able to basically use the items that are managed on the parent state. This scenario is only partially supported, and requires manually updating the child's items.

Currently, the items on the parent's state can be passed to a dropdown like so:

HH.slot unit Dropdown.componont
  { items: state.items
  , selectedItem: state.selectedItem
  , render: renderDropdown
  }

But then when state.items changes, the dropdown component won't be notified. If we update the typeahead and dropdown components with a receiver, we can respond to changes in input from the parent.

davezuch avatar Mar 08 '19 23:03 davezuch

@davezuch Remember when we had a flag for this, called receive or listen or something like that? That way you could decide which behavior you want. If you want the child component to defer management to the parent component, then you'd set listen: true and that would enable the receiver. If not, then you'd set listen: false and that would disable the receiver (and be the current behavior).

thomashoneyman avatar Mar 12 '19 18:03 thomashoneyman

@thomashoneyman I don't recall. We got rid of this though? I was thinking on this more, and I don't think we can support both styles at the same time (without some conditional receiver like you mention), since in the case where we want to have the child manage its items, every time the parent state changes, the child's items will be reset to NotAsked (or whatever initial value is passed via the parent's render).

davezuch avatar Mar 12 '19 18:03 davezuch

@davezuch I implemented it in a branch, but we didn't end up needing it, so we never merged it. It ended up being something like:

type Input = { listen :: Boolean, ... }

data Query a = Receive Input a

component = H.component { receiver: Just <<< Receive, ... }
  where
  eval = case _ of
    Receive input a -> do
      when input.listen do
        H.modify_ _ { items = input.items }
      pure a

so that the receiver query is always run, but it only sets its items to the parent's items when it is listening, and if it is not listening, then it preserves its own items without overwriting them with new input

thomashoneyman avatar Mar 12 '19 18:03 thomashoneyman

@thomashoneyman that seems like a good solution, I might just use it. Thanks!

davezuch avatar Mar 12 '19 20:03 davezuch