[SalesForce] How to change lightning-radio-group selected value programmatically

If a lightning-radio-group has two options, and a user selects one, I want to programmatically have the UI changed back to the other one.

Link to a playground with a simple example. (code copied below)

import { LightningElement, track } from 'lwc';

export default class RadioGroupRequired extends LightningElement {
    @track value = 'option1';

    get options() {
        return [
            { label: 'Option one', value: 'option1' },
            { label: 'Option two', value: 'option2' },
        ];
    }

    handleOnChange(evt) {
        this.value = 'option1';
        // how to make the UI select Option one?
    }
}

And the html:

<template>
    <lightning-radio-group name="radioGroup"
                           label="Radio Group"
                           options={options}
                           value={value}
                           required
                           type="button"
                           onchange={handleOnChange}></lightning-radio-group>

                           value={value}
</template>

Output

I think that there is no rerendering because the bind variable, {value} doesn't actually change. However, the selected state of the lightning-radio-group does, and I want to be able to change it back. How can that be achieved?

I did not notice any methods or attributes that would seem to do the trick in the lightning-radio-group specification.

Best Answer

Here you go.

The primary technique I like using for intercepting events that any base component doesn't have is to wrap it with a div or span.

The relevant parts are:

<div onclick={handleValueIntercept}>
  <!-- some base component or whatever -->  
</div>
handleValueIntercept(evt) {
  if (evt.target.value === 'option1') {
    evt.preventDefault();
  }
}

However, using this technique I dont know for sure if you can "flash" the option 2 back selection to quickly revert to option 1 in the base component, to give the user a little UI feedback because otherwise it may be confusing why option 2 appears clickable...but it's not letting you.

I feel like you should be able to if you just control it in this intercept function, but I hope this gets you started!

EDIT: Actually, I realized that the order of the event and value setting wasn't working in my favor, so what I did was something else entirely. I will leave that answer up there just to showcase how to intercept clicks (but the value was being set after the click, so it was moot).

Here's a working version, complete with the reset to normal - albeit not pretty.

What's happening here is important in these two parts:

<div if:true={showRadioGroup}>
  <!-- something you want to reset -->
</div>
handleChange(evt) {
  const selectedValue = evt.detail.value;
  if (selectedValue === 'option2') {
    // this allows the render cycle to delay just long enough to "reset" state
    this.showRadioGroup = false;
    window.clearTimeout(this.delayTimeout);
    this.delayTimeout = setTimeout(() => {
      this.showRadioGroup = true;
    }, 0);
  } else {
    this.value = selectedValue
  }
}

As far as I can tell, this component does not take into account the value state as matching which color is highlighted, so programmatically passing it in after an event change doesn't seem to fly.

Related Topic