5

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.

4 Answers 4

3

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.

1

Use 'checked' instead of value.

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

I think there is a "digest cycle" that needs to complete before you can change the value. If you use a separate button to set the value it updates the UI. If you use setTimeout with a time of 0 in the change handler you can see the UI change briefly before changing back.

Code Follows but you can see it in action at https://developer.salesforce.com/docs/component-library/tools/playground/1pib5bt9_/3

comment out the setTimeout to use the button to set value to option1.

HTML

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

    value={value}

    <button onclick={setAsOne}>set as option1</button>
</template>

JS

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(event) {
        console.log({ event })


        this.value = event.target.value


        // doesn't work
        // this.setAsOne()

        setTimeout(() => {
            this.value = 'option1';
        }, 0);


    }

    setAsOne() {

        this.value = 'option1';
    }
}
0

I think value is bound to the selection at some level though - I tried this simple test where in the UI I set the radio button, and then have a second button that lets me set it back to option1 and it works for me. But I wasn't able to revert it back in the onchange event though...

<template>
    <lightning-card >
       <lightning-button label="Set back to One" slot="actions" class="slds-m-around_medium" onclick={setBacktoOne}></lightning-button>
<lightning-layout-item padding="around-small" size="12" large-device-size="2"  medium-device-size="4" small-device-size="6">
            <lightning-radio-group name="radioGroup"
                                   label="Radio Group"
                                   options={rooptions}
                                   value={rovalue}
                                   onchange={handleROOnChange}
                                   type="radio"></lightning-radio-group>
            </lightning-layout-item>
  </lightning-layout>
</lightning-card>
</template>

@track rovalue = 'option1';

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

    handleROOnChange(event) {
        console.log('option' + event.target.value);
        this.rovalue = event.target.value;//This shows me the right option value based on selection
    }

    setBacktoOne() {
        this.rovalue = 'option1';
    }

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .