I’d like to learn how to reduce code duplication in my Halogen form.
I suspect there’s a way to just reconfigure the input fields in StateRows
and not need to touch any other part of the code. The current version requires updating four places for each new input field (see all repeats of foo
).
@kritzcreek, @cvlad, and @natefaubion shared some tips about using variants and links to these examples on slack a few months ago:
But I haven’t been able to figure out how to successfully apply these techniques to my code.
Here’s the core snippet along with instructions on how to checkout and build the example project:
git clone https://github.com/milesfrain/many_inputs.git
cd many_inputs
spago build
parcel src/index.html --open
type StateRows =
( foo :: String
, bar :: String
, baz :: String
)
type State = Record StateRows
data Action = UpdateState State
handleAction ∷ forall o m. Action -> H.HalogenM State Action () o m Unit
handleAction = case _ of
UpdateState s -> H.put s
mkInput :: forall r l a. IsSymbol l => Cons l String r StateRows =>
SProxy l -> State -> HH.HTML a Action
mkInput sym st =
HH.input
[ HP.type_ HP.InputNumber
, HP.value $ Record.get sym st
, HE.onValueChange \v -> Just $ UpdateState $ Record.set sym v st
]
render :: forall m. State -> H.ComponentHTML Action () m
render state =
HH.div_
[ HH.div_ [ mkInput (SProxy::_"foo") state ]
, HH.div_ [ mkInput (SProxy::_"bar") state ]
, HH.div_ [ mkInput (SProxy::_"baz") state ]
-- Print back to verify state
, HH.div_ [ HH.text $ foldMap (\s -> s <> " ") [ state.foo, state.bar, state.baz ] ]
]
initialState :: forall i. i -> State
initialState _ =
{ foo: ""
, bar: ""
, baz: ""
}
I also recently replaced H.modify_
with H.put
for additional simplification. Is this bad practice? I can’t think of a situation where passing the new state in an action is worse than passing just the state update instructions.