0

I want to add button show/hide to lightning-textarea for showing masked values as in lightning-input with type="password". I can simply replace it by '*' characters but it pretty hard to handle input changes (user can paste some text). So I want to read the value as well. Is it possible to use some CSS or any other simple way?

0

2 Answers 2

1

Try this! Basically you have two text areas, you can only be focused on the plain text one, every change you do to the plain text is replicated to the masked

Using a toggle button you can change the opacity of the plain text to hide it and show the masked one

Position both elements in a relative container and set the plain text to a position absolute so both components are rendered in the same place

The monospace makes both text have the same size.

The only bad thing is that the cursor is not visible when masked mode is on

<template>
    <div class="app slds-p-around_x-large">
        <div class="slds-is-relative slds-text-font_monospace">
            <lightning-textarea class={plainTextClass} onchange={onChange}></lightning-textarea>
            <lightning-textarea class="over-textarea" onfocus={onFocus}></lightning-textarea>
        </div>

        <div class="slds-grid slds-grid_align-space">
            <lightning-button variant="brand" label="Value" onclick={onClick}></lightning-button>

            <lightning-button variant="brand" label="Toggle" onclick={onToggle}></lightning-button>
        </div>

    </div>
</template>
.plain-textarea {
    position: absolute;
    opacity: 0;
    top: 0;
    right: 0;
    left: 0;
    bottom: 0;
    z-index: 25;
}

.plain-textarea.show {
    opacity: 100;
}
import { LightningElement } from "lwc";

export default class App extends LightningElement {

  showPlain;

  get plainTextClass() {
    return [
      'plain-textarea',
      this.showPlain && 'show',
    ].filter(a => a).join(' ');
  }

  get plainTextarea() {
    return this.template.querySelector('.plain-textarea');
  }

  get overTextarea() {
    return this.template.querySelector('.over-textarea');
  }

  onClick() {
    console.log(`plain -> ${this.plainTextarea.value}`);
    console.log(`over -> ${this.overTextarea.value}`);
  }

  onChange() {
    const skipped = new Set([' ', '\n'])
    this.overTextarea.value = (this.plainTextarea.value)
      .split('')
      .map((character) => skipped.has(character) ? character : '*')
      .join('');
  }

  onFocus() {
    this.plainTextarea.focus()
  }

  onToggle() {
    this.showPlain = !this.showPlain;
    this.plainTextarea.focus();
  }
}

Live example!!: https://webcomponents.dev/edit/Cyncg4uCBEJArw0Ihd1P/src/app.html

1
  • Nice implementation. You may want to update it to make it accessible.
    – POZ
    Feb 2, 2021 at 13:16
0

This is not supported by lightning-textarea. You'll have to create your own custom component starting from the textarea SLDS blueprint.

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