Dev
Dev

Reputation: 149

AngularJS Avoid duplicates when updating a CRUD table (normal add to table works)

I am trying to create a simple CRUD table that does not allow duplicate names. I have been able to get the duplicate to work when adding a contact to the table, but it does not seem to be working when updating the table.

Below is my simple function that verified uniqueness of a contact:

// (allowed) dupCount is 0 when adding, and 1 when in update
// mode to allow saving the contact without making any changed.
var isUnqiue = function(newContact, dupCount) {
    var returnVal = true;
    var count = 0;

    for (var contact in $scope.model.contacts) {
        if (newContact.name.toUpperCase() === $scope.model.contacts[contact].name.toUpperCase()) {
          count++;
        }
    }

    if (count > dupCount) {
        returnVal = false;
    }

    return returnVal;
}

For some reason, it the duplicate in update mode is not working at all! Even if I update 3 or 4 contacts to the same name, the 'if (count > dupCount) ... ' statement always seem to compare 1 and 1.

Here is a JSFiddle with the entire code: https://jsfiddle.net/7ay9nsLv/

Simple scenario:

Add 'Adam, Smith'
1. Edit 'Adam, Smith', Save without Changing > Good
2. Add 'Adam, Smith' again > Duplicate Error
Add 'Adam, SmithX'
3. Edit 'Adam, SmithX' to 'Adam, Smith' > Duplicate Error

Also note, that the data in the table could be sorted and all, so not sure if passing $index to the controller would be too useful (unless sorting doesn't change the data index).

Upvotes: 0

Views: 563

Answers (2)

developer033
developer033

Reputation: 24894

First you're doing something redudant in your for-loop, you can simply use the Array.prototype.forEach() method to find if the index exists:

// Use named function to stop looping correctly
var indexExists = -1;
$scope.model.contacts.forEach(function loop(contact, index) {
  if (loop.stop) {
    return;
  }
  if (contact.name.toUpperCase() === newContact.name.toUpperCase()) {
    indexExists = index;
    loop.stop = true;
  }
});

or With ES6:

var indexExists = $scope.model.contacts.findIndex(function(contact) {
  return contact.name.toUpperCase() === newContact.name.toUpperCase();       
});

or even using findIndex method of underscorejs:

_.findIndex($scope.model.contacts, function(contact) { return contact.name.toUpperCase() === newName });

Then simply check:

return indexExists == -1 && indexExists !== idx || indexExists === idx && $scope.model.contacts[indexExists].name.toUpperCase() === newName;

It will returns true only if the user doesn't exists or if it exists and it's editing itself.

Now, let's go to the error:

You've commited 2 mistakes:

  1. You're passing the old contact to your unique function, you should pass the new contact.

Change

this:

if (isUnqiue(contact, 1)) {

for:

if (isUnqiue($scope.model.selected, 1)) {
  1. You're attributting the $scope.error to the old contact, it should be this:
$scope.errorContact = $scope.model.selected;

DEMO

Upvotes: 1

SirCapy
SirCapy

Reputation: 295

You should catch duplicate error not on client, but on server)) Create Uniq constraint (or primary key if it doesn't exists) on UserName field. So when you trying put or post duplicate, db throws error. You can catch it and redirect on some error page, or add something error info to response, or just show backend error.

Upvotes: 0

Related Questions