Any tricks for storing a Msg in a Model?

I have a simple scenario where I have a confirmation dialog box (OK / Cancel) and I’m passing the component a Msg to run when clicking OK. This Msg should be defined by the update action that decided to open the dialog box and thus stored in the model. In short, I have an action that I want to potentially perform later by saving it in the model.

This creates an import cycle between the Model and Msg modules. I know one way around this is combining those two modules, but I’d prefer not to as both are quite large and I want to keep a clean separation of concerns.

I could create a second message type specifically for these deferred actions, but this seems ugly.

Are there any solutions beyond combining the two modules for storing a deferred message in a model?

Would moving the update function into its own third module solve your circular dependency?

I took another look at my Msg type and realized I didn’t need the entire Model type there so I broke it up into parts that don’t reference Msg and can be imported by it. Thanks for nudging me in the third module direction.

Hi,

IMHO Msg and Model are not two separate concerns - the first indicates actions on the second and update ties both up .

Anyway - it leads usually to a bit of boiler-plate code but you can always parametrize your Model and or Msg if you want to have nested components.
I like to do something like this:

model Component

type alias Embedding baseModel baseMsg =
  { getModel : baseModel -> Maybe Model
  , setModel : Model -> baseModel -> baseModel
  , mapMsg : Msg -> baseMsg
  , yourBaseAction : DesiredParameter -> baseMsg
  }

type alias Model = { ... }

type Msg = ...

update : Embedding baseModel baseMsg -> Msg -> baseModel -> (baseModel, Cmd baseMsg)
update emb msg baseModel =
   case emb.getModel of
      Nothing -> (baseModel, Cmd.none)
      Just model ->
           let (newModel, cmd) = handleMsg msg model
           in (emb.setModel newModel baseModel, Cmd.map emb.mapMsg cmd)

the idea is for Embedding to be a prism/lens-like accessor to your component from the view-point of the enclosing parent-compenten/page and if you like you can just pass out Cmd baseMsg for the embedded parent-messages (use the Task.succeed/Task.perform trick to get an Cmd for a message)

I would create a new DialogAction type and a msg ConfirmedDialogAction DialogAction.

In your model you would have a field

type alias Model =
    { dialogAction : Maybe DialogAction
    }

In the update function you can then both define the DialogAction as well as resolve it once the dialog has been confirmed.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.