How to emulate "one branch if" to add attributes to Html element?


how to emulate a “one branch if” to add attributes to an Html element when a certain condition is met ?
In imperative languages you can do: say

if condition():

The same problem happens with adding, or not adding Html children nodes to a parent element. What I do in this situation is I use a:

text ""

in the branch when the condition isn’t met.

But there’s no “empty attribute” I can use for attributes (unless I missed that in Elm Attribute library).
What I do is use list concatenation with empty lists when the condition isn’t met, but that makes the code quite heavy and unreadable, and long to type.

Is there a better way?


I think that you’ve come up with the best solutions available already!

The problems you’re describing are ones that I run into fairly often as well. I think that official “empty” Html and Html.Attribute values would be really nice here—just like what you find in the Cmd and Sub modules (with Cmd.none and Sub.none).

However, the Html.Extra package does provide helpers that do basically this already—see Html.Extra.nothing and Html.Attributes.Extra.empty. So you could use those!


Thank you!
I think Html.Attributes.Extra.empty is going to make my code much less heavy.

Note that for Bool conditions and Maybe values there are also the Html.Attributes.Extra.attributeIf and Html.Attributes.Extra.attributeMaybe helpers. You don’t need to actually write an if yourself.


That’s even more readable indeed. Thanks!

I’m writing some code just now and I realize I want to add an attribute when something in my model is Nothing. By any chance would there be an attributeNothing function ? attributeNothing and attributeJust would have covered the two scenarios. With attributeMaybe I’m left with only one possible scenario (wanting to add an attribute when something is Just _). Or is there a function that turn Maybes into Nothings and vice versa ?

You could write your own version, if you’d like. Here’s the definition of Html.Attributes.Extra.attributeMaybe:

attributeMaybe : (a -> Attribute msg) -> Maybe a -> Attribute msg
attributeMaybe fn = fn >> Maybe.withDefault empty

attributeNothing might look like:

attributeNothing : Attribute msg -> Maybe a -> Attribute msg
attributeNothing attr = (always empty) >> Maybe.withDefault attr

A lot of inline conditionals in markup, even when using these helper functions, can get messy. Depending on the situation, I find it is often much nicer to push conditional logic higher up the decision tree. This is especially true if your booleans and maybes have dependencies on each other (although that might also be a sign you need a custom type). Ideally the logic and the markup can be kept separate.

This combos well with a layered approach to designing UI components where lower-level layers provide generic functions that might take more arguments such as extra attributes or child nodes.

An alternative when there are a lot of independent variables is using a builder approach as shown in the Robot Buttons from Mars talk by Brian Hicks.

1 Like
Attrs.attributeIf (foo == Nothing) <| "color" "red"

hey all !

my 2 cents since I haven’t seen it, the thing I personally use to create an empty attribute is classList with an empty list :

emptyAttribute : Attribute msg
emptyAttribute =
    Html.Attributes.classList []

in case someone search for it.


edit: TIL >> Html Extra uses the same trick.


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