使用ajax动态创建具有相同名称的按钮。

时间:2022-03-05 16:51:05

I'm trying to implement a comment section and after button-press I want to update the comment section with ajax so the page doesn't have to refresh...

我正在尝试实现一个注释部分,按下按钮后,我想用ajax更新注释部分,这样页面就不需要刷新了……

In this comment section I have 1 textarea + 1 button + a couple of hidden fields for every comment so users can answer specific comments...

在这个评论部分,我有一个textarea + 1按钮+两个隐藏字段为每个评论,以便用户可以回答特定的评论……

so if there are 50 comments there are also 50 answer-fields, 1 for each...

因此,如果有50条评论,也就有50个答案栏,每个答案1个。

And every thing works except for 1 thing...
- either I name all id's of the buttons and fields the same name (ie. id="sendAnswer" and id="answer", id="userID", ...) and then only the first one works...
-or I dynamically name them all (ie. id="sendAnswer(echo $i) ) thereby naming them all id="sendAnswer0", "sendAnswer1", "sendAnswer2", ... and then I do that for the textarea and hidden fields too (ie. id="answer(echo $i), id="userID(echo $i), ...)

除了一件事,所有的事都是有效的。-我可以为所有的按钮和字段命名相同的名称。id=“sendAnswer”和id=“answer”,id=“userID”,…或者我动态地给它们命名。id=“sendAnswer(echo $i)”),因此将它们全部命名为id=“sendAnswer0”、“sendAnswer1”、“sendAnswer2”、……然后我对textarea和hidden fields也这样做。id="answer(echo $i), id="userID(echo $i),…"

And that works great too... except for now I have to make a jQuery-script for each... and since they are dynamically created that's difficult - as how many there are changes as more comments comes in...

这也很有效……除了现在,我必须为每个…由于它们是动态创建的,所以这很困难——随着更多评论的出现,会有多少变化……

Code for approach 1: naming them all the same...

方法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('');
            }
        });
    });
});

And as I said... this works fine for the first one and the rest are duds...

就像我说的…这对第一个很有效,其余的都是垃圾。

Code for approach 2: I dynamically name all values...

方法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.
            }
        });
    });
});

With this I would have to name every single possible #sendAnswer-number + #comment-number for it to work... and with an infinite set of numbers to choose from 0-(infinite) - that's not viable...

有了这个,我将不得不命名每一个可能的#sendAnswer-number + # comm- number来让它工作……有一组无限的数字可以从0-(无限)中选择-那是不可行的…

If of any interest...
Php that dynamically creates the buttons and fields in question

如果任何感兴趣的…动态创建问题中的按钮和字段的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; } ?>" width="50" height="50" 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 }
        }
    }
} ?>
.
.
.

2 个解决方案

#1


2  

two ways .. 1st use classes instead of ids .OR. 2nd use selector id starts with [id^="something"] .. and on both ways you need to use $(this) to refer to the same section .. And for me its bad practice to use .load() to refresh the whole comment section you can directly get the specific comment and append it to the #commentDiv

两种方法. .首先使用类而不是id。2使用选择器id始于[id ^ = "东西"]. .在这两种方法中,都需要使用$(this)来引用相同的部分。对于我来说,使用.load()刷新整个注释部分是不好的做法,您可以直接获得特定的注释并将其附加到#commentDiv

by using $("#sendAnswer"+$(this).val()) $(this) in this case refer to nothing/window or something else but not to your element

通过使用$(“#sendAnswer”+$(this).val()) $(this),在这种情况下,$(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('');
            }
        });
    });
});

Note: Change .BigDiv with the div id/class which hold both commentDiv and comment section

注意:使用div id/class更改.BigDiv,该id/class包含commentDiv和comments部分

#2


0  

Using your current approach, where everything is identified with ids, the best option would be to use event delegation. Create just one event handler, on some parent element which exists at the time the page is loaded, which via delegation will handle any of your buttons - existing and future. Once the handler fires, you can determine which set of elements you are working with, and continue as normal.

使用您当前的方法(其中所有内容都与id标识),最好的选择是使用事件委托。只在加载页面时存在的父元素上创建一个事件处理程序,该元素通过委托处理您的任何按钮——现有的和将来的。一旦处理程序触发,您就可以确定要处理哪些元素,并继续正常工作。

Here's an example, using body as the parent, but you can use any element which contains all your present and future buttons/inputs, eg maybe you have a parent <div id="something">. This also assumes your button inputs are actual button elements, you'll have to adjust if that's not the case:

这里有一个例子,使用body作为父元素,但是您可以使用任何包含当前和未来所有按钮/输入的元素,例如,您可能有父元素

。这也假定您的按钮输入是实际的按钮元素,如果不是这样,您将不得不进行调整:

$(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

As well as the article linked above, the jQuery .on() docs have a good description of event delegation (see "Direct and delegated events").

除了上面链接的文章之外,jQuery .on()文档对事件委托有很好的描述(参见“直接和委托事件”)。

Update

Another option, which I find neater, is to wrap each comment section in a div (or any identifying element, such that each comment/input/button set is nested inside it), and use only classes for each element. Again using event delegation, you can find the section which contains the button that was clicked, and therefore identify which input elements you're working with.

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

For example, your HTML might look like:

例如,您的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>

Now your JS would look something like this:

现在你的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

#1


2  

two ways .. 1st use classes instead of ids .OR. 2nd use selector id starts with [id^="something"] .. and on both ways you need to use $(this) to refer to the same section .. And for me its bad practice to use .load() to refresh the whole comment section you can directly get the specific comment and append it to the #commentDiv

两种方法. .首先使用类而不是id。2使用选择器id始于[id ^ = "东西"]. .在这两种方法中,都需要使用$(this)来引用相同的部分。对于我来说,使用.load()刷新整个注释部分是不好的做法,您可以直接获得特定的注释并将其附加到#commentDiv

by using $("#sendAnswer"+$(this).val()) $(this) in this case refer to nothing/window or something else but not to your element

通过使用$(“#sendAnswer”+$(this).val()) $(this),在这种情况下,$(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('');
            }
        });
    });
});

Note: Change .BigDiv with the div id/class which hold both commentDiv and comment section

注意:使用div id/class更改.BigDiv,该id/class包含commentDiv和comments部分

#2


0  

Using your current approach, where everything is identified with ids, the best option would be to use event delegation. Create just one event handler, on some parent element which exists at the time the page is loaded, which via delegation will handle any of your buttons - existing and future. Once the handler fires, you can determine which set of elements you are working with, and continue as normal.

使用您当前的方法(其中所有内容都与id标识),最好的选择是使用事件委托。只在加载页面时存在的父元素上创建一个事件处理程序,该元素通过委托处理您的任何按钮——现有的和将来的。一旦处理程序触发,您就可以确定要处理哪些元素,并继续正常工作。

Here's an example, using body as the parent, but you can use any element which contains all your present and future buttons/inputs, eg maybe you have a parent <div id="something">. This also assumes your button inputs are actual button elements, you'll have to adjust if that's not the case:

这里有一个例子,使用body作为父元素,但是您可以使用任何包含当前和未来所有按钮/输入的元素,例如,您可能有父元素

。这也假定您的按钮输入是实际的按钮元素,如果不是这样,您将不得不进行调整:

$(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

As well as the article linked above, the jQuery .on() docs have a good description of event delegation (see "Direct and delegated events").

除了上面链接的文章之外,jQuery .on()文档对事件委托有很好的描述(参见“直接和委托事件”)。

Update

Another option, which I find neater, is to wrap each comment section in a div (or any identifying element, such that each comment/input/button set is nested inside it), and use only classes for each element. Again using event delegation, you can find the section which contains the button that was clicked, and therefore identify which input elements you're working with.

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

For example, your HTML might look like:

例如,您的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>

Now your JS would look something like this:

现在你的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