AJAX点击按钮显示<div>失效及Twig if/else逻辑疑问求助
问题:AJAX投票后无法显示删除按钮
我正在实现AJAX功能,希望点击按钮后显示以下整个<div>:
<div class="col-12" id="deleteVote"> <div class="row mb-2" > <div class="col-12"> {% for vote in proposal.votes %} {% if app.user == vote.user %} <a href="{{ path('vote_delete',{'slug' : slug, 'proposal' : proposal.id, 'vote' : vote.id}) }}" class="btn btn-light ml-1 btn-sm deleteVote" data-toggle="deleteConfirmation"> <i class="bi bi-trash"></i> {{ 'vote-delete' | trans }} </a> {% endif %} {% endfor %} </div> </div> </div>
以下是我的脚本,不清楚为什么.show()方法不生效:
<script> $(document).on('click', '.votedFullAgreement', function (){ $.ajax({ url: '{{ path('vote_add', {'slug' : slug, 'proposal' : proposal.id, 'userVote' : 'votedFullAgreement', 'user' : app.user.id }) }}', type: 'POST', dataType: 'html', success: function (){ $('#deleteVote').show(); }, error: function (resultat, statut, erreur) { } }); return false; }); </script>
注:这是我写的第一个脚本,能正常发送数据,但未做优化。
编辑2:
我搞不懂这个if/else逻辑为什么失效。当用户已有投票记录时,if分支正常生效,刷新页面后删除按钮会显示;但用户还没投票时,.show()无法激活设置了display:none的else分支里的元素。
是不是因为投票后proposal.votedByUser(app.user)变成true了?而且.show()需要找到之前隐藏的元素,但此时这个元素根本不存在?
模板代码如下:
{# Standard loop #} {% if proposal.votedByUser(app.user) %} <div class="col-12"> <div class="row mb-2"> <div class="col-12"> {% for vote in proposal.votes %} {% if app.user == vote.user %} <a href="{{ path('vote_delete',{'slug' : slug, 'proposal' : proposal.id, 'vote' : vote.id}) }}" class="btn btn-light ml-1 btn-sm" data-toggle="deleteConfirmation"> <i class="bi bi-trash"></i> {{ 'vote-delete' | trans }} </a> {% endfor %} </div> </div> </div> {% else %} {# AJAX loop #} <div class="col-12"> <div class="row mb-2"> <div class="col-12"> {% for vote in proposal.votes %} {% if app.user == vote.user %} {# ID deleteVote here, which has display:none in the CSS #} <a href="{{ path('vote_delete',{'slug' : slug, 'proposal' : proposal.id, 'vote' : vote.id}) }}" id="deleteVote" class="btn btn-light ml-1 btn-sm" data-toggle="deleteConfirmation"> <i class="bi bi-trash"></i> {{ 'vote-delete' | trans }} </a> {% endif %} {% endfor %} </div> </div> </div> {% endif %}
另外,如果拆分两个循环,AJAX循环仅在已有投票记录(标准循环的按钮已显示)时生效。
解决方案
核心问题分析
- 元素不存在导致
.show()失效:用户未投票时,{% else %}分支里的投票循环不会执行(无用户投票记录),id="deleteVote"的<a>元素根本没渲染到页面,自然无法被.show()找到。 - ID使用违规:即使循环执行,把ID放在
<a>标签上会生成重复ID(多投票记录场景),违反HTML唯一ID规则。
修复步骤
1. 调整模板结构
不管用户是否已投票,都渲染删除按钮的容器,默认隐藏。AJAX投票成功后,再动态填充按钮内容并显示容器。
修改后的模板:
{# 始终渲染容器,默认隐藏 #} <div class="col-12" id="deleteVoteContainer" style="display:none;"> <div class="row mb-2"> <div class="col-12" id="deleteVoteButtons"> {% if proposal.votedByUser(app.user) %} {% for vote in proposal.votes %} {% if app.user == vote.user %} <a href="{{ path('vote_delete',{'slug' : slug, 'proposal' : proposal.id, 'vote' : vote.id}) }}" class="btn btn-light ml-1 btn-sm" data-toggle="deleteConfirmation"> <i class="bi bi-trash"></i> {{ 'vote-delete' | trans }} </a> {% endif %} {% endfor %} {% endif %} </div> </div> </div>
2. 优化AJAX脚本
投票成功后,通过接口获取最新的删除按钮HTML,插入容器后再显示:
<script> $(document).on('click', '.votedFullAgreement', function (){ $.ajax({ url: '{{ path('vote_add', {'slug' : slug, 'proposal' : proposal.id, 'userVote' : 'votedFullAgreement', 'user' : app.user.id }) }}', type: 'POST', dataType: 'json', success: function (){ // 请求删除按钮的渲染接口,更新内容并显示容器 $.get('{{ path('vote_delete_buttons', {'slug' : slug, 'proposal' : proposal.id}) }}', function(html){ $('#deleteVoteButtons').html(html); $('#deleteVoteContainer').show(); }); }, error: function () { alert('投票失败,请重试'); } }); return false; }); </script>
3. 新增后端辅助接口(可选)
创建专门渲染删除按钮的模板vote_delete_buttons.html.twig:
{% for vote in proposal.votes %} {% if app.user == vote.user %} <a href="{{ path('vote_delete',{'slug' : slug, 'proposal' : proposal.id, 'vote' : vote.id}) }}" class="btn btn-light ml-1 btn-sm" data-toggle="deleteConfirmation"> <i class="bi bi-trash"></i> {{ 'vote-delete' | trans }} </a> {% endif %} {% endfor %}
然后在控制器中添加对应路由,返回该模板的HTML内容。
简化版修复(无需新增接口)
如果不想新增接口,可修改投票接口返回新投票ID,前端手动拼接按钮HTML:
success: function (result){ // 替换投票接口返回的vote_id var deleteUrl = '{{ path('vote_delete', {'slug' : slug, 'proposal' : proposal.id, 'vote' : '__VOTE_ID__'}) }}'.replace('__VOTE_ID__', result.vote_id); var buttonHtml = `<a href="${deleteUrl}" class="btn btn-light ml-1 btn-sm" data-toggle="deleteConfirmation"><i class="bi bi-trash"></i> {{ 'vote-delete' | trans }}</a>`; $('#deleteVoteButtons').html(buttonHtml); $('#deleteVoteContainer').show(); }
此方法需要将投票接口的返回类型改为JSON,包含新创建的投票ID。
内容的提问来源于stack exchange,提问作者vLk171x
相关产品推荐
相关产品推荐

