自动完成如何避免重复选择

时间:2019-05-18 12:18:12

标签: javascript jquery jquery-ui-autocomplete

我正在使用JQuery自动完成功能。在这种情况下,我要避免重复选择预选和预定位(预取)列表。

以下脚本适用于当前选择的列表。但是,我该如何使用通过document onload获取的预先定位的列表来做到这一点。

///////////////////////////////////////////////// ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// ////

JS

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

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

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

           data.forEach(item => {
             let value = item.name.trim().toLowerCase();

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

           });

           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);
    $('#id_' + id_num).val(ui.item.data.id).change();
    $('#marks_' + id_num).val(ui.item.data.marks);
    $(this).attr('data-type', ui.item.type); 
    return false;
},
appendTo: $(this).parent()
});
});    

HTML

<table class="table table-bordered table-hover" id="pat_tests">
                            <thead>
                                <tr>
                                    <th>ID</th>
                                    <th>Name</th>
                                    <th>Marks</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td> <input type="number" id="id_1"> </td>
                                    <td><input type="text" id="name_1" class="search" data-type="type"></td>                                    
                                    <td><input type="number" id="marks_1" ></td>
                                </tr>
                                <tr>
                                    <td> <input type="number" id="id_2"> </td>
                                    <td><input type="text" id="name_2" class="search" data-type="type"></td>                                    
                                    <td><input type="number" id="marks_2" ></td>
                                </tr>
                                <tr>
                                    <td> <input type="number" id="id_3"> </td>
                                    <td><input type="text" id="name_3" class="search" data-type="type"></td>                                    
                                    <td><input type="number" id="marks_3" ></td>
                                </tr>
                            </tbody>
                        </table>

                        <h2>Pre Selected List of Students</h2>
                        <p class="selected">Mario</p>
                        <p class="selected">Nico"</p>
                        <p class="selected">Mento</p>

PHP

if(!empty($_POST['type'])){
$type = $_POST['type'];
$name = $_POST['name_startsWith'];
$query = $db->prepare("SELECT id, name, marks FROM class where (name LIKE '".$name."%') ");
$query->execute();
$data = array();

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

    $data[$i]['id'] = $row['id'];
    $data[$i]['name'] = $row['name'];
    $data[$i]['marks'] = $row['marks'];
++$i;
}  
echo json_encode($data);

2 个答案:

答案 0 :(得分:2)

我建议在Js中使用一个数组,您可以在其中放入预选的数组。然后使用它来验证是否尚未将其推入其中,然后可以将其添加到您的dom中。

因此在js中,您会遇到

var selected = [<?= !empty($selected) ? '"'.implode('","', $selected).'"' : '' ?>];

脚本的第一行代码中的上面的代码使数组为空,或者如果选择的不为空,则已经选择 然后您可以使用它来检查是否选择了一个项目。同样最好在PHP中使用$selected = array_map('strtolower', $selected);(根据您的代码)

编辑

<script type="text/javascript">

    //in case you have php array of already selected items. remove it if $selected is not provided in php.
    //var selected = [<?= !empty($selected) ? '"'.implode('","', $selected).'"' : '' ?>];

    var selected = []; 
    $(".selected").each(function(index, value){ 
        selected.push($(this).text().trim().toLowerCase()); 
    });

    $(document).on('focus', '.search', function (e) {
        let type = $(this).data('type');
        $(this).autocomplete({
            source: function (request, response) {
                $.ajax({
                    url: 'your url',
                    dataType: "json",
                    method: 'post',
                    data: {
                        name_startsWith: request.term,
                        type: type
                    },
                    success: function (data) {
                        let uniques = [],
                            choices = [];
                        data.forEach(function (item) {
                            let value = item.name.trim().toLowerCase();
                            if (uniques.indexOf(value) < 0 && selected.indexOf(value) < 0) {
                                choices.push({
                                    label: item.name,
                                    value: item.name,
                                    data: item,
                                    type: 'name'
                                });
                                uniques.push(value);
                            }
                        });
                        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);
                $('#id_' + id_num).val(ui.item.data.id).change();
                $('#marks_' + id_num).val(ui.item.data.marks);
                $(this).attr('data-type', ui.item.type);
                selected.push(ui.item.value.trim().toLowerCase());
                return false;
            },
            appendTo: $(this).parent()
        });
    });
</script>

如果将js加载为外部文件,请不要担心。只要确保定义

<script>
    var selected = [<?= !empty($selected) ? '"'.implode('","', $selected).'"' : '' ?>];
</script>

之前。

答案 1 :(得分:0)

更新的答案: 因为您更改了HTML,所以解决方案可能基于:

if ($('.selected:contains(' + value + ')').length == 0) {

更新的代码段:

$(document).on('focus', '.search', function (e) {
    let type = $(this).data('type');
    $(this).autocomplete({
        source: function (request, response) {
            $.ajax({
                url: 'https://api.github.com/repositories?since=364',
                dataType: "json",
                method: 'get',
                data: {
                    name_startsWith: request.term,
                    type: type
                },
                success: function (data) {
                    data = data.map((a) => ({name: a.name || ''})).filter((e) => e.name.indexOf('_') == -1);
                    let selected = [],
                            uniques = [],
                            choices = [];
                    $('tr .search[id^="name_"]').each(function () {
                        let value = this.value.trim().toLowerCase();
                        if (value && selected.indexOf(value) < 0) {
                            selected.push(value);
                        }
                    });
                    data.forEach(function (item) {
                        let value = item.name.trim().toLowerCase();
                        if (uniques.indexOf(value) < 0 && selected.indexOf(value) < 0) {
                            if ($('.selected:contains(' + value + ')').length == 0) {
                                choices.push({
                                    label: item.name,
                                    value: item.name,
                                    data: item,
                                    type: 'name'
                                });
                                uniques.push(value);
                            }
                        }
                    });
                    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);
            $('#id_' + id_num).val(ui.item.data.id).change();
            $('#marks_' + id_num).val(ui.item.data.marks);
            $(this).attr('data-type', ui.item.type);
            return false;
        },
        appendTo: $(this).parent()
    });
});
<link href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>

<table class="table table-bordered table-hover" id="pat_tests">
    <thead>
    <tr>
        <th>ID</th>
        <th>Name</th>
        <th>Marks</th>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td> <input type="number" id="id_1"> </td>
        <td><input type="text" id="name_1" class="search" data-type="type"></td>
        <td><input type="number" id="marks_1" ></td>
    </tr>
    <tr>
        <td> <input type="number" id="id_2"> </td>
        <td><input type="text" id="name_2" class="search" data-type="type"></td>
        <td><input type="number" id="marks_2" ></td>
    </tr>
    <tr>
        <td> <input type="number" id="id_3"> </td>
        <td><input type="text" id="name_3" class="search" data-type="type"></td>
        <td><input type="number" id="marks_3" ></td>
    </tr>
    </tbody>
</table>

<h2>Pre Selected List of Students</h2>
<p class="selected">invisible</p>
<p class="selected">tinder</p>
<p class="selected">ike</p>

尝试选择火种,仅用于测试。

旧答案:

第一个问题:您在每个焦点事件上初始化自动完成功能!请避免将其初始化多次。

如果我理解正确,您想从自动完成列表中删除具有预选学生列表之一的值的元素。 如果是这样,您可以在 choices.push({一个测试:

if ($('.selected:text[value="' + item.name + '"]').length == 0) {

完整代码:

$(document).on('focus', '.search', function (e) {
    let type = $(this).data('type');
    $(this).autocomplete({
        source: function (request, response) {
            $.ajax({
                url: 'your url',
                dataType: "json",
                method: 'post',
                data: {
                    name_startsWith: request.term,
                    type: type
                },
                success: function (data) {
                    let selected = [],
                            uniques = [],
                            choices = [];
                    $('tr .search[id^="name_"]').each(function () {
                        let value = this.value.trim().toLowerCase();
                        if (value && selected.indexOf(value) < 0) {
                            selected.push(value);
                        }
                    });
                    data.forEach(function (item) {
                        let value = item.name.trim().toLowerCase();
                        if (uniques.indexOf(value) < 0 && selected.indexOf(value) < 0) {
                            if ($('.selected:text[value="' + item.name + '"]').length == 0) {
                                choices.push({
                                    label: item.name,
                                    value: item.name,
                                    data: item,
                                    type: 'name'
                                });
                                uniques.push(value);
                            }
                        }
                    });
                    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);
            $('#id_' + id_num).val(ui.item.data.id).change();
            $('#marks_' + id_num).val(ui.item.data.marks);
            $(this).attr('data-type', ui.item.type);
            return false;
        },
        appendTo: $(this).parent()
    });
});