iT邦幫忙

0

jquery 點擊事件寫在副程式裡,重複觸發

  • 分享至 

  • xImage

大家好:
本來是想透過table的button點了後,再跳一個視窗確認是否送出 以下是button click後觸發modal副程式,跳出視窗再次確認是否送出,但因為不知道要怎麼把$(".btn").unbind('click').click 訊號回傳到button.click,是否執行ajax,只好把ajax寫在副程式的click中..

另外不用unbind('click')會使副程式的click重複動作,想請問甚麼原因

謝謝

$("table").on('click','button',function(e){ 
  rownum=$(this).closest('tr').index()-1;  
  seq=$(".text-success:eq("+rownum+")").text(); 
  agree = $(this).text(); 
  modal(this.id,seq,agree);
});



function modal(btname,seq,agree)
{   
  $('.modal').modal({
    keyboard: false,
    backdrop: false
  });
$(".modal").modal("show");
$(".modal").find(".modal-body").html("<b>"+bodytext+"</b>");
$(".btn").unbind('click').click(function(e) { 
    $.ajax({
        url:"abv.php",
        type:"POST",
        data: {
            "sqnum":seq,
            "status":agree,
              },
        error: function(jqXHR, textStatus, errorThrown) {
        alert(jqXHR.responseText);
        },
        success: function(data) {  
        $(".modal").modal("hide");
        location.reload();
        }
    });
});
}



ccutmis iT邦高手 2 級 ‧ 2021-02-03 03:45:21 檢舉
看看是不是跟"事件冒泡"有關:
https://ithelp.ithome.com.tw/articles/10198999
froce iT邦大師 1 級 ‧ 2021-02-03 08:48:27 檢舉
補充一下:
像這種問題很可能是和事件冒泡有關,也就是如果你在母元素綁定點擊事件,在子元素也綁定點擊事件,那你點擊子元素時,母元素的事件也會一起執行。
你預期的行為是點擊子元素,但因為DOM是樹狀結構,所以你母元素也一併會被點擊。
https://blog.techbridge.cc/2017/07/15/javascript-event-propagation/

然後上面那篇還有提到 preventDefault() ,但我覺得 preventDefault() 並不該在這裡提及,preventDefault() 是阻止元素原本的預定行為,比如說form裡的button你不想讓他進行預設的 submit 行為。

最後,為啥我們都說可能是跟事件傳遞有關...
因為這得看你的html結構才說得準。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
2
ccutmis
iT邦高手 2 級 ‧ 2021-02-03 09:54:39
最佳解答

這邊提供一個土法煉鋼的範例給樓主參考,
簡單來說就是在按第一個按鈕時把ajax要傳值帶進modal裡,
按第二個按鈕的事件函式獨立出來寫,避免事件冒泡的情況發生。
(ajax要傳的東西就從modal裡面的值去撈,不知這樣說你了解嗎?)

bs5_test.htm (底下是直接從bs5官網的start範例改的 存成htm可直接看結果)

<!doctype html>
<html lang="tw">
  <head>
    <!-- Required meta tags -->
    <title>Hello, world!</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js" integrity="sha384-q2kxQ16AaE6UbzuKqyBE9/u/KzioAlnx2maXQHiDX9d4/zp8Ok3f+M7DPm+Ib6IU" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.min.js" integrity="sha384-pQQkAEnwaBkjpqZ8RU1fF1AKtTcHJwFl3pblpTlHXybJjHpMYo79HY3hIi4NKxyj" crossorigin="anonymous"></script>
    <script
  src="https://code.jquery.com/jquery-3.5.1.min.js"
  integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
  crossorigin="anonymous"></script>
  </head>
<body class="bg-secondary">
<h1 class="text-white text-center p-3">Hello, world!</h1>
<table class="w-75 mx-auto border testTable">
<tr><th>主題</th><th>說明</th><th>動作</th></tr>
<tr>
    <td class="testTitle">測試主題001</td>
    <td class="testContent">測試內容001</td>
    <td><button class="testBtn">SEND 001</button></td>
</tr>
<tr>
    <td class="testTitle">測試主題002</td>
    <td class="testContent">測試內容002</td>
    <td><button class="testBtn">SEND 002</button></td>
</tr>
</table>


<div class="modal" tabindex="-1">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Modal title</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <p>Modal body text goes here.</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary btnAJAX">AJAX TEST</button>
      </div>
    </div>
  </div>
</div>

<script>
$(".testBtn").click(function(){
    let tmp_title=$(this).parent().parent().find('.testTitle').text();
    let tmp_content=$(this).parent().parent().find('.testContent').text();
    //console.log(tmp_title,tmp_content);
    $('.modal .modal-title').text(tmp_title);
    $('.modal .modal-body p').text(tmp_content);
    $('.modal').modal('show');
});
$('.btnAJAX').click(function(){
    alert($('.modal .modal-title').text()+'\n'+$('.modal .modal-body').text()+"\nIt's your turn to write some codes!");
    $('.modal').modal('hide');
});

$(".testTable tr th,.testTable tr td").addClass("border text-center p-2 text-info");
</script>

</body>
</html>
看更多先前的回應...收起先前的回應...
mayyola iT邦研究生 1 級 ‧ 2021-02-03 10:44:09 檢舉

第一個button click先將值隱藏在modal 再用modal的button click去讀值是比較直觀的
好像沒有modal的button click 直接抓第一個click資料
謝謝

ccutmis iT邦高手 2 級 ‧ 2021-02-03 10:51:52 檢舉

第一個button click先將值隱藏在modal 再用modal的button click去讀值是比較直觀的

這邊我是為了讓你清楚它的運作所以都顯示出來,實際運用上面可以把資料元素隱藏沒錯(比如說加一個<input type="hidden" class="hidden_title" value="" />來存標題之類的,用jquery可以存取但在畫面上不會顯示),就看你怎麼運用。詳見下方範例...

好像沒有modal的button click 直接抓第一個click資料

你說的是這個嗎? modal裡面的按鈕留意一下我有加一個class "btnAJAX" (能alert出來的值當然能改成用AJAX傳)

$('.btnAJAX').click(function(){
    alert($('.modal .modal-title').text()+'\n'+$('.modal .modal-body').text()+"\nIt's your turn to write some codes!");
    $('.modal').modal('hide');
});

範例改寫成跟樓主提問時附的源碼比較相近的結果如下:

<table class="w-75 mx-auto border testTable">
<tr><th>主題</th><th>說明</th><th>動作</th></tr>
<tr>
    <td class="test_sqnum">sqnum:001</td>
    <td class="test_status">status:001</td>
    <td><button class="testBtn">SEND-001</button></td>
</tr>
<tr>
    <td class="test_sqnum">sqnum:002</td>
    <td class="test_status">status:002</td>
    <td><button class="testBtn">SEND-002</button></td>
</tr>
</table>

<div class="modal" tabindex="-1">
  <input type="hidden" class="sqnum" value="" />
  <input type="hidden" class="status" value="" />
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Modal title</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <p>Modal body text goes here.</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary btnAJAX">AJAX TEST</button>
      </div>
    </div>
  </div>
</div>

<script>
$(".testBtn").click(function(){
    let tmp_sqnum=$(this).parent().parent().find('.test_sqnum').text();
    let tmp_status=$(this).parent().parent().find('.test_status').text();
    $('.modal .sqnum').val(tmp_sqnum);
    $('.modal .status').val(tmp_status);
    $('.modal').modal('show');
});
$('.btnAJAX').click(function(){
    $.ajax({
        url:"abv.php",
        type:"POST",
        data: {
            "sqnum":$('.modal .sqnum').val(),
            "status":$('.modal .status').val(),
              },
        error: function(jqXHR, textStatus, errorThrown) {
        alert(jqXHR.responseText);
        },
        success: function(data) {
		  console.log(data); 
          //把ajax成功返回結果顯示在console
          $(".modal").modal("hide");
          //location.reload();
        }
    });
});

/* 底下這行是美化頁面用的無視即可 */
$(".testTable tr th,.testTable tr td").addClass("border text-center p-2 text-info");
</script>
mayyola iT邦研究生 1 級 ‧ 2021-02-04 12:26:43 檢舉

cc 大您好:看懂您寫的,這比較直觀,謝謝!

ccutmis iT邦高手 2 級 ‧ 2021-02-04 13:07:14 檢舉

不客氣 很高興幫上忙 :)

0
japhenchen
iT邦超人 1 級 ‧ 2021-02-03 08:09:09

unbind已過時,請改用off,建議移進ajax的success裡

function modal(btname,seq,agree)
{   
    $('.modal').modal({
        keyboard: false,
        backdrop: false
    });
    $(".modal").modal("show");
    $(".modal").find(".modal-body").html("<b>"+bodytext+"</b>");
    $.ajax({
        url:"abv.php",
        type:"POST",
        data: {
            "sqnum":seq,
            "status":agree,
              },
        error: function(jqXHR, textStatus, errorThrown) {
        alert(jqXHR.responseText);
        },
        success: function(data) {  
            $(".btn").off('click');
            $(".modal").modal("hide");
            location.reload();
        }
    });
}
mayyola iT邦研究生 1 級 ‧ 2021-02-03 08:53:13 檢舉

j大好,我是在table點一次確認按鈕,會跑出modal,再點modal的按鈕才會執行ajax,是否需要將ajax包在btn click的事件中 如果放在success好像是先執行ajax 才執行click @@? 謝謝

那我建議你改用$.dialog,在按下對應鍵後才發動ajax送回資料

$(function(){
    $("#dialogBudgetCheck").dialog({
        autoOpen: false,
        modal: true,
        title: "預算檢查狀況",
        show: "explode",
        hide: "fadeout",
        buttons: {
            "關閉": function () {
                $(this).dialog("close");
            },
            "回寫ERP": function () {
                if (errcount > 0) {
                    alert("有項目超過預算限制,請查閱清單");
                } else {
                    confirmWriteBackPO(lastPOSData);
                    // ajax在上面那行的function裡
                    $(this).dialog("close");
                }
            }
        },
    });
});
var confirmWriteBackPO = function () {
    $.post({
        url: './',
        dataType: "html",
        data: {
            act: 'confirmWBPO',
            uid: 'uid'.urlParamValue(),
            data: JSON.stringify(lastPOSData),
        }
    })
        .done(function (d) {
            alert(d);
        });
};

2

正常來說,不要在會重覆呼叫的function內去綁定事件。
很容易發生複合式事件的生成。

而且你用的還是class元素的事件綁定更是危險。

不需要去管要不要用unbind。
本身的架構就不該這樣設計了。

你山一段在function內的click綁定事件要拿出來綁定。

0
耿直小伙
iT邦新手 1 級 ‧ 2021-02-03 09:45:46

如果你的 modal 是固定在 html 內,而不是動態產生出來的,那麼副程式內的 click 事件一直被重複綁定,所以你才需要 unbind('click') 或 off('click')

我要發表回答

立即登入回答