15

I was trying if we can validate input in javascript and then post errors on latest lightning:input. But i think it doesn't support such use case.

pattern attribute is there but it cant work when i/p is based on other fields.

The requirement I am trying to achieve is that phone number without spaces should be 11 digits.

Markup:

          <lightning:input type="tel" label="Telephone"
             name="tel" value="{!v.applicant1.Phone__c}" pattern="^[0-9_ ]*$"
             messageWhenPatternMismatch="Phone number is not valid"
             onblur='{!c.checkValidityOfphone}'
             messageWhenBadInput='Phone number should be 11 chars max'
             /> 

Controller:

checkValidityOfphone : function(component, event, helper) {
  console.log('checkValidityOfphone called');
  var inp = event.getSource();
  var val=inp.get('v.value');
  val=val.replace(/ /g,'');
  console.log(val);
  console.log(val.length);
  if(val.length!=11){
    inp.set("v.errors", [{message:"Input not a number: " + val}]);
    console.log('Error Set called');   
    //  inp.get('v.validity').valid=false;
  }
}

According to the given doc, lightning:input does support client side validations. https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/js_validate_fields.htm

18

This is a bit of an old question now, but I've discovered another way which seems pretty legit. The validity attribute of lightning:input is not just for reading the validity, you can also set it. So, write the component like this:

<aura:handler name="change" value="{!v.value}" action="{!c.valueChangeValidation}"/>

<lightning:input aura:id="inputField" 
                 type="text" value="{!v.value}" 
                 label="Enter foo" 
                 messageWhenBadInput="You must say foo" />

And then the controller like this:

valueChangeValidation : function(component, event, helper) {
    var inputField = component.find('inputField');
    var value = inputField.get('v.value');
    if(value != 'foo') {
        inputField.set('v.validity', {valid:false, badInput :true});
        inputField.showHelpMessageIfInvalid();

    }
}

Then, you can write whatever logic you want in that handler method and the result is shown in the normal Lightning way.

  • 1
    Does the solution presented here work still? I'm trying to do some custom validation and this isn't working for me. – ratatoskr Jun 1 '18 at 13:15
  • 1
    Hi @ratatoskr , you have to call 'inputField.showHelpMessageIfInvalid();' after setting the valid flag as false. This displays error message. I have edited the answer to reflect the same – Pranay Jaiswal Jun 4 '18 at 11:23
  • 1
    Thanks @PranayJaiswal, though I've tried that and still nothing. Is this working in Spring '18 orgs? – ratatoskr Jun 5 '18 at 9:06
  • 2
    This is not working anymore. From documentation: "This validity attribute is a read-only object with the following boolean properties." – Daniel Horký Jul 23 '18 at 15:16
  • 5
    @DanielHorký is right, this no longer works, but they gave us something very similar: reasonCmp.setCustomValidity("Error message or blank if valid"); reasonCmp.reportValidity(); – textual Aug 8 '18 at 21:40
4

I noticed a few issues:

  • v.errors is not available in lightning:input though it's available in ui:input. So you'll want to define the errors attribute in your component and iterate over it to display the errors.
  • event.getSource().get('v.value') won't give you the input value here. You can use component.find("tel").get("v.value") instead.

Here's the revised code (I removed value="{!v.applicant1.Phone__c} when testing in my org):

<aura:component >
<aura:attribute name="errors" type="List"/>
<lightning:input aura:id="tel" type="tel" label="Telephone"
         name="tel"  pattern="^[0-9_ ]*$"
         messageWhenPatternMismatch="Phone number is not valid"
         onblur='{!c.checkValidityOfphone}'
         messageWhenBadInput='Phone number should be 11 chars max'
         /> 
<aura:iteration items="{!v.errors}" var="error">{!errors}</aura:iteration>

({
    checkValidityOfphone : function(component, event, helper) {
        console.log('checkValidityOfphone called');
        //var inp = event.getSource();
        var val=component.find("tel").get('v.value');
        val=val.replace(/ /g,'');
        console.log(val);
        console.log(val.length);
        if(val.length!=11){
            component.set("v.errors", ["Input not a number: " + val]);
            console.log('Error Set called');   
        }
    }
})
3

There's a new method on lightning:input named reportValidity() that simplifies validation. The docs describe this method as doing the following:

If the input is invalid, displays the error and returns false. If the input is valid, clears any displayed error and returns true.

Here's a link to the full documentation and you should look for the Input Validation section: https://developer.salesforce.com/docs/component-library/bundle/lightning:input/documentation

Here's an example of how to use this:

const inputField = component.find('input-field-aura-id');
if(inputField.reportValidity()) {
    component.set('v.attributeName', inputField.get('v.value'));
}

I suggest using reportValidity() because it does all the work for you. The other way to do this (described in other answers) is to get a component's validity attribute, check if the valid property is true and if it is, calling showHelpMessageIfInvalid() to display an error message.

  • From the docs: This component supports the following methods. focus(): Sets focus on the element. setCustomValidity(): Sets the custom error message. reportValidity(): If the input is invalid, displays the error and returns false. If the input is valid, clears any displayed error and returns true. checkValidity(): Returns true if the input is valid. – thebrettbarlow Jul 14 '18 at 0:38
  • sweet, thanks for updating you answer =) +1 – glls Jul 14 '18 at 2:05
2

As of API v39.0, checking validity in lightning:input got a lot easier. Here's my controller:

({
    checkValidity : function(component, event, helper) {
        var validity = event.getSource().get("v.validity");
        console.log(validity)
    }
})

and here's my component:

<aura:component >
    <lightning:input aura:id="tel" type="tel" label="Telephone"
                     name="tel"  pattern="^[0-9_ ]*$" maxlength="11"
                     messageWhenPatternMismatch="Phone number is not valid"
                     onblur='{!c.checkValidity}'
                     /> 
</aura:component>

All you have to do is check the validity attribute of your lightning:input, and your configured error messages will appear below it automatically.

  • Note, Diana's answer is correct if you wanted to bring your own validation instead of use the default pattern/maxlength validation by attribute. – Christian Carter Feb 17 '17 at 23:30
  • But your answer perfectly suits to Present scenaio... – user533 May 19 at 2:25
1

I played around with Aidan's accepted answer but couldn't get the showHelpMessageIfInvalid() method to behave reliably. In my case, for some reason it would only show the error message after a user had entered their value, then tabbed off the field THEN came back to the field I was validating and attempted to tab back off again.

I did a quick debug and the validation method was firing on first input...but the error text wasn't showing up. Very frustrating. After beating my head against the proverbial SF wall, I ended up going with a completely custom route. It's a bit more work, but it's pretty reliable and arguably more flexible than the built-in SF method.

The basic idea is to have a lightning:input field and associated a lightning:formattedText field with it via aura:id. This formattedText has a css class that hides it (display:none). When the input field is filled out, onblur throws event, which you can capture. The controller captures the field that threw the event (not shown in code, but I have five or six fields that have this same validation, so I generalized it a bit). Then run your own custom validation. If the validation fails, add a "show" css class which sets the display to flex, showing the error message. Relevant code below:

Component:

<div class="slds-col slds-size_4-of-12">
                <lightning:input type="number" label="FTE" aura:id="genFTE1" step="0.01"
                                 onblur="{!c.validateFTE}"/>
                <p><lightning:formattedText aura:id="fteError" class="error-text" value="Value must be between 0 and .49" /></p>
</div>

Controller:

validateFTE : function(component, event, helper) {
        //Get field that triggered the event
        var field = component.find(event.getSource().getLocalId());
        //Get value of field
        var val = field.get("v.value");
        //Validate entry and show error message if validation is not passed
        if(val < 0 || val > 0.49) {
            $A.util.addClass(component.find("fteError"),"show");
        } else {
            $A.util.removeClass(component.find("fteError"), "show");
        }
    }

CSS:

.THIS .error-text {
    display:none;
}

.THIS .show {
    display:flex;
    color:red;
}
0

Turns out there's actually a spec for U.S. phone numbers called NANP.

So if you're looking for a more comprehensive phone number validation, you could use the following regex, which checks for stuff like extensions. The component below is based on a regex I found on Stack Overflow.

<lightning:input 
    type="tel" 
    value="{!v.someValue}" 
    aura:id="mobile" 
    name="mobile" 
    readonly="{!v.readOnly}" 
    label="Cellular Telephone Number" 
    messageWhenPatternMismatch="Please specify a valid phone format such as (###)-###-#### ext ###" 
    pattern="^(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:\(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*\)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$"/>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.