lwc icon indicating copy to clipboard operation
lwc copied to clipboard

feat(template-compiler): lwc:if, lwc:elseif, lwc:else directives

Open jye-sf opened this issue 2 years ago • 2 comments

Details

This PR ships the if-elseif-else directives into master. These directives are analogous to if-statements in Javascript and enable developers to express else if and else logic in their html templates to conditionally render parts of their template:

<template>
    <template lwc:if={abra}>
        Abra!
    </template>
    <template lwc:elseif={kadabra}>
        Kadabra!
    </template>
    <template lwc:else>
        Alakazam!
    </template>
</template>

The above can be thought of as:

if (component.abra) {
  // render "Abra!"
} else if (component.kadabra) {
  // render "Kadabra!"
} else {
  // render "Alakazam!"
}

Additionally, these directives can be applied to arbitrary elements:

<div lwc:if={renderDiv}>...</div>
<div lwc:elseif={altDiv}>...</div>
<div lwc:else>...</div>

and other components

<c-component lwc:if={renderComponent}></c-component>
<c-alternative lwc:elseif={renderAlt}></c-alternative>
<c-default lwc:else></c-default>

Here's a complex example with nested elements:

<template>
    <template lwc:if={outer.if}>
        <h1>outer if</h1>
    </template>
    <template lwc:elseif={outer.elseif1}>
        <h1>outer elseif</h1>
    </template>
    <template lwc:elseif={outer.elseif2}>
        <template lwc:if={inner.if}>
            <h1>inner if</h1>
        </template>
        <template lwc:elseif={inner.elseif}>
            <h1>inner elseif</h1>
        </template>
        <template lwc:elseif={inner.elseif2}>
            <x-foo lwc:dynamic={trackedProp.foo}></x-foo>
        </template>
        <template lwc:else>
            <h1>inner else</h1>
        </template>
    </template>
    <template lwc:else>
        <h1>outer else</h1>
    </template>
</template>

Similar to if-statements in Javascript, elements with lwc:elseif and lwc:else must be immediately preceded by a sibling lwc:if or lwc:elseif. Each statement is evaluated only if the previous statements in its block evaluate false, and only one of the branches in a block of statements will be rendered. Note that lwc:else does not take an attribute value and will throw an error if one is provided.

With the introduction of these directives, if:true and if:false statements should be considered "legacy" and are now redundant. Documentation will need to be introduced to clearly communicate this change, and we should evaluate how to add warnings to our compiler to un-noisily communicate this moving forward.

High Level Summary of Implementation

  • The template compiler's parser transforms sets of sibling if-elseif-else directives into a tree of nodes representing the different conditional branches.
  • The template compiler's parser keeps track of which slot names are valid/invalid in which branches of the conditional tree to maintain existing validation on duplicate slot names.
  • The template compiler's codegen converts the if-elseif-else tree into ternary operators

Additional Documentation

RFC PR for tracking parser context PR for codegen implementation

Does this pull request introduce a breaking change?

  • ✅ No, it does not introduce a breaking change.

Does this pull request introduce an observable change?

  • ⚠️ Yes, it does include an observable change.

This is a new feature to be used by downstream developers.

GUS work item

jye-sf avatar Aug 29 '22 21:08 jye-sf

The remaining issue with the diffing algo should be addressed by a combination of the Fragment VNodes work and ~~https://github.com/salesforce/lwc/pull/3042/commits/b9cfd81e4bfbdf19612456460d0e90322ac25ce2~~ https://github.com/salesforce/lwc/pull/3047. That PR uses the new Fragment VNodes to mark each if-elseif-else branch so that the diffing algo can patch them.

jye-sf avatar Sep 13 '22 00:09 jye-sf

https://github.com/salesforce/lwc/pull/3047 is now ready to merge and should address the issues with the diffing algo by making use of the VFragments work.

jye-sf avatar Sep 16 '22 20:09 jye-sf

/nucleus test

jye-sf avatar Oct 05 '22 16:10 jye-sf

cc @jmsjtu if-else work just merged! 🎉

jye-sf avatar Oct 05 '22 16:10 jye-sf