SamDasti
SamDasti

Reputation: 87

autocomplete suggest from multiple columns and prevent duplicate

I want autocomplete value from two columns of MySql database table, One column have multiple similar values, In autocomplete window in case of similarity it should only display one of the similar values. And after select it should not be suggested in autocomplete window in next row.

HTML

<tr>
    <td><input type="text" data-type="aTeam"  id="team_1" class="team"></td>
    <td><input type="text"  id="score_1" ></td>
</tr>
<button type="button" id="addRow">Add Row</button>

JS

$(document).on('focus','.team',function(){
var type = $(this).data('type');
if(type ==='aTeam' )autoTypeNo= 0;
$(this).autocomplete({
    source: function( request, response ) {
        $.ajax({
            url : 'fetch.php',
            dataType: "json",
            method: 'post',
            data: {
               name_startsWith: request.term,
               type: type
            },
             success: function( data ) {
                 response( $.map( data, function( item ) {
                    return {
                        label: item.aTeam,
                        value: item.aTeam,
                        data : item
                    };
                }));
            }
        });
    },
    autoFocus: true,            
    minLength: 1,
    select: function( event, ui ) {                         
        id_arr = $(this).attr('id');
        id = id_arr.split("_");
        $('#team_'+id[1]).val(ui.item.data.aTeam);
        $('#score_'+id[1]).val(ui.item.data.score);
    }               
  });
});

//add row
   var i=$('table tr').length;
   $("#addRow").on('click',function(){
       html = '<tr>';
       html += '<td><input type="text" data-type="aTeam" id="team_'+i+'" class="team"></td>';
       html += '<td><input type="text" id="score_'+i+'"></td>';
       html += '</tr>';
       $('table').append(html);
       i++;
   });

PHP

<?php
    require_once("config.php");

    if(!empty($_POST['type'])){
       $type = $_POST['type'];
       $name = $_POST['name_startsWith'];
       $query = $db->prepare("SELECT aTeam, bTeam FROM teams where UPPER($type) LIKE '".strtoupper($name)."%' limit 10 ");
       $query->execute();
       $data= array();

   $i = 0;
       while ($row = $query->fetch(PDO:: FETCH_ASSOC)) {

           $data[$i]['aTeam'] = $row['aTeam'];
           $data[$i]['bTeam'] = $row['bTeam'];
           $data[$i]['score'] = $row['score'];
   ++$i;
       }  
       echo json_encode($data);
  }

Upvotes: 1

Views: 2042

Answers (1)

Sally CJ
Sally CJ

Reputation: 15620

Try this: (read the // {comment here} and just compare the code with yours to see what changed)

$(document).on('focus','.team',function(){
let type = $(this).data('type');

// `autoTypeNo` isn't used anywhere, so I commented out this.
//if(type ==='aTeam' )autoTypeNo= 0;

$(this).autocomplete({
    source: function( request, response ) {
        $.ajax({
            url : 'fetch.php',
            dataType: "json",
            method: 'post',
            data: {
               name_startsWith: request.term,
               type: type
            },
             success: function( data ) {
               let selected = [],
                   uniques = [],
                   choices = [];

               $('tr .team[id^="team_"]').each(function(){
                 let value = this.value.trim().toLowerCase();
                 if (value && selected.indexOf(value) < 0) {
                   selected.push(value);
                 }
               });

               data.forEach(item => {
                 let value = item.aTeam.trim().toLowerCase(),
                     value2 = item.bTeam.trim().toLowerCase();

                 if (uniques.indexOf(value) < 0 && selected.indexOf(value) < 0) {
                   choices.push({
                     label: item.aTeam,
                     value: item.aTeam,
                     data: item,
                     type: 'aTeam'
                   });
                   uniques.push(value);
                 }

                 if (uniques.indexOf(value2) < 0 && selected.indexOf(value2) < 0) {
                   choices.push({
                     label: item.bTeam,
                     value: item.bTeam,
                     data: item,
                     type: 'bTeam'
                   });
                   uniques.push(value2);
                 }
               });

               response(choices);
            }
        });
    },
    autoFocus: true,
    minLength: 1,
    select: function( event, ui ) {
        // Strips the 'team_' part, leaving just the number.
        let id_num = $(this).attr('id').substring(5);

        $(this).val(ui.item.value);
        $('#score_' + id_num).val(ui.item.data.score);
        $(this).attr('data-type', ui.item.type); // Change to the correct type?

        // Cancels default action, so that the above `jQuery.val()` call works.
        return false;
    }
  });
});

//add row
// 'i' is too generic, so I renamed it to 'row_num'.
   var row_num=$('table tr').length;
   $("#addRow").on('click',function(){
       // Increment before used.
       row_num++;

       let html = '<tr>';
       html += '<td><input type="text" data-type="aTeam" id="team_' + row_num + '" class="team"></td>';
       html += '<td><input type="text" id="score_' + row_num + '"></td>';
       html += '</tr>';
       $('table').append(html);

       // Optional, but I like to focus on the `input` in the row that was just added.
       $('#team_' + row_num).select();
   });

UPDATE

I updated the JS code (above).

And note that for the PHP part, I changed the $query from:

$query = $db->prepare("SELECT aTeam, bTeam FROM teams where UPPER($type) LIKE '".strtoupper($name)."%' limit 10 ");

to:

$query = $db->prepare("SELECT aTeam, bTeam, score FROM teams where ( aTeam LIKE '".$name."%' OR bTeam LIKE '".$name."%' ) limit 10 ");

because without the OR bTeam LIKE '".$name."%', for example if you typed "d" and there were no aTeam starting with "d", then you know what would happen..

Upvotes: 2

Related Questions