29

I have form and form text field which generates dynamically using JSP. And I'm using Jquery validation but want to add functionlaty to prevent duplicate entry in the form.

E.g.

<form name="myForm" id="myForm">
      <input type="text" name="text1" id="text1">
      <input type="text" name="text2" id="text2">
      <input type="text" name="text3" id="text3">
      =
      = 
      N number of form fields
      <input type="text" name="textn" id="textn">

</form>

I want to check if there is any duplicate value entered in the textfield using jQuery validation.

Arslan Ali
  • 17,418
  • 8
  • 58
  • 76
Vicky
  • 9,515
  • 16
  • 71
  • 88

11 Answers11

31

I'm pretty new to jquery validation, but I had a similar issue to solve, I came up with the following solution (using previous answers for inspiration!):

Javascript:

jQuery.validator.addMethod("unique", function(value, element, params) {
    var prefix = params;
    var selector = jQuery.validator.format("[name!='{0}'][unique='{1}']", element.name, prefix);
    var matches = new Array();
    $(selector).each(function(index, item) {
        if (value == $(item).val()) {
            matches.push(item);
        }
    });

    return matches.length == 0;
}, "Value is not unique.");

jQuery.validator.classRuleSettings.unique = {
    unique: true
};

Usage:

<input name="currency1" unique="currency" />
<input name="currency2" unique="currency" />

Demo here: http://jsfiddle.net/mysteryh/bgzBY/

bpromas
  • 684
  • 1
  • 11
  • 25
MysteryH
  • 311
  • 1
  • 3
  • 3
  • If you posted code straight here, the solution wouldn't depend on jsfiddle.net working. – Tom Sep 18 '12 at 06:37
  • Updated my answer to include the code, thanks for the advice! – MysteryH Sep 18 '12 at 09:03
  • Works well, but I had to remove the params argument for some reason. – row1 May 20 '13 at 10:37
  • 1
    For anyone who wants to perform this validation on all html tags that contain unique="foo" attribute just remove [name^='{1}'] from the jQuery.validator.format string. – jr3 May 21 '13 at 14:17
  • You are awesome! This is great and I am going to be using this in applications from now on! btw, I also had to remove [name^='{1}'] from the code to make it work, but other than that it is flawless. – Eric Feb 04 '14 at 21:17
  • I took the liberty to edit the `[name^='{1}']` out of your answer and I also refactored your code to remove unnecessary parts. [fiddle](http://jsfiddle.net/bgzBY/196/). – bpromas Sep 21 '15 at 18:14
  • I want to use this function for form array of inputs but its not working, Please any help will be appreciated ` ` – 4Jean Jun 10 '16 at 10:55
13

Something like this should work:

$(function(){

$('input[name^="text"]').change(function() {

    var $current = $(this);

    $('input[name^="text"]').each(function() {
        if ($(this).val() == $current.val() && $(this).attr('id') != $current.attr('id'))
        {
            alert('duplicate found!');
        }

    });
  });
});

In a nutshell, how this works is: Whenever a user enters something into a text box, JQuery loops through all the text boxes in the form and compares their values with the value that the user just entered, if a duplicate value is found, then alert the user.

Bug Magnet
  • 2,668
  • 5
  • 29
  • 28
12

Define a function that returns a boolean after making assertion on the validity of the value:

const isValidGuid = (value) => {
  const validGuid = /^({|()?[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}(}|))?$/;
  const emptyGuid = /^({|()?0{8}-(0{4}-){3}0{12}(}|))?$/;
  return validGuid.test(value) && !emptyGuid.test(value);
};

Use $.validator.addMethod to enable running of the function upon adding the same class name to an element

$.validator.addMethod("isValidGuid", (value) => isValidGuid(value), "Please select a valid and non empty Guid value.");

Use the class name on your desired element:

<select id="title" class="isValidGuid" title="Please select a title!">
  <option value="00000000-0000-0000-0000-000000000000" selected="selected">(select)</option>
  <option value="33a1eb15-cdbc-4c85-be01-dcb4f393c0a5">Engineer</option>
  <option value="43b5d0f7-4915-41f1-b3b9-d6335299cc22">Physicist</option>
  <option value="d80322f2-bb76-447c-a6ac-77f145bac70d">Technician</option>
</select> 
makeitmorehuman
  • 11,287
  • 3
  • 52
  • 76
  • 9
    Please use `$.validator.addMethod` instead of hacking the plugin. – Farzher Dec 20 '12 at 19:42
  • Downvoted. Editing a plugin directly is not recommended. There are other ways to go about it. – bpromas Sep 21 '15 at 18:15
  • If you ever update to a newer version of the library you lose your fix unless you happen to remember it and can find which code is yours and where in the new version to put it in and test to see if it still works and doesn't break the new library. Where `addMethod` is provided in the API, that is definitely recommended. – jinglesthula Feb 06 '19 at 20:46
7

For what it's worth to new viewers of this post... I couldn't seem to get any of these solutions to work for me (I'm using v1.13.1)... so I did a little Frankensteining and pieced bits and pieces from several answers together to create what I needed (and in turn creating another answer for this question). My scenario was similar to @Vicky in the since that I needed the fields to all be unique. However, if the field wasn't a required field, then it was okay for it to be empty.

Using part of the solution from @XGreen, and the suggestion from @Stephen Bugs Kamenar, this is the solution that I came up with:

Solution

$.validator.addMethod("unique", function(value, element) {
    var parentForm = $(element).closest('form');
    var timeRepeated = 0;
    if (value != '') {
        $(parentForm.find(':text')).each(function () {
            if ($(this).val() === value) {
                timeRepeated++;
            }
        });
    }
    return timeRepeated === 1 || timeRepeated === 0;

}, "* Duplicate");


How to Use

To use this solution, all you need to do is add a class with the value of, unique, to the input fields that you are wanting to be unique:

<input type="text" class="unique" name="firstName" />
<input type="text" class="unique" name="lastName" />

In the example above, jQuery Validate will throw an error if the value of firstName and lastName are the same.


Works with jQuery.Validate v1.13.1 or higher.

Pixel Rubble
  • 1,104
  • 3
  • 14
  • 26
  • Thank you. But what do you mean with:class="unique". For example I have email like this:contactpersonen_email:{ required: "U heeft geen geldig email adres ingevuld", email: "je email is leeg" }, – InfinityGoesAround Mar 04 '16 at 10:28
  • It works in v1.15. For my use I modified it for a dynamic list of text boxes in a table and added a class "error" before returning as below. if(timeRepeated > 1) { $(element).addClass("error"); } That will highlight the offending element. – santon Sep 23 '16 at 00:48
  • I tried this but its not working properly...give some ideas – praveenkumar Oct 05 '16 at 14:41
  • @praveenkumar I've updated my explanation to hopefully make it easier to understand. – Pixel Rubble Nov 02 '16 at 18:32
  • 1
    This is definitely the most elegant answer. Although your script would match all "text" fields, and would only work for text fields. Would be nice to improve by adding a data field to the input, and only matching those. Like `class="unique" data-unique="currency"`. Although this put me on the right track, so upvote for you! – Fran Mayers Nov 24 '16 at 21:22
  • You're absolutely right. I was actually just looking back over this the other day, and was thinking about that specifically. I'll probably update this answer in the next few weeks, but it should be a really easy thing to change. – Pixel Rubble Nov 25 '16 at 15:07
1

This should work:

HTML

<form name="myForm" id="myForm">
   <input type="text">
   <input type="text">
   <input type="text">
   <input type="text">
   <button>Click</button>
</form>

JQuery

$(function(){

    $('button').click(function(){

    var len = $('input').length,i,k;
    $('input').css({'border':'solid 1px #888'})

    for(i=0; i < len; i++){
      var v = $('input:eq('+ i +')').val();
      for( k=0; k < i; k++ ){
        var s = $('input:eq('+ k +')').val();
        if( s == v ){
          $('input:eq('+ i +')').css({'border':'solid 1px #F00'})
          $('input:eq('+ k +')').css({'border':'solid 1px #F00'})
          return false;
        }
       }
     }
  })

})
1
 <input type="text" id= "txtName" class="name" onfocusout="checkName(this)">
 function checkName(thisvalues) {
        var currentval = $('#' + thisvalues.id).val();
        $('.name').each(function () {
            console.log(this.value + ',' + this.id);
            if (currentval == this.value && thisvalues.id != this.id) {
                alert('With' + this.value+ 'name already exists');
            }
        });
    }
copycat
  • 31
  • 6
  • Please add some details and/or info about your code. So the OP, and maybe new users can easily understand your answer. – Dwhitz Jul 25 '17 at 12:07
1

If I'm not mistaken, you could narrow the duplicate comparison down a bit. For example, I just want to look at other fields of the same class, say 'name':

$(parentForm.find('.name')).each(function () {
            if ($(this).val() === value) {
                timeRepeated++;
            }

or maybe:

$('.name').each(function () {
            if ($(this).val() === value) {
                timeRepeated++;
            }
rladd
  • 11
  • 1
0

I won't use the Validator plugin, but, maybe this http://jsfiddle.net/6dbrjbg6/2/ can help:

function ISeeWhatYouDidThere(e) {
    var $repeat = 0,
        $val = e.val(),
        $parent = "#" + e.closest("div").attr("id")
    ;
    if($.trim($val) == "")
        return;
    e.removeClass("ui-state-error");
    $("input", $parent).each(function() {
        if($(this).val() == $val)
            $repeat++;
    });
    if($repeat <= 1)
        return;
    alert("Repetido!");
    e.addClass("ui-state-error");
}
/////////////////////////////////
$("input","div").blur(function(){
    ISeeWhatYouDidThere(
        $(this)
    );
});
Jason Aller
  • 3,541
  • 28
  • 38
  • 38
  • You should avoid posting likes to external sites such as `jsfiddle` without posting a formatted code block. In the event that jsfiddle is down, users will not be able to view your solution. – ptierno Jan 13 '15 at 18:29
0

I know this is an old question and the answer is slightly off track from the original question but I was pulling my hair out for a while as I only wanted to check a specific field VS another specific field and could't get it to work any other way. The jQuery validation comes with an equalTo validator. https://jqueryvalidation.org/equalTo-method/

Which in the source code looks like:

equalTo: function( value, element, param ) {

        // Bind to the blur event of the target in order to revalidate whenever the target field is updated
        var target = $( param );
        if ( this.settings.onfocusout && target.not( ".validate-equalTo-blur" ).length ) {
            target.addClass( "validate-equalTo-blur" ).on( "blur.validate-equalTo", function() {
                $( element ).valid();
            } );
        }
        return value === target.val();
    }

take this code and use the addMethod function like so swapping the === to !==:

jQuery.validator.addMethod("notEqualTo", function(value, element, param) {
        // Bind to the blur event of the target in order to revalidate whenever the target field is updated
        var target = $( param );
        if ( this.settings.onfocusout && target.not( ".validate-equalTo-blur" ).length ) {
            target.addClass( "validate-equalTo-blur" ).on( "blur.validate-equalTo", function() {
                $( element ).valid();
            } );
        }
        return value !== target.val();
        // condition returns true or false
    }, "Values must be unique");

Then apply in rules section:

 'first_name':{
      required: true,
      notEqualTo: '#last_name'
  }
Kyle
  • 667
  • 6
  • 28
0

Here is another slightly modified answer from the previous answers.

This one checks duplicate values against form elements with the same name (which is perfectly valid from an HTML standpoint).

For example:

<input type="email" name="emailField" id="email-1" />
<input type="email" name="emailField" id="email-2" />
<input type="email" name="emailField" id="email-3" />

Note: You don't even need the ID, it's just shown for completeness.

The following custom validator will validate these inputs as having unique values:

$.validator.addMethod('unique', (value, element) => {
    var timeRepeated = 0;
    if (value && value.length)
    {
        $(`input[name=${(element as HTMLFormElement).name}]`).each(function ()
        {
            if ($(this).val() === value)
            {
                timeRepeated++;
            }
        });
    }
    return timeRepeated === 1 || timeRepeated === 0;
});

Note: This is TypeScript, but easily convertible back to pure JS.

Be sure to enable the rule elsewhere, e.g.:

var myValidationRules = {
  emailField: {
    unique: true
  }
}

And put a validation message on the validator definition above, or use the validator.settings.messages property.

qJake
  • 16,821
  • 17
  • 83
  • 135
0

function ISeeWhatYouDidThere(e) {
    var $repeat = 0,
        $val = e.val(),
        $parent = "#" + e.closest("div").attr("id")
    ;
    if($.trim($val) == "")
        return;
    e.removeClass("ui-state-error");
    $("input").each(function() {
        if($(this).val() == $val)
            $repeat++;
    });
    if($repeat <= 1)
        return;
    alert("Repetido!");
    e.addClass("ui-state-error");
}
/////////////////////////////////
$("input","div").blur(function(){
    ISeeWhatYouDidThere(
        $(this)
    );
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="validDiv01">
    <input />
    <input />
    <input />
</div>
<hr />
<div id="validDiv02">
    <input />
    <input />
    <input />
</div>
<hr />
<div id="validDiv03">
    <input />
    <input />
    <input />
</div>

follow this for validate unique input value using jquery