单击下一行中的 select2 时如何防止 select2 清除所选值

How to prevent select2 from clearing the selected value when clicking on select2 in next row

我的网络应用程序使用 angularjs 和 php。在该网站中,有一个部分可以由用户添加估算值。它有 select2 作为下拉列表,用于填充库存中的现有项目。

<tr class="valign-top"
   ng-repeat="estimate in workorder.steps[1].estimates track by $index"
   ng-init="item_key = $index">
     <div id="material_div{{$index}}"
            ng-if="estimate.type == 'material'"
            class="create_Wo_forms  inspec_crt_forms margin-0">
            <select
                style="width: 100%!important;"
                id="parts_selected{{$index}}"
                stepIndex="{{estimatesselectedStep}}"
                itemIndex="{{$index}}"
                class="crt-wo-input inspec-input"
                item_wo_create_select>
            </select>
     </div>
</tr>

整个部分在 HTML 文件中的 ng-repeat 中。

directive('itemWoCreateSelect', function () {
    return {
        restrict: 'A',
        link: function (scope, elem, attrs) {
            var stepIndex = attrs.stepindex;
            var elemIndex = attrs.itemindex;
            var item = scope.workorder.steps[stepIndex]['estimates'][elemIndex];
            $(elem).append('<option>' + item['name'] + '</option>');
            scope.selected_items = [];
            angular.forEach(scope.workorder.steps[stepIndex]['estimates'], function (v) {
                if (v['item_id'] && v['item_id'] != null && !(v['item_id'] == item['item_id'] && v['unit_cost'] == item['unit_cost'])) {
                    scope.selected_items.push({ 'item_id': v['item_id'], 'unit_price': v['unit_cost'] });
                }
            });
            var formatRepo = function (repo) {
                if (repo.loading)
                    return repo.text;
                var markup = '<span class="label">';
                if (repo.hasOwnProperty('item_name') && repo.item_name.trim()) {
                    markup += repo.item_name + ' (' + repo.unit_price + ')' + '';
                } else {
                    markup += repo.text + '';
                }
                markup += '</span>';
                return markup;
            };

            var formatRepoSelection = function (repo) {
                if (repo.hasOwnProperty('item_name')) {
                    return repo.item_name + ' (' + repo.unit_price + ')';
                } else {
                    item['name'] = repo.id;
                    return repo.id;
                }
            };
            $(elem).select2({
                placeholder: "Search for item",
                tags: true,
                ajax: {
                    type: 'POST',
                    url: version5Url + 'inventory/getMasterStocksForInvoice',
                    tags: true,
                    data: function (params) {
                        return {
                            token: scope.token,
                            user_id: scope.user_id,
                            client_id: scope.client_id,
                            search: params.term,
                            selected_items: scope.selected_items
                        };
                    },
                    dataType: 'json',
                    delay: 250,
                    processResults: function (data, params) {

                        $(elem).find('option').remove();
                        if (item['item_id']) {
                            delete item['item_id'];
                        }
                        item['unit_cost'] = 0;
                        item['applied_taxes'] = [];
                        item['selected_tax'] = [];
                        item['amount'] = 0;
                        item['quantity'] = 0;
                        item['description'] = '';
                        scope.details = data.parts;
                        scope.$apply();
                        return {
                            results: data.parts,
                            pagination: false
                        };
                    },
                    cache: false
                },
                escapeMarkup: function (markup) {
                    return markup;
                },
                minimumInputLength: 0,
                templateResult: formatRepo,
                templateSelection: formatRepoSelection
            });

            $(elem).on("select2:select", function () {
                var index = parseInt($(elem).val());
                console.log("Slect", index)
                if (!isNaN(index)) {
                    angular.forEach(scope.details, function (value, k) {
                        if (value['id'] == index) {
                            item['quantity'] = 1;
                            item['lot_number'] = value.lot_number;
                            item['item_id'] = value.item_id;
                            item['name'] = value.item_name + ' (' + value.unit_price + ')';
                            item['description'] = value.item_description;
                            item['unit_cost'] = value['unit_price'];
                            item['applied_taxes'] = [];
                            item['selected_tax'] = [];
                            if (value['taxes'] != '' && value['taxes'] != null) {
                                var tax_array = value['taxes'].split(',').map(function (x) {
                                    return parseInt(x);
                                });
                                angular.forEach(scope.newTaxes, function (value, key) {
                                    angular.forEach(tax_array, function (v1, k1) {
                                        if (value['tax_id'] == v1) {
                                            tax_array.splice(k1, 1);
                                        }
                                    });
                                });
                                item['applied_taxes'] = tax_array;
                                angular.forEach(tax_array, function (value) {
                                    var result = scope.taxes.filter(function (obj) {
                                        return obj.tax_id == value;
                                    });
                                    if (result.length > 0) {
                                        item['selected_tax'].push(result[0].tax_name + ' (' + result[0].rate + '%)');
                                    }
                                });
                            }
                        }
                    });
                } else {
                    if (item['item_id']) {
                        delete item['item_id'];
                    }
                    item['unit_cost'] = 0;
                    item['applied_taxes'] = [];
                    item['selected_tax'] = [];
                    item['amount'] = 0;
                    item['quantity'] = 0;
                    item['description'] = '';

                }
                scope.$apply();
            });
        }
    };
})

select2 由js 文件中的指令初始化。

所有这些功能都曾在 select2 版本 3.x 中使用。但我最近将 select2 升级到 4.0.13 版,估计部分的 select2 下拉列表不再正常工作。

问题:第一行中的选择没问题。添加新行时,第一行的 select2 下拉列表中的选定值将被清除。

如有需要,请询问更多信息。提前致谢!

来自 Joe Enzminger's Anwser 这里的技巧是将 select2 初始化包装在一个超时函数中,这样选项将在 DOM 中作为正常 [=17] 的一部分可用=] 下拉菜单。只有选项是 DOM 的一部分后,下拉列表才能转换为 select2 下拉列表。

The first $timeout is necessary because the options won't be in the DOM until the next digest cycle. The problem with this is that new options won't be added to the control if the model is later changed by your application.

    $timeout(function() {
        $(elem).select2({
            placeholder: "Search for item",
            tags: true,
            ajax: {
                type: 'POST',
                url: version5Url + 'inventory/getMasterStocksForInvoice',
                tags: true,
                data: function (params) {
                    return {
                        token: scope.token,
                        user_id: scope.user_id,
                        client_id: scope.client_id,
                        search: params.term,
                        selected_items: scope.selected_items
                    };
                },
                dataType: 'json',
                delay: 250,
                processResults: function (data, params) {

                    $(elem).find('option').remove();
                    if (item['item_id']) {
                        delete item['item_id'];
                    }
                    item['unit_cost'] = 0;
                    item['applied_taxes'] = [];
                    item['selected_tax'] = [];
                    item['amount'] = 0;
                    item['quantity'] = 0;
                    item['description'] = '';
                    scope.details = data.parts;
                    scope.$apply();
                    return {
                        results: data.parts,
                        pagination: false
                    };
                },
                cache: false
            },
            escapeMarkup: function (markup) {
                return markup;
            },
            minimumInputLength: 0,
            templateResult: formatRepo,
            templateSelection: formatRepoSelection
        });
});