0

I have made a contact list app which shows the contact details. I want to implement search feature based on name. Now when I type in someone's name it should dynamically change the contact list.

index.html :

var array = [];
function Person(fullName, number, group) {
        this.fullName = fullName;  
        this.number = number;
        this.group =  group;
        array.push(this);
}

Person.prototype.getFullName = function() {
    return this.fullName+' '+this.number+' '+this.group;
}

var p1 = new Person("Jonathan Buell",5804337551,"family");
var p2 = new Person("Patrick Daniel",8186934432,"work");

console.log(array);

/*
function save() {
    localStorage.setItem("array", JSON.stringify(array));
}


function submitToDb() {
    var person = new Person(nameInput.value, numberInput.value, groupInput.value);
   // refresh();
} 

var storedArray = JSON.parse(localStorage.getItem("array"));
function loadLocalStorage() {
    for(var i in storedArray){
        array[i] = storedArray[i]; 
    }
   // refresh(); 
}
loadLocalStorage();
*/

function showContacts() {
    for(var i in array){
        var id = i;
        contactlist.innerHTML +=
        `
        <ul>
        <div>
        <p>Name: `+ array[i].fullName +`</p>
        <p>Number: `+ array[i].number +`</p>
        <p>Group: `+ array[i].group +`</p>
        <button type="button" class="btn btn-warning" onclick="editContact(`+ id +`)">Edit</button>
        <button type="button" class="btn btn-danger">Delete</button>
        </div>
        `
    }
}

showContacts();

function addNew() {
 document.getElementById("search").style.display = 'none';
 document.getElementById("contactlist").style.display = 'none';
 document.getElementById("editcontact").style.display = 'none';
 document.getElementById("addnewcontact").style.display = '';
 document.getElementById("addnewcontact").innerHTML = 
 `
 <form>
      <div class="form-group">
        <label for="inputName">Name</label>
        <input type="text" class="form-control" id="inputName" aria-describedby="namehelp" placeholder="Enter Name">
      </div>
       <div class="form-group">
        <label for="inputNumber">Number</label>
        <input type="text" class="form-control" id="inputNumber" aria-describedby="numberhelp" placeholder="Enter Number">
      </div>
      <div class="form-group">
        <label for="inputGroup">Group</label>
        <input type="text" class="form-control" id="inputGroup" aria-describedby="grouphelp" placeholder="Enter Group">
      </div>
      <button type="submit" class="btn btn-primary" onclick="submittoDB()">Submit</button>
    </form>
 `;
}


function editContact(id) {
    document.getElementById("search").style.display = 'none';
    document.getElementById("contactlist").style.display = 'none';
    document.getElementById("editcontact").style.display = '';
    document.getElementById("editcontact").innerHTML = 
        `
        <form>
          <div class="form-group">
            <label for="InputName2">Name</label>
            <input type="text" class="form-control" id="inputName2" aria-describedby="namehelp" value="`+array[id].fullName+`" >
          </div>
          <div class="form-group">
            <label for="InputNumber2">Number</label>
            <input type="text" class="form-control" id="inputNumber2" value="`+array[id].number+`">
          </div>
          <div class="form-group">
            <label for="InputGroup2">Group</label>
            <input type="text" class="form-control" id="inputGroup2" value="`+array[id].group+`">
          </div>
          <button type="submit" class="btn btn-primary" onclick="saveMe(`+id+`)">Submit</button>
        </form>
        `;
}

/*
function saveMe(id) {
    array[id].fullName = document.getElementById("nameInput2").value;
    array[id].number = document.getElementById("numberInput2").value;
    array[id].group = document.getElementById("groupInput2").value;
}
*/

function deleteMe(id) {
    array.splice(id, 1);
   // refresh();
   // save();
}
.header{
 display:flex;
}

.header>div{
 float: left;
}

.header .title{
 padding-left: 400px;
}

.header .dropdown{
 padding-top: 20px;
 padding-left: 20px;
}

.header .button{
 padding-left: 500px;
 padding-top: 5px;
}

.glyphicon-plus-sign{
 font-size: 50px;
}

#search form .input-group{
 padding-left: 30px;
 padding-right: 30px;
 padding-bottom: 10px;
}

.input-group{
 padding-top: 20px;
}

.form-group{
 padding-left: 30px;
 padding-right: 30px;
}

form .btn-primary{
 margin-left: 30px;
}
<!DOCTYPE html>
<html>
<head>
  <title>Contact List App</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  <link rel="stylesheet" type="text/css" href="index.css">
  <script type="text/javascript" src="app.js"></script>
</head>
<body>

  <div class="header">
    
     <div id="dropdown">
        <div class="dropdown">
           <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Sort by Group
           <span class="caret"></span></button>
           <ul class="dropdown-menu">
             <li><a href="#">All</a></li>
             <li><a href="#">Work</a></li>
             <li><a href="#">Family</a></li>
           </ul>
         </div> 
     </div>

     <div class="title">
       <h2>All Contacts</h2>
     </div>

     <div class="button" id="addButton">
       <p>
         <a href="#">
           <span class="glyphicon glyphicon-plus-sign" onclick="addNew()"></span>
         </a>
       </p>
     </div>
    
  </div>

  <div id="search">
     <form>
      <div class="input-group">
        <input type="text" class="form-control" placeholder="Search">
        <div class="input-group-btn">
          <button class="btn btn-default" type="submit">
            <i class="glyphicon glyphicon-search"></i>
          </button>
        </div>
      </div>
    </form> 
  </div>


  <div id="contactlist" >
        
  </div>


  <div id="addnewcontact">
  
    
  </div>


  <div id="editcontact">
    
  </div>


  
</body>
</html>

Currently I am dynamically populating 3 div tag with id="contactlist" , id="editcontact" id="addnewcontact"

App live demo : https://jsfiddle.net/ap8xvoo7/

screenshot of app: enter image description here

Nihal
  • 5,262
  • 7
  • 23
  • 41
stone rock
  • 1,923
  • 9
  • 43
  • 72
  • 1
    A lot of irrelevant code. I suggest make a simple list and input, this is all you need to the demo. Then if you take this https://stackoverflow.com/a/9127872/949476 it's quite easy to convert into vanilla version. – dfsq Feb 07 '18 at 13:18
  • 1
    What exactly is the question? – Liam Feb 07 '18 at 13:19
  • @Liam When I search in input box say if I type `J` it should show all contacts with starting letter `J` and then if I type `Jon` then it should show `Jonathan` contact only. – stone rock Feb 07 '18 at 13:23
  • That's not a question, see it doesn't have a `?`? That is a statement of what you want. So why can't you do this? What piece of information do you want from us? – Liam Feb 07 '18 at 13:27
  • 1
    I think you need to read [How do I ask a good question?](https://stackoverflow.com/help/how-to-ask) – Liam Feb 07 '18 at 13:29

1 Answers1

3

Lot of irrelevant code in your snippets. But, generally, Array.filter is your friend:

const contacts = [
  { fullName: 'Jonathan Buell', number: 5804337551, group: 'family' },
  { fullName: 'Joey Whatever', number: 5454355351, group: 'family' },
  { fullName: 'Patrick Daniel', number: 8186934432, group: 'work' }
];

contacts.filter(contact => contact.fullName.startsWith('Jo'));
/*
Result:
  [
    { fullName: 'Jonathan Buell', number: 5804337551, group: 'family' },
    { fullName: 'Joey Whatever', number: 5454355351, group: 'family' }
  ]
*/

…but startsWith is case-sensitive, it would return an empty array for lowercase 'jo'.

One solution is to use regex instead:

contacts.filter(contact => contact.fullName.match(/^jo/i));
contacts.filter(contact => contact.fullName.match(/^Jo/i));

/*
The 'i' flag makes matching case-insensitive.
Result is the same as above in both cases. 
*/

You can create a filtering function easily:

const filterContacts = (startLetters, contacts) =>
  contacts.filter(contact =>
    contact.fullName.match(new RegExp(`^${startLetters}`, 'i'))
  );

…and use it like this:

filterContacts('jo', contacts);

/*
Result:
  [
    { fullName: 'Jonathan Buell', number: 5804337551, group: 'family' },
    { fullName: 'Joey Whatever', number: 5454355351, group: 'family' }
  ]
*/

filterContacts('pat', contacts);

/*
Result:
  [
     { fullName: 'Patrick Daniel', number: 8186934432, group: 'work' }
  ]
*/

…and of course bind it to search input change:

searchInput.addEventListener('input', function(event) {
    const startLetters = event.target.value;
    const filteredContacts = filterContacts(startLetters, contacts);
    // …and display filteredContacts in your template
});

Working snippet (requires a modern browser with ES2015 support):

document.addEventListener('DOMContentLoaded', function() {
  const contacts = [
    { fullName: 'Jonathan Buell', number: 5804337551, group: 'family' },
    { fullName: 'Joey Whatever', number: 5454355351, group: 'family' },
    { fullName: 'Patrick Daniel', number: 8186934432, group: 'work' }
  ];

  const filterContacts = (startLetters, contacts) =>
    contacts.filter(contact =>
      contact.fullName.match(new RegExp(`^${startLetters}`, 'i'))
    );

  // populate the list with all contacts after the page is loaded:
  const contactList = document.querySelector('ul');
  contactList.innerHTML = contacts
    .map(contact => `<li>${contact.fullName}, ${contact.number}</li>`)
    .join('');
    
  // filter contacts when user types something into input, and replace the list contents with filtered contacts:  
  document.querySelector('input').addEventListener('input', function(event) {
    const startLetters = event.target.value;
    const filteredContacts = filterContacts(startLetters, contacts);
    contactList.innerHTML = filteredContacts
      .map(contact => `<li>${contact.fullName}, ${contact.number}</li>`)
      .join('');
  });
});
<input />
<ul></ul>

A small bonus: if you want to search anywhere, not just from the start (so 'ni' would match 'Patrick Daniel'), just remove ^ from the regex.

helb
  • 3,154
  • 15
  • 21