skip to Main Content

a.) Currently i have a php / html form with input validation using html input patterns.
b.) To show that the input entered is correct, I use the css pseudo property user-invalid / user-valid via a class ‘check_valid’ as below;

input.check_valid:user-invalid     { border: 4px dotted red;   }
input.check_valid:user-valid       { border: 4px solid  green; }

c.) The issue is with textareas and the lack of pattern support. What i do have is;

textarea.check_valid:user-invalid  { border: 4px dotted red;   }
textarea.check_valid:user-valid    { border: 4px solid  green; }

However this ONLY checks minlength / maxlength of the content in the textarea and not the content in the textarea.

However – I have server side validation ( in php ) that checks the content of the textarea and that is working fine. But i would like to add a green / red border like that on the other input fields when the content is as per the pattern ( which carries a regex )

d.) I am looking for a javascript snippet that will mimic the behaviour of check_valid:user-invalid / check_valid:user-valid when the user leaves the textarea after entering some content. The javascript snippet should check the content against a regex ( this achieving pattern support for the textarea )

This is what i have ( incomplete ) so far;

const textArea1 = document.getElementById("textarea1");

textArea1.addEventListener("change", (event) => {

  let patternTextArea1 = ~^[a-zA-Z0-9:s,.'&()/-]{10,550}$~; 
   
  if ( // test textarea content against the regex ) {
  
      // apply user-valid - green border
    
  } else {
  
     // apply user-invalid - red dotted line
    
  }
  
});

My javascript skills is absymal as evidenced above.

Help will be most appreciated.

3

Answers


  1. You are asking how to force an element to be :user-valid or the other :user-invalid. Is this possible? Yes. Using inputField.setCustomValidity(msg). Well actually it will work for :valid and :invalid but we can change CSS for this, and toggle a class .user-interacted to check validity only when user interacted.

    So that’s 2 things: setCustomValidity, and adding a .user-interacted.

    textarea.addEventListener("input", checkOnServer)
    
    function checkOnServer(ev) {
      var elem = ev.target
    
      // this of course will use AJAX to query server
      setTimeout(function() {
        elem.classList.add("user-interacted")
        var value = elem.value
        var msg = value.length > 3 ? '' : 'Length must be longer than 3 chars'
        elem.setCustomValidity(msg)
      }, 100)
    
    }
    textarea.check_valid.user-interacted:invalid {
      border: 4px dotted red;
    }
    
    textarea.check_valid.user-interacted:valid {
      border: 4px solid green;
    }
    
    textarea {
      outline: none;
    }
    <p>let's assume valid is > 3 chars</p>
    <textarea id="textarea" class="check_valid" cols="80" rows="5"></textarea>
    Login or Signup to reply.
  2. When the change event happens on the textarea element you can set the same value on a hidden input element that has the pattern attribute.

    // stop the default invalid message from showing
    document.forms.form01.addEventListener('invalid', e => {
      e.preventDefault();
    }, true);
    
    document.forms.form01.addEventListener('change', e => {
      let form = e.target.form;
      if (e.target.dataset.name) {
        // set the input to have the same value as the textarea
        form[e.target.dataset.name].value = e.target.value;
        // set class name according to validity
        e.target.classList.add('valid');
        if (!form[e.target.dataset.name].validity.valid) {
          e.target.classList.replace('valid', 'invalid');
        }
      }
    });
    
    document.forms.form01.addEventListener('submit', e => {
      e.preventDefault();
      let data = new FormData(e.target);
      console.log(...data);
    });
    form {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    
    textarea.invalid {
      border: 4px dotted red;
    }
    
    textarea.valid {
      border: 4px solid green;
    }
    
    input:user-invalid {
      border: 4px dotted red;
    }
    
    input:user-valid {
      border: 4px solid green;
    }
    <form name="form01">
      <input type="text" name="other" pattern=".{2,10}" required>
      <textarea data-name="longtext" name=""></textarea>
      <input type="text" name="longtext"
        pattern="[a-zA-Z0-9:s,.'&()/-]{10,550}"
        style="display:none" required>
      <button type="submit">Submit</button>
    </form>
    Login or Signup to reply.
  3. Adding pattern check to a textarea

    The textarea element does not have a pattern attribute, but you can add one using a data attribute.

    In the change event you can test the pattern and use setCustomValidity to add a validation message.

    The browser will automatically display the custom message the same way it does minlength, maxlength, and required value checks. The drawback is that they are not localized like the built-in validation messages.

    enter image description here

    There are also pseudo classes for :invalid and :valid that work automatically.

    The example has been kept very simple to show how it works.

    Code Snippet

    const textarea = document.querySelector('textarea')
    
    textarea.addEventListener('change', () => {
      const reg = new RegExp(textarea.dataset.pattern, 'gmi');
      textarea.setCustomValidity('');
      if (reg.test(textarea.value)) {
        textarea.setCustomValidity('Invalid characters in text');
      }
      textarea.classList.add('check_valid');
      textarea.reportValidity();  
    })
    textarea {
      height: 2rem;
      padding: 0.5rem;
      border: 4px dotted black;
    }
    
    textarea.check_valid:valid {
      border-color: green;
    }
    
    textarea.check_valid:invalid {
      border-color: red;
    }
    <textarea 
      required 
      minlength="10" 
      maxlength="500" 
      data-pattern="[^w(),.s]">
    </textarea>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search