0

Is it possible to loop through each input and see if a specific border color exists ?

Currently I'm using a keyup event that triggers an ajax request to validate form input. That works well and if an error is noted the input has a style applied:

'border': '1pt solid #ff00ff', 'color': '#ff00ff'}

I also add an error message to a status DIV. What I need to do is clear the status but on when all errors have been addressed. As each error is cleared the color is removed from the border.

I have tried counting the errors and storing the count in localstorage, but if the user keeps entering a valid value in a field, the count is decreased which results in the status being cleared when it shouldn't be.

So can I check any input where the name starts with name, id or cell and if any have the border color #ff00ff then keep the status message otherwise remove the message from #status ?

Thanks

Rocket
  • 1,065
  • 2
  • 21
  • 44
  • I would rather suggest to check for `class`. Create `error` class which will have necessary border styling and then just check for its availability – Rajesh Sep 21 '16 at 08:21
  • I agree with @Rajesh. On input focus remove the relevant error class from the input and the corresponding div. Traversing the dom each time is really unefficient – Lelio Faieta Sep 21 '16 at 08:24

3 Answers3

2

As has been pointed out, this kind of thing is not usually done by setting borders and checking what borders are set. It's possible to do it that way, but it's cumbersome and error-prone.

A much easier way to manage element state (and "valid"/"invalid" is element state) would be to use CSS classes - especially if you want to modify the visual style of an element.

Here is what I would do. Add a CSS class "has-error" to your stylesheet.

/* by default, the error status is not shown */
.error-status {
  display: none;
  border: 1px solid red;
}

/* in a form that has an error, the error status is visible */
form.has-error .error-status {
  display: block;
}

Now, upon validation,

  1. Remove has-error from the <form> - just in case it had been set previously.
  2. Find all contained <input> elements you are interested in.
  3. Filter them down to those that are invalid (i.e. empty). For those that remain:
  4. Move back to the respective <form>.
  5. Add the has-error class.

This actually works for any number of forms and input elements. If there are no invalid input elements, the last two steps do nothing.

$("#btnVaidate").on("click", function() {
  $("form")
    .removeClass('has-error')
    .find("input[name^='name'], input[name^='cell'], input[name^='id']")
    .filter(function() { return !$.trim(this.value).length; })
    .closest('form')
    .addClass('has-error');
  });
});
Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • Thanks - I've used a variation of this and set the class on the input and then check the count of that class – Rocket Sep 21 '16 at 11:03
  • You can do that as well, or both of it. I find it convenient to have a CSS class on the container (i.e. the form) as well, because: Writing CSS that applies to *"any element inside `form.has-error`"* is easy. Writing CSS that applies to *"a form that contains any `element.has-error`"* is impossible. My answer does not contain any code that shows or hides any elements. All it does is manipulate "state markers". All showing and hiding is done purely via CSS. – Tomalak Sep 21 '16 at 11:06
1

As commented, its better to rely on classes rather than css-property.

Logic:

  • Wrap input and error-label in a div
  • Validate input and if invalid, add class to wrapper div
  • Use css selector to toggle styling.

Following is a sample:

$("#btnSubmit").on("click", function() {
  var valid = validateForm();
  $('#lblError').toggleClass('hide', valid)
  if(valid){
    sendData();
  }
});

$('.content input').on('blur', validateForm)

function validateForm() {
  var formValid = true;
  var inputs = $(".content").find("input[name^='name'], input[name^='cell'], input[name^='id']");
  $.each(inputs, function(i, el) {
    var $el = $(el);
    var valid = $el.val().trim().length > 0;
    formValid = formValid && valid;
    $el.toggleClass('error', !valid);
  });
  
  return formValid;
}

function sendData() {
  console.log("Do your stuff here");
}
input.error {
  border: 1px solid red;  
}
p.error {
  color: red;
}
.hide {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="content">
  <input type="text" name="cell1"/>
  <input type="text" name="id1"/>
  <input type="text" name="nameField"/>
  <input type="text" name="test"/>
</div>
<p id="lblError" class="hide error">This is not a valid value</p>
<button id="btnSubmit">Submit</button>
Community
  • 1
  • 1
Rajesh
  • 24,354
  • 5
  • 48
  • 79
  • Your JS code has a logical mistake in it. Can you see it? :) – Tomalak Sep 21 '16 at 08:59
  • No, I am referring to the fact that your "each" switches the `has-error` class on and off per invalid element, instead of doing it once overall. This way the container will have the class or not, depending on whether the last element in the loop was valid or not. – Tomalak Sep 21 '16 at 09:25
  • Assume your component wrapper contains three input elements: valid, invalid, valid. Now your `.each()` loop switches the `has-error` class: off, on and off. Overall the `has-error` class will be off in this scenario. This is wrong. – Tomalak Sep 21 '16 at 09:30
  • Thanks for this, but it is different to how the page I have is working. I have one status DIV that needs to show if there is an error. Only when there are no errors show it be cleared. I'd also prefer to do this live, not having the user to click the submit button. – Rocket Sep 21 '16 at 10:14
0

This should do it. You iterate through all inputs and check the border-color with jQuerys css() function

$("yourInputs").each(function(e){
  var borderColor = $(this).css("border-color");
  if(borderColor != "#ff00ff"){
     // empty the status div
     $("#statusDiv").empty();
  }else{
     // keep message
  }
});

To check with which string the input starts you should check this thread.

Community
  • 1
  • 1
m1crdy
  • 1,371
  • 2
  • 25
  • 58