I recently made a small program requirement, where a page uses the textarea small program component, and then clicking on an element on the page will trigger the page to pop up a pop-up window, and then find that textarea placeholder text or input text content will directly through the mask layer and the floating pop-up window. At first, I thought it was because the layer of mask and the floating popover were too small, so I changed it to bigger, but it didn’t work. When I changed it to 99999, it didn’t work either, so I realized it wasn’t my code.

The solution

  • hiddentextarea

This is the simplest solution, usually when popover, there will be a mask layer, hide part of the content under the mask layer, the user will not notice, and then remove the popover and mask layer, and then display the Textarea. It’s simple, it works, and it works in most cases.

<textarea wx:if="{{ showMask }}"></textarea>
Copy the code
  • Using alternative elements

Sometimes, textarea does not penetrate the mask layer, or the mask layer is presented in a translucent form rather than completely covering the content of the page. It is worried that users can see the page jump caused by the disappearance of textarea, resulting in a bad user experience. Instead of hiding the Textarea, you can replace it with a substitute element.

The basic TextaREA component only accepts text input. Without input, it looks like a simple element with a text node. You just need to take the text input in the current state of the TextaREA and give it to a normal element with the same style as the Textarea to achieve temporary substitution effect.

<! -- This is the real Textarea component -->
<textarea id="text-area" value="{{txtRealContent}}" bindinput='txtInput' wx:if="{{! showMask}}" />
<! This is an alternative element to simulate a textarea -->
<view class='rich-text' style="{{('height:' + txtHeight + 'px')}}" wx:else>
  <rich-text nodes="{{txtRealContent}}"></rich-text>
</view>
Copy the code

As shown above

  • Because of the need for real-time accesstextareaHas entered the content, so givetextareaThe element is added with abindinputThe listener
  • showMaskUsed to indicate whether a mask layer (or any other floating element that may be penetrated by a Textarea) is displayed, and if so, hiddentextareaElement and display alternative harajuku
  • heretextareaThe hidden use ofwx:if“Will make it completely disappear from the page, and when it reappears,textareaThe element will be recreated, missing the original input, so we add avalueProperty, and its valuetxtRealContentIt’s cachedtextareaText content that has been entered; If you don’t use this method, don’t lettextareaFully displayed, but only hidden, as in usehidden="{{ showMask ? true :false }}"Because it doesn’t involvetextareaDelete and rebuild, so there is no need to addvalueProperty to control the text content.
  • textareaIt is possible to enter newline text content, so it is used hererich-textComponent, while using, I foundrich-textThere seems to be no support for overflow hiding, so we added an extra layer on top of itviewComponent and set its height to andtextareaThe same

If the textarea contains newline text, the newline character should be processed:

textareaContent.replace(/\n/g.'<br/>')
Copy the code

If you want the textarea to increase its height automatically instead of fixing it, and you add auto-height to the Textarea, then you need to get the height in real time, which is not real time, regardless of the other style changes, the height of the textarea depends on the number of lines. Its height changes every time you add or subtract a line, so you just need to monitor the number of lines in its content, which happens to be the same monitor that the Textarea component already provides: Bindlinechange.


Principle said, the complete example code is as follows:

index.wxml

<view class="page-body">
  <button bindtap="changeMaskVisible">Switch the mask</button>
  <view class="textarea-wrp">
    <textarea id="text-area" value="{{txtContent}}" bindinput='txtInput' bindlinechange="textAreaLineChange" wx:if="{{! showMask}}" auto-height />
    <view class='rich-text' style="{{('height:' + txtHeight + 'px')}}" wx:else>
      <rich-text nodes="{{txtRealContent}}"></rich-text>
    </view>
  </view>
  <button>Footer</button>
  <view wx:if="{{showMask}}" bindtap="changeMaskVisible" class="mask">
    <view class="mask-content"></view>    
  </view>
</view>
Copy the code

index.js

Page({
  data: {
    txtRealContent: ' '.txtContent: ' '.showMask: false.txtHeight: 0
  },
  textAreaLineChange(e) {
    this.setData({ txtHeight: e.detail.height })
  },
  txtInput(e) {
    this.setData({ txtContent: e.detail.value })
  },
  changeMaskVisible(e) {
    if (!this.data.showMask) {
      // Convert a newline character to a wXML-recognized newline element.
      const txtRealContent = this.data.txtContent.replace(/\n/g.'<br/>')
      this.setData({ txtRealContent })
    }
    this.setData({ showMask:!this.data.showMask })
  }
})
Copy the code

index.wxss

.rich-text {
  overflow: hidden;
}
.mask {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background-color: rgba(0, 0, 0, 6);z-index: 10;
}
.mask-content {
  position: fixed;
  top: 44%;
  left: 50%;
  height: 60%;
  width: 60%;
  transform: translate(50%, 50%);background-color: yellowgreen;
  z-index: 12;
}
Copy the code