Bootstrap 5.1.3中jQuery修改Popover的data-bs-content属性无效如何修复?
问题
我尝试动态修改Bootstrap Popover的内容,当前必须使用Bootstrap 5.1.3版本(该版本没有新版本中的setContent()方法),编写了如下jQuery脚本:
$(document).ready(function() { $('#item-datalist').attr({ 'data-bs-toggle': "popover", 'data-bs-trigger': "manual" }); $('#count').attr({ 'data-bs-toggle': "popover", 'data-bs-trigger': "manual" }); $('#item-datalist').click(function() { $(this).css('border-color', '#001427'); let attr = $(this).attr('data-bs-toggle'); if (typeof attr !== 'undefined' && attr === 'popover') { $(this).popover('hide'); } }) $('#count').click(function() { $(this).css('border-color', '#001427'); let attr = $(this).attr('data-bs-toggle'); if (typeof attr !== 'undefined' && attr === 'popover') { $(this).popover('hide'); } }) }) $('.form').submit(function (e) { var datalist_value = $('#item-datalist').val(); var count_value = $('#count').val(); var datalist_valid = false; var count_valid = false; if (datalist_value == '') { e.preventDefault(); $('#item-datalist').css('border-color', '#F24236'); $('#item-datalist').attr('data-bs-content', 'Поле не должно быть пустым'); $('#item-datalist').popover('show'); } else { id = $('#items [value="' + datalist_value + '"]').data('value'); if (id != null) { datalist_valid = true; } else { e.preventDefault(); $('#item-datalist').css('border-color', '#F24236'); $('#item-datalist').attr('data-bs-content', 'Не совпадает ни с одним наименованием'); $('#item-datalist').popover('show'); } } if (Math.floor(count_value) == count_value && $.isNumeric(count_value) && count_value > 0) { count_valid = true; } else { e.preventDefault(); $('#count').css('border-color', '#F24236'); $('#count').attr('data-bs-content', 'Введите целое, положительное число, больше 0'); $('#count').popover('show'); } if (datalist_valid === true && count_valid === true) { $('#item-datalist').val(id); } })
为什么$('#item-datalist').attr('data-bs-content', 'Не совпадает ни с одним наименованием');这行代码无法生效,而另外两行$('#item-datalist').css('border-color', '#F24236');和$('#item-datalist').popover('show');却能正常工作?该如何修复此脚本?
原因分析
Bootstrap 5.1.3中,当第一次调用popover('show')时,组件会完成初始化并将data-bs-content的内容缓存到Popover实例的配置中。后续直接修改data-bs-content属性,并不会同步到已初始化的实例配置里,所以弹窗显示的始终是第一次缓存的内容。而CSS样式是直接操作DOM元素的样式属性,popover('show')只是触发弹窗显示动作,这两者都不受实例缓存的影响,因此能正常工作。
修复方案
方法1:销毁实例后重新配置
每次修改内容前,先销毁已有的Popover实例,再设置新的data-bs-content属性,最后重新初始化并显示弹窗:
修改表单提交事件中对应的代码块:
// 处理item-datalist空值分支 if (datalist_value == '') { e.preventDefault(); $('#item-datalist').css('border-color', '#F24236'); // 销毁已存在的实例 $('#item-datalist').popover('dispose'); // 设置新提示内容 $('#item-datalist').attr('data-bs-content', 'Поле не должно быть пустым'); // 重新初始化并显示 $('#item-datalist').popover({trigger: 'manual'}).popover('show'); } else { id = $('#items [value="' + datalist_value + '"]').data('value'); if (id != null) { datalist_valid = true; } else { e.preventDefault(); $('#item-datalist').css('border-color', '#F24236'); $('#item-datalist').popover('dispose'); $('#item-datalist').attr('data-bs-content', 'Не совпадает ни с одним наименованием'); $('#item-datalist').popover({trigger: 'manual'}).popover('show'); } } // 处理count的错误分支 else { e.preventDefault(); $('#count').css('border-color', '#F24236'); $('#count').popover('dispose'); $('#count').attr('data-bs-content', 'Введите целое, положительное число, больше 0'); $('#count').popover({trigger: 'manual'}).popover('show'); }
方法2:直接修改实例配置
通过Bootstrap的getInstance方法获取已初始化的Popover实例,直接修改其内部配置的内容属性,再触发显示:
修改表单提交事件中对应的代码块:
// 处理item-datalist空值分支 if (datalist_value == '') { e.preventDefault(); $('#item-datalist').css('border-color', '#F24236'); // 获取Popover实例 const popoverInstance = bootstrap.Popover.getInstance($('#item-datalist')[0]); if (popoverInstance) { // 修改实例中的内容配置 popoverInstance._config.content = 'Поле не должно быть пустым'; } else { // 未初始化则设置属性并初始化 $('#item-datalist').attr('data-bs-content', 'Поле не должно быть пустым'); $('#item-datalist').popover({trigger: 'manual'}); } $('#item-datalist').popover('show'); } else { id = $('#items [value="' + datalist_value + '"]').data('value'); if (id != null) { datalist_valid = true; } else { e.preventDefault(); $('#item-datalist').css('border-color', '#F24236'); const popoverInstance = bootstrap.Popover.getInstance($('#item-datalist')[0]); if (popoverInstance) { popoverInstance._config.content = 'Не совпадает ни с одним наименованием'; } else { $('#item-datalist').attr('data-bs-content', 'Не совпадает ни с одним наименованием'); $('#item-datalist').popover({trigger: 'manual'}); } $('#item-datalist').popover('show'); } } // 处理count的错误分支 else { e.preventDefault(); $('#count').css('border-color', '#F24236'); const popoverInstance = bootstrap.Popover.getInstance($('#count')[0]); if (popoverInstance) { popoverInstance._config.content = 'Введите целое, положительное число, больше 0'; } else { $('#count').attr('data-bs-content', 'Введите целое, положительное число, больше 0'); $('#count').popover({trigger: 'manual'}); } $('#count').popover('show'); }
内容的提问来源于stack exchange,提问作者Sigarev Andrey

