You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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循环仅在已有投票记录(标准循环的按钮已显示)时生效。


解决方案

核心问题分析

  1. 元素不存在导致.show()失效:用户未投票时,{% else %}分支里的投票循环不会执行(无用户投票记录),id="deleteVote"的<a>元素根本没渲染到页面,自然无法被.show()找到。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 15:05:26