JavaScript DOM Scripting By Example Improving the Application Code Next Steps

Brian Foley
Brian Foley
8,439 Points

How to reject duplicate names

Hello, can someone give me a hint to Guil's suggestion of improving this with rejecting duplicate names? Here's my current code for the submit handler. I figure it's with another if statement, but not sure how it would work. Any help is much appreciated!

form.addEventListener('submit', (e) => { e.preventDefault();
const text = input.value; input.value = '';
if (text == 0) { alert("Please enter a name");

} else {

const li = createLI(text);

ul.appendChild(li);

} });

Brian McLaren
Brian McLaren
17,632 Points

Hey were you able to figure it out?

Brian Foley
Brian Foley
8,439 Points

@ Brian McLaren , not yet, but I'm meeting with a mentor today, so hopefully he can help me. I tried doing a for loop and if statement a couple different ways, but no luck. :)

Brian Foley
Brian Foley
8,439 Points

Brian McLaren Steven Parker my meeting w/ my mentor fell through. Gagan's comment below didn't work, but I think it's in the right direction. I'll keep working on this tonight.

8 Answers

Steven Parker
Steven Parker
173,506 Points

It would take a bit more than just an if statement.

You would probably use a loop to step through all the elements currently in the list, and compare the current name to the name of each one. If any matched (so there would be an if statement here), then you would not add the current one and perhaps display some sort of error message instead.

Brian Foley
Brian Foley
8,439 Points

That makes sense. I'll play around with it. Thanks very much!

Steven Parker
Steven Parker
173,506 Points

Since your mentor didn't show up, here's one way to implement what I proposed above:

form.addEventListener('submit', e => {
    e.preventDefault();
    const text = input.value;
    input.value = '';
    for (i=0; i < ul.children.length; i++) {
      if (text == ul.children[i].children[0].textContent) {
        alert("That name has already been entered, try another.");
        return;
      }
    }
    const li = createLI(text);
    ul.appendChild(li);
  });
Brian Foley
Brian Foley
8,439 Points

There it is! Thanks very much! I don't think I would've ever gotten this part:

ul.children[i].children[0].textContent

Steven Parker
Steven Parker
173,506 Points

That's certainly not the only way to get to the name, and probably not the best. I relied on the span being the first child of the list item.

Zsofia Helmeczi
Zsofia Helmeczi
11,357 Points

Hey Steven, I really like your solution. I would only add one more thing to it, that your solution doesn't check for letter cases, e.g "Mark" vs "mark". I would add a .toUppercase to the if condition, like this:

form.addEventListener('submit', (e) => {
    e.preventDefault();
    const text = input.value;
    input.value = '';
    for (i=0; i < ul.children.length; i++) {
      if (text.toUpperCase == ul.children[i].children[0].textContent.toUpperCase) {
        alert("That person has already been invited.");
        return;
      }
    }
    const li = createLI(text);
    ul.appendChild(li);
  });
Steven Parker
Steven Parker
173,506 Points

Since JavaScript is case-sensitive by nature, I wouldn't consider a name with different cases to be a "duplicate". But if you want to exclude similar names with case differences in addition to the duplicates for some reason, you will need to call the toUpperCase() method by adding the parentheses to the end of the method name.

Sorry that I ask you so many questions Steven Parker, but I'm just trying to rap this ish around my brain.

The answer you provided earlier makes the same 'That name has already been used' alert come up each time I enter any name at all.

Would appreciate any advice or hints on how to fix this.

  /*enters name to the list of invitees and checks to see if an empty 
   string is entered or if duplicate names are entered */
  form.addEventListener('submit', (e) => {
    e.preventDefault();
    const text = input.value;
    input.value = '';
    const li = createLi(text);
    ul.appendChild(li);

    const emptyEntry = input.value = '';
    //if text entry submitted is empty, then an alert appears and the empty entry is removed//
    if (text === emptyEntry) {
    alert('You need to add real people');
    ul.removeChild(li);
   }

    for (i=0; i < ul.children.length; i++) {
if (text == ul.children[i].children[0].textContent) {
alert('That name has already been used');
  return;
}
  }

  });
Milad Latif
Milad Latif
6,189 Points

Nathan Angulo

I had the same problem until I moved the, ul.appendChild(li) to the bottom of the submit event listener, after the if and for statements.

That seemed to do the trick!

  form.addEventListener('submit', e => {
    e.preventDefault();
    const text = input.value;
    input.value = '';
    const li = createLi(text);
    if (text === '') {
      alert('Please enter a name');
      ul.removeChild(li);
    }
    for (i=0; i < ul.children.length; i++) {
      if (text === ul.children[i].children[0].textContent) {
        alert("That name has already been entered, try another.");
        return;
      }
    }
    ul.appendChild(li);
  });
Brian McLaren
Brian McLaren
17,632 Points

Wow, Brian Foley, i was thinking the same thing. Thanks for your help Steven Parker

Brian McLaren
Brian McLaren
17,632 Points

Yea I tried the same solutions to no avail. I will keep trying. Good luck. Thanks

i got mine if some one enters an emety string i am still working on local storage and if the name is already in there .. cant seem to figure it out

Anjolaoluwa Akinremi
Anjolaoluwa Akinremi
8,532 Points

After you include those if statement's that checks for something and stops, always make sure to include return false at the end so it does not keep submitting.

Andrew Phythian
Andrew Phythian
19,126 Points

I did this a different, relatively simple way. When the name was entered, I included a line that added it to an array of names, called 'namesArray'.

namesArray.push(text);

As each new name is entered a simple array of those names is built. Adding

console.log(namesArray);

lets you view the updated array as you enter a new name so it's easy to see what's going on.

Then I checked whether a name that has been entered is already in that array using the indexOf() function that we met earlier in the course.

var checkDuplicate = namesArray.indexOf(text);

If checkDuplicate returns a value > -1 then the name already has an index and therefore is in the array. I ran an 'alert' in this case.

One thing... be careful which order you do these tasks in. Add the name to the array after you add it to your list, therefore you won't reject a name from joining the list because it was already in the array.

Steven Parker
Steven Parker
173,506 Points

A clever idea, and it makes the search simpler; but the trade off is having to maintain a separate array with redundant data and keep it in sync with the object array.

Andrew Phythian
Andrew Phythian
19,126 Points

Indeed, editing names causes an issue because the entered name remains in the array after the edit. Therefore running through the list and re-building the array before each name is entered ensures it includes edited names.

At the top, declare the empty array as a variable.

var namesList = []

Before committing an entered name to the list, loop through the list to create an array of the names already in the list

// Loops through names in the list and adds each one to namesList array
for ( var i=0; i<lis.length; i++) {
   var span = lis[i].firstElementChild;
   namesList.push(span.textContent.toUpperCase());
}
// Output the array to the console
console.log(namesList);

Then run a check to see if the array is empty in order to assign a value to 'checkDuplicate'

if ( namesList != [] ) {
   var checkDuplicate = namesList.indexOf(text.toUpperCase());
} else {
   // The variable needs a value in the case of an empty array
   checkDuplicate = 0;
}
// Now that we have assigned a value to 'checkDuplicate' we can reset the array to empty again    
namesList = [];

The final step is to account for an empty field or a duplicate name before committing the name to the list.

if (input.value == '') {
  alert('You have not entered a name!')
} else if ( checkDuplicate>-1 ) {
  alert('You have already entered this name!');
} else {
  const li = createLI(text);
  ul.appendChild(li);
  input.value = '';
}

Not so simple now but the array could always be used in a different context for an additional feature at some point.

Tennyson Horn
Tennyson Horn
14,660 Points

This is a good idea for its simplicity. However, since it uses indexOf, "str" would be blocked if "string" were already on the list. It's a comparatively rare problem when listing names. Especially if using full names, first name + last initial, or something like that. But, if only using one name, the error could be encountered such as with the case of "Jimmy" causing "Jim" to be blocked.

charlotte `Sukhraj
charlotte `Sukhraj
7,570 Points

Form Handler

 form.addEventListener('submit', (e) => {
    e.preventDefault();
    const text = input.value;
    const li = createLi(text);
    input.value = '';
    Check for empty string and spit out alert msg 
    if (text === '') {
      alert('Please enter a name');
      return;
    }
    for (let i=0; i < ul.children.length; i++){
      let li =text[i];
       if (text == ul.children[i].children[0].textContent) {
        alert("That person has already been invited, Please invite another.");
      return;
   }
}
    ul.appendChild(li);   
  });

form.addEventListener("submit",(e) => { e.preventDefault(); const text = input.value; const lis = ul.children; if(input.value === ""){ alert("please enter a valid name!"); }else if (input.value === lis){

  for(var i = 0 ; i < lis.length; i++){
  alert("please enter a differnt name that name has been used");
  return input.value = ""
}

}
  input.value = "";
Brian Foley
Brian Foley
8,439 Points

This didn't work for me. But I think you're going in the right direction. I'll keep working on it later today.