is there a neater way to conditionally apply modif...
# compose
x
is there a neater way to conditionally apply modifiers than
Copy code
modifier = modifier
  .let { if(canBeExpanded) it.clickable { expanded = !expanded } else it }
f
you can use
then
,
Copy code
modifier = modifier.then(
   if (condition) Modifier.clickable {} else MOdifier
)
x
not sure if that's any neater though
Copy code
modifier = modifier
  .then( if(canBeExpanded) Modifier.clickable { expanded = !expanded } else Modifier)
  .run { if(canBeExpanded) clickable { expanded = !expanded } else this }
trying to avoid that
else
part,
apply
compiles but doesn't seem to work, not sure why
Copy code
.apply { if(canBeExpanded) clickable { expanded = !expanded } }
f
if you have complex logic, you might want to consider an extension function, or using
composed
for simple logic
then
seems to be the preferred approach, if you check the compose code that's what it uses under the hood, for instance
Copy code
@Stable
@Suppress("ModifierInspectorInfo")
fun Modifier.fillMaxWidth(/*@FloatRange(from = 0.0, to = 1.0)*/ fraction: Float = 1f) =
    this.then(if (fraction == 1f) FillWholeMaxWidth else createFillWidthModifier(fraction))
👍 1
x
Extension like this
Copy code
fun Modifier.on(condition: Boolean, block: Modifier.() -> Modifier): Modifier =
  if(condition) block() else this
can make the call site look like
Copy code
modifier = modifier
  .on(canBeExpanded) { clickable { expanded = !expanded } }
but this comes at the cost of indirection i guess
f
in your particular case, couldn't you always have the clickable modifier and then use
enabled
to control whether it's actually clickable?
x
how so?
f
using this version of
clickable
Copy code
fun Modifier.clickable(
    enabled: Boolean = true,
    onClickLabel: String? = null,
    role: Role? = null,
    onClick: () -> Unit
)
with
enabled = condition
x
ah much simpler 👍 thanks
👍 1
a
Copy code
/**
 * Convenience for modifiers that should only apply if [condition] is true.
 * [elseFn] useful for conditional else-logic.
 */
inline fun Modifier.thenIf(
    condition: Boolean,
    modifierFn: Modifier.() -> Modifier,
) = this.let {
    if (condition) {
        it.modifierFn()
    } else {
        it
    }
}


/**
 * Convenience for modifiers that should only apply if [condition] is true.
 * [elseFn] useful for conditional else-logic.
 */
inline fun Modifier.thenIf(
    condition: Boolean,
    modifierFn: Modifier.() -> Modifier,
    elseFn: Modifier.() -> Modifier,
) = this.let {
    if (condition) {
        it.modifierFn()
    } else {
        it.elseFn()
    }
}
we use these functions extensively for this specific use case
c
I asked about something similar a while back: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1638332547357800
z
For the record,
apply
doesn't work because apply returns its receiver, not the last expression in the lambda. You'd want
run
or
let
.
2