多个使用ajax动态创建的同名按钮

Posted

技术标签:

【中文标题】多个使用ajax动态创建的同名按钮【英文标题】:multiple dynamically created buttons with same name using ajax 【发布时间】:2018-05-22 07:12:07 【问题描述】:

我正在尝试实现一个评论部分,按下按钮后我想用 ajax 更新评论部分,这样页面就不必刷新......

在这个评论部分,我有 1 个文本区域 + 1 个按钮 + 每个评论的几个隐藏字段,因此用户可以回答特定的 cmets...

因此,如果有 50 个 cmets,则还有 50 个答案字段,每个字段 1 个...

除了 1 件事之外,所有的事情都有效... - 要么我将按钮和字段的所有 id 命名为相同的名称(即 id="sendAnswer" 和 id="answer", id="userID", ...),然后只有第一个有效... - 或者我动态地将它们全部命名(即 id="sendAnswer(echo $i) ),从而将它们全部命名为 id="sendAnswer0", "sendAnswer1", "sendAnswer2", ... 然后我为 textarea 和隐藏字段(即 id="answer(echo $i), id="userID(echo $i), ...)

这也很好用......除了现在我必须为每个人制作一个 jQuery 脚本......而且由于它们是动态创建的,这很困难 - 因为随着更多 cmets 的加入,会有多少变化......

方法 1 的代码:将它们命名相同...

$(document).ready(function()
    "use strict";
    $("#sendAnswer").click(function()
        var comment = $("#comment").val();
        var userID = $("#userID").val();
        var randomStringVideo = $("#randomStringVideo").val();
        var commentID = $("#commentID").val();
        $.ajax(
            type: "POST",
            url:'../scripts/comment.php',
            data:"comment="+comment+"&userID="+userID+"&randomStringVideo="+randomStringVideo+"&commentID="+commentID,
            success:function()
                $("#commentDiv").load(location.href + " #commentDiv>*", "");
                $("#commentsDiv").load(location.href + " #commentsDiv>*", "");
                $("#comment").val('');
            
        );
    );
);

正如我所说...这对第一个很好,其余的都是哑弹...

方法 2 的代码:我动态命名所有值...

$(document).ready(function()
    "use strict";
    $("#sendAnswer"+$(this).val()).click(function() // this +$(this).val() doesn't work, only if I put #sendAnswer3 - then the 4th works and the rest are duds etc.
        var comment = $("#comment"+$(this).val()).val(); // works perfectly no matter what #sendAnswer I use
        var userID = $("#userID"+$(this).val()).val(); // works perfectly no matter what #sendAnswer I use
        var randomStringVideo = $("#randomStringVideo"+$(this).val()).val(); // works perfectly no matter what #sendAnswer I use
        var commentID = $("#commentID"+$(this).val()).val(); // works perfectly no matter what #sendAnswer I use
        $.ajax(
            type: "POST",
            url:'../scripts/comment.php',
            data:"comment="+comment+"&userID="+userID+"&randomStringVideo="+randomStringVideo+"&commentID="+commentID,
            success:function()
                $("#commentDiv").load(location.href + " #commentDiv>*", "");
                $("#commentsDiv").load(location.href + " #commentsDiv>*", "");
                $("#comment"+$(this).val()).val(''); // this +$(this).val() doesn't work, only if I put #comment3 (matching the #sendAnswer)- then the 4th works and the rest are duds etc.
            
        );
    );
);

有了这个,我必须命名每一个可能的#sendAnswer-number + #comment-number 才能让它工作......并且有一组无限的数字可以从 0-(无限)中选择 - 这是不可行的.. .

如果有任何兴趣... 动态创建相关按钮和字段的 PHP

.
.
.
<?php if ($_SESSION[numberOfComments] != 0) 
    for ($i=0; $i<$_SESSION[numberOfComments]; $i++) ?> // run through all comments that aren't answers to other comments
        // show comment info
        <div class="media">// answer comment box starts here
            <img class="mr-3 rounded" src="<?php $file = USER . $_SESSION['randomString'] . THUMBNAIL; if ( file_exists ( $file ) ) echo $file;  else  echo USER . "default" . THUMBNAIL;  ?>"   data-toggle="tooltip" data-placement="left" title="<?php echo $_SESSION['username']; ?>">
            <div class="media-body">
                <textarea class="form-control" rows="2" type="text" name="comment<?php echo $i; ?>" id="comment<?php echo $i; ?>" value="" placeholder="Great video!"></textarea>
                <input type="hidden" name="userID<?php echo $i; ?>" id="userID<?php echo $i; ?>" value="<?php if ( isset ( $_SESSION['id'] ) )  echo $_SESSION['id'];  ?>">
                <input type="hidden" name="randomStringVideo<?php echo $i; ?>" id="randomStringVideo<?php echo $i; ?>" value="<?php echo $_GET['v']; ?>">
                <input type="hidden" name="commentID<?php echo $i; ?>" id="commentID<?php echo $i; ?>" value="<?php echo $_SESSION['commentID_getComment']; ?>">
                <button type="button" class="btn btn-primary float-right margin-top-5" id="sendComment<?php echo $i; ?>" value="<?php echo $i; ?>">
                    Answer
                </button>
            </div>
        </div> // answer comment box ends here
        <?php if ($_SESSION[numberOfAnswers][$i] != 0) 
            for ($j=0; $j<$_SESSION[numberOfAnswers][$i]; $j++)  ?> // run through all answer to this comment
                // show answer info
            <?php 
        
    
 ?>
.
.
.

【问题讨论】:

那么button#commentDiv是什么关系? 按钮'调用' ajax...和#commentDiv id 包含所有 cmets 的 div - - 显示所有 cmets - ajax 正在刷新它... 【参考方案1】:

两种方式 .. 第一种使用类而不是 ids .OR。第二次使用选择器 id 以 [id^="something"] 开头 .. 在这两种方式上,您都需要使用 $(this) 来引用同一部分.. 对我来说,使用 .load() 刷新整个评论部分是不好的做法,您可以直接获取特定评论并将其附加到#commentDiv

在这种情况下,通过使用 $("#sendAnswer"+$(this).val()) $(this) 来引用任何内容/窗口或其他内容,但不要引用您的元素

$(document).ready(function()
    "use strict";
    $('button[id^="sendAnswer"]').on('click',function()
        var ThisIs = $(this);
        var ClosestDiv = ThisIs.closest('.media-body');
        var comment = ClosestDiv.find('textarea').val(); 
        var userID = ClosestDiv.find('[id^="userID"]').val(); 
        var randomStringVideo = ClosestDiv.find('[id^="randomStringVideo"]').val();
        var commentID = ClosestDiv.find('[id^="commentID"]').val();
        $.ajax(
            type: "POST",
            url:'../scripts/comment.php',
            data:"comment="+comment+"&userID="+userID+"&randomStringVideo="+randomStringVideo+"&commentID="+commentID,
            success:function()
                var commentDiv = ThisIs.closest('.BigDiv').find('[id^="commentDiv"]'); // change `.BigDiv` with the div id/class which hold both commentDiv and comment section
                commentDiv.load(location.href + " #commentDiv>*", "");
                ClosestDiv.find('textarea').val('');
            
        );
    );
);

注意:.BigDiv 更改为同时包含两者的 div id/class commentDiv 和评论部分

【讨论】:

@mohammed-Yousef - 谢谢你这行得通……唯一的事……comment.val('');不清除文本区域(评论)...但更改为 $("#comment").val('');它有效(在您的答案中更改它以获取您的投票和复选标记以及我永恒的感激,呵呵)......唯一的事情是......在我发布了一个答案(这就像一个魅力)之后,我必须刷新整个页面以发布另一个答案...有没有办法避免这种情况? @APM 和关于刷新整个页面 .. 正如我在回答中所说,为您的评论/答案提供参考,然后使用 ajax data: 发送它以获取特定的评论/答案,然后将其附加到它的部分 @APM 您需要将其更改为 ClosestDiv.find('textarea').val('') 而不是 $("#comment").val(''); @Mohammed-Yousef 成功了... tnx... 答案被接受并且赞成票是你的 :) - tnx 一堆... 不客气@APM 我也赞成你的问题祝你有美好的一天:)【参考方案2】:

使用您当前的方法,其中所有内容都用ids 标识,最好的选择是使用event delegation。在页面加载时存在的某个父元素上仅创建一个事件处理程序,通过委托将处理您的任何按钮 - 现有的和未来的。处理程序触发后,您可以确定您正在使用哪一组元素,然后照常继续。

这是一个示例,使用body 作为父级,但您可以使用包含所有当前和未来按钮/输入的任何元素,例如,也许您有一个父级&lt;div id="something"&gt;。这也假设您的按钮输入是实际的 button 元素,如果不是这种情况,您将不得不进行调整:

$(document).ready(function()
    "use strict";

    // A single event handler on body, which handles any child button
    $("body").on('click', 'button', function(event) 

        // $(this) will be the button that was clicked.  We can find its id,
        // and if your buttons all have ids like sendAnswer1, sendAnswer2,
        // sendAnswerX, we can find the X
        var id = $(this).attr('id').replace('sendAnswer', '');

        // Now we can use the X to access each of this button's matching
        // inputs etc. Again this assumes your other elements have ids like 
        // commentX.
        var comment = $("#comment" + id).val(),
            userID = $("#userID" + id).val(),
            // ... etc, rest of your code

与上面链接的the article 一样,the jQuery .on() docs 对事件委托有很好的描述(请参阅“直接和委托事件”)。

更新

另一个我觉得更简洁的选择是将每个评论部分包装在一个 div 中(或任何标识元素,这样每个评论/输入/按钮集都嵌套在其中),并且每个元素只使用类。再次使用事件委托,您可以找到包含被单击按钮的部分,从而确定您正在使用哪些输入元素。

例如,您的 html 可能如下所示:

<div id="all-comments">
    <div class="comment-section">
        <textarea class="comment" name="whatever"> ... </textarea>
        <button name="button" type="submit">Post!</button>
        <!-- your hidden fields, etc -->
    </div>

    <div class="comment-section">
        ...
    </div>

    <!-- ... etc, many comment sections -->
</div>

现在你的 JS 看起来像这样:

$(document).ready(function()
    "use strict";

    // A single event handler on the parent div, which handles any child button
    $("#all-comments").on('click', 'button', function(event) 

        // $(this) will be the button that was clicked.  We need to find the
        // .comment-section containing that button
        var div = $(this).closest('div.comment-section');

        // Now we can find all elements inside that particular section
        var comment = $(".comment", div).val(),
            userID = $(".userID", div).val(),
            // ... etc, rest of your code

【讨论】:

以上是关于多个使用ajax动态创建的同名按钮的主要内容,如果未能解决你的问题,请参考以下文章

如何从动态创建的按钮中获取属性?

仅返回一个 <h3> 父标签的文本

带有ajax调用的jsf通过轮询获取动态值

动态创建或删除表单元素

如何使用 Ajax 成功创建动态表

使用 ImageView 动态创建多个 EditText 并将 ImageView 点击值设置为 EditText 并从 EditText 获取值