nanohtml icon indicating copy to clipboard operation
nanohtml copied to clipboard

Support && operator-based conditionals in expressions

Open timwis opened this issue 8 years ago • 8 comments

What do you think of supporting && operator-based conditionals in interpolated expressions?

Current syntax:

html`<input type="checkbox" name="reviewed" ${data.reviewed ? 'checked' : ''} />`

Proposed syntax to support:

html`<input type="checkbox" name="reviewed" ${data.reviewed && 'checked'} />`

The proposed syntax is simply more succinct, and I believe it's popular in the react ecosystem. While the above example doesn't save much text, the : '' gets in the way more when you have multi-line expressions -- it becomes a trailing piece that is often overlooked.

Currently, the proposed syntax works in bel if the first condition is truthy, but if it is falsy, bel renders its falsy value, and you'd end up with <input type="checkbox" name="reviewed" undefined />. I believe the way around this would be for bel (or maybe hyperx?) to not return anything from an interpolated expression that evaluates to undefined or false. I believe this is how JSX does it.

If for some reason you want to render undefined or false, I think it would be reasonable to convert it to a string (since it's a string once it's in the DOM anyway). I think the exception to this would be the value 0 -- it may be unexpected to have to convert 0 to a string just to render it to the DOM. 0 comes in to play when you want to do ${rows.length && 'foo'} vs. ${rows.length > 0 && 'foo'}.

/cc @yoshuawuyts

timwis avatar Oct 02 '16 17:10 timwis

I'm on board with this; seems useful enough and can't think of a reason to render the value undefined like ever

yoshuawuyts avatar Oct 02 '16 23:10 yoshuawuyts

I don't think we have much control over what happens within the expression of a template literal.

Although I think we should just make it smarter about interpreting booleans for attributes:

html`<input type="checkbox" name="reviewed" checked=${data.reviewed} />`

Would render if true:

<input type="checkbox" name="reviewed" checked="checked" />

and if false:

<input type="checkbox" name="reviewed" />

shama avatar Oct 15 '16 02:10 shama

I agree with this issue, it is actually implemented with Babel/JSX. Those falsy values should be forgotten (not numbers):

  • false
  • null
  • undefined
  • empty string

Let's compare:

❌ html`<input value="${data.value ? data.value : ''}" />`
✅ html`<input value="${data.value}" />`

Declarative conditional

❌ html`<div>${data.alert ? html`<x-alert />` : ''}</div>`
✅ html`<div>${data.alert && html`<x-alert />}</div>`

Declarative switch case with three ternary operators

❌ html`<div>${data.option === 1 ? html`<x-option1 />` : (data.option === 2 ? html`<x-option2 />` : html`<x-option3 />`)}</div>`
✅ html`<div>
${data.option === 1 && html`<x-option1 />}
${data.option === 2 && html`<x-option2 />}
${data.option === 3 && html`<x-option3 />}
</div>`

The idea is to keep it declarative (no if/else/swtich) and lisible as possible.

What do you think?

vladimirkosmala avatar Dec 14 '17 17:12 vladimirkosmala

I’m on board with this idea

bcomnes avatar Dec 14 '17 21:12 bcomnes

Are there any advancements on this ? It seems that it is "supported" syntaxwise but a false value is rendered as the string "false".

I think that it would be best to suppress falsey outputs from the expressions - the only issue being rendering "false" from ${false}, but I think this is much less useful than the simpler conditional rendering ^^.

Thoughts ? Should be an easy fix.

weepy avatar May 10 '19 09:05 weepy

I'm going to be diving back into the Choo ecosystem in a big way over the coming months. This is something I would like to see land as well.

bcomnes avatar May 10 '19 15:05 bcomnes

The type tests in hyperx show that the following values will render empty:

  • null
  • undefined
  • empty string (test is not written, but I wrote a test and will submit a PR)

0 does not render empty thankfully.

I see only two problems making this change.

  1. Change false to render empty would be a breaking change
  2. I have no idea where in the code to make that change because the code is rather dense. So I could use a hand with that (@goto-bus-stop ?)

mjstahl avatar Jun 21 '19 00:06 mjstahl

@mjstahl yeah, hyperx is not an easy codebase. i'd have to go in with some console.logs myself to be sure, but I think the places to look at would be the places that call strfn and concat. Those functions are used to stringify text and attribute values and to concatenate them if there is a ${templatePart} inside.

goto-bus-stop avatar Jun 21 '19 09:06 goto-bus-stop