jaspervdj / digestive-functors

A general way to consume input using applicative functors
149 stars 71 forks source link

More flexible Heist radio buttons? #43

Open davidsd opened 12 years ago

davidsd commented 12 years ago

I'd like to have more fine-grained control over how my radio buttons are displayed. For instance, I'd like the possibility of wrapping each button/label pair in a span, for styling purposes. My suggestion: instead of having dfInputRadio return simply a set list of nodes, have it bind splices for "dfInputRadio:button" and "dfInputRadio:label" and then run its children with those splices.

Here's a sample implementation:

getParamAttrs :: Monad m => HeistT m [(Text, Text)]
getParamAttrs = do
  node <- getParamNode
  return $ case node of
             X.Element _ as _ -> as
             _                -> []

-- merge the paramNode's attributes with the given element
mergeWithNode :: Monad m => X.Node -> Splice m
mergeWithNode (X.Element t as c) = do
  as' <- getParamAttrs
  return [X.Element t (addAttrs as' as) c]
mergeWithNode n = return [n]

dfInputRadio :: Monad m => View Text -> Splice m
dfInputRadio view = do
  (ref, _) <- getRefAttributes Nothing
  let ref'     = absoluteRef ref view
      choices  = fieldInputChoice ref view
      value i  = ref' `mappend` "." `mappend` i
      button (i, c, sel) =
          X.Element "input"
               (attr sel ("checked", "checked")
        [ ("type", "radio"), ("value", value i)
        , ("id", value i), ("name", ref')
                ]) []
      label (i, c, sel) = X.Element "label" [("for", value i)] [X.TextNode c]
      choiceSplice c = runChildrenWith [ ("dfInputRadio:button", mergeWithNode $ button c)
                                       , ("dfInputRadio:label", mergeWithNode $ label c)
                                       ]
  mapSplices choiceSplice choices

Then in my template I can do

For instance, in my template, I'd like to do

<dfInputRadio ref="myRadio">
  <span class="my-stylish-class">
    <dfInputRadio:button class="some-button-class"/><br />
   And the label is <dfInputRadio:label />
  </span>
</dfInputRadio>
jaspervdj commented 12 years ago

I am currently backpacking through Romania until the 30th of August, I'll look at this when I get back.

Peace, Jasper On Jul 20, 2012 10:30 PM, "David Simmons-Duffin" < reply@reply.github.com> wrote:

I'd like to have more fine-grained control over how my radio buttons are displayed. For instance, I'd like the possibility of wrapping each button/label pair in a span, for styling purposes. My suggestion: instead of having dfInputRadio return simply a set list of nodes, have it bind splices for "dfInputRadio:button" and "dfInputRadio:label" and then run its children with those splices.

Here's a sample implementation:

getParamAttrs :: Monad m => HeistT m [(Text, Text)]
getParamAttrs = do
  node <- getParamNode
  return $ case node of
             X.Element _ as _ -> as
             _                -> []

-- merge the paramNode's attributes with the given element
mergeWithNode :: Monad m => X.Node -> Splice m
mergeWithNode (X.Element t as c) = do
  as' <- getParamAttrs
  return [X.Element t (addAttrs as' as) c]
mergeWithNode n = return [n]

dfInputRadio :: Monad m => View Text -> Splice m
dfInputRadio view = do
  (ref, _) <- getRefAttributes Nothing
  let ref'     = absoluteRef ref view
      choices  = fieldInputChoice ref view
      value i  = ref' `mappend` "." `mappend` i
      button (i, c, sel) =
          X.Element "input"
               (attr sel ("checked", "checked")
                [ ("type", "radio"), ("value", value i)
                , ("id", value i), ("name", ref')
                ]) []
      label (i, c, sel) = X.Element "label" [("for", value i)] [X.TextNode
c]
      choiceSplice c = runChildrenWith [ ("dfInputRadio:button",
mergeWithNode $ button c)
                                       , ("dfInputRadio:label",
mergeWithNode $ label c)
                                       ]
  mapSplices choiceSplice choices

Then in my template I can do

For instance, in my template, I'd like to do

<dfInputRadio ref="myRadio">
  <span class="my-stylish-class">
    <dfInputRadio:button class="some-button-class"/><br />
   And the label is <dfInputRadio:label />
  </span>
</dfInputRadio>

Reply to this email directly or view it on GitHub: https://github.com/jaspervdj/digestive-functors/issues/43

cimmanon commented 11 years ago

I'm also interested in this, but I'm not certain this implementation will help me very much with the form I am currently working on.

Sample form from an old PHP project

Those are not images paired up with the radios, but a collection of divs (designed by the user, they represent content blocks in a newspaper or flyer). If I had access to the name of the view/subview from within the template, I could at least manually write out my own radio element so that it processes correctly upon submission.