0

I'm trying to run a function on ng-blur which will validate the user input against regular expression defined for that field.

What I want to achieve is if the regular expression doesn't matches the user input, I want to turn that specific text field input box border to turn red.

I understand this is a trivial javascript case where we use getElementById() and modify DOM. I'm not able to update the DOM from regular controller.

I cannot use ng-messages,etc as I want to throw error from controller based on which regular expression failed, so I can't write hardcoded ng-messages.

Any insight on how to proceed further will be very helpful.

Code: prop object : This will be retrieved from salesforce server. I'm providing the jist for what is needed to explain the code. Actual response requires lot of pre-processing to make it useful for generating form at runtime with all reference,lookups fields,picklist options pulled from server,etc.

[ 
 { label      : Application Name
   cid        : uniqueId
   typeApex   : CURRENCY
   fieldPath  : application_Name__c
   type       : NUMBER
   value      : ''
   dbRequired : true
   isRequired : false
 },
 {...similar array of JSON object ...},
 {}
]

view.html

<div ng-if="prop.type != 'picklist' && prop.type != 'reference'">
    <label for="{{prop.label}}">{{prop.label}}</label>
    <input type="{{prop.type}}" id="inputFields{!cid}" ng-blur='fieldValidation(prop.fieldPath, prop.typeApex, inputFields{!cid}, $event)' ng-model-options="{updateOn: 'blur'}"  
           class="form-control" name="{{prop.fieldPath}}" ng-model="fieldPathValue[prop.fieldPath]" ng-init="fieldPathValue[prop.fieldPath]=getDefaultValue(prop.type,prop.value)"
           ng-required="isRequired({{prop.dbRequired}}, {{prop.isRequired}})"/>
</div>

Controller:

From here I'm trying to update DOM elements of input text box on error

$scope.fieldValidation = function(fieldPath, type, id, $event) {

   // Hardcoded regular expression for testing, this will be read  from server object
    var myMap = new Map();
    myMap.set("Term__c","^[0-9]+$");
    myMap.set("Loan_Amount__c","[0-9]+(\.[0-9][0-9]?)?");

    var value = $event.target.value; //$event object contains element Id, user input value
    var reg = new RegExp(myMap.get(fieldPath));

    if(!reg.test(value)) {
       //add error message class to selected field
       //display error message on top of field

       $timeout(function(){
         // added $scope.apply recently, not a good practice I understand 
         $scope.$apply(function () {
           $scope.spanId = document.getElementById($event.srcElement.id);
           $scope.spanId.style.borderColor='#ff0000';
           $scope.spanId.style.border='solid';
           }); 
         }, 1000);
        }

1 Answer 1

1

First of all no need to use $apply inside $timeout, as it internally use it. Best practice, Dom Manipulations should not exist in controllers, services or anywhere else but in directives.

.directive('fieldvalidate', [
  function() {
    return {
      restrict: 'A',
      link: function($scope, $element, $attributes) {
        $element[0].onblur = function() {
          //check against regex
          if(){//if failed
            $element[0].style.borderColor='red';
            $element[0].insertAdjacentHTML('afterend', '<div>your message</div>');
          }
        }
      }
    };
  }
]);
Sign up to request clarification or add additional context in comments.

3 Comments

Yea. I understand that $apply shouldn't use it as it can pollute space.I read an article writing it in above style, so tried it. Thanks it works great after some additional modifications as my Regex will be loaded from server based on which controller is getting loaded. I'm loading controller at runtime. I have a doubt though, if regex failed I want to display message in front of editor which failed regex. How can I achieve that. I don't want to hardcode ng-messages with each input fields.
Thanks I was able to do it with little efforts with ng-message
btw afterend is standard token?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.