javascript - jQuery on click not working after DOM was changed - Stack Overflow

I have setup my HTML in razor like following:@if (ViewBag.Added != null){if (ViewBag.Added == false){

I have setup my HTML in razor like following:

  @if (ViewBag.Added != null)
                            {
                                if (ViewBag.Added == false)
                                {                        
                                    <div class="col-lg-2 col-md-3 col-sm-12 col-xs-12" id="wholeBtn">

                                     <a class="btn btn-app btnWatchList" style="min-width:100%;margin:0;height:67px">
                                    <i class="fa fa-save"></i> Add to Watchlist
                                  </a>
                                </div>
                                }
                                else if (ViewBag.Added)
                                {
                                    <div class="col-lg-2 col-md-3 col-sm-12 col-xs-12" id="addedToWatchList" style="padding:10px 0">
                                        <h4 style="text-align:center;margin-top:20px"><i class="fa fa-check" style="color:darkseagreen;font-size:25px"></i> Watching</h4>
                                    </div>
                                }
                            }
                            else
                            {
                                <div class="col-lg-2 col-md-3 col-sm-12 col-xs-12" id="wholeBtn">

                                    <a class="btn btn-app btnWatchList" style="min-width:175px;margin:0;height:67px">
                                        <i class="fa fa-save"></i> Add to Watchlist
                                    </a>
                                </div>
                            }

The onclick button looks like this:

$(".btnSaveWatchlist").on("click", function (event) {
       $.post("/User/SaveWatchList", { ment: $('#TextArea1').val(), rating: $('input[name=rating]:checked').val(), petitor: $('.txtSearch').val() }, $(this).prop('disabled', true))
                             .done(function (data) {
                                 if (data == "AllFieldsRequired") {
                                     ShowErrorMessage("All fields are required!");
                                     return;
                                 }
                                 else {
                                     $('.hideit').hide();
                                     $('.canvas').show();
                                     AnimateGreenCheck();
                                     setTimeout(function () {
                                         var result = $('<div />').append(data).find('#addedToWatchList').html();
                                         $('#wholeBtn').html(result);
                                         var l = document.getElementById('cancelButton');
                                         l.click();
                                     },
                                   3000);

                                     setTimeout(function () {
                                         ResetWatchListField();
                                     },
                                  4500);
                                 }
                             });
});

So initially this button "Add to watchlist" isn't present in DOM. It is loaded into the DOM after an search is performed on website.

Once that is done, onclick event works very fine. When post is done, I hide the button and update the DOM to show user that he added this user to watchlist.

Performing the search now again on different user that wasnt added to watchlist, and the button "Add to watchlist" with class "btnSaveWatchlist" is again loaded into the DOM.

But this time it is pletely unresponsive... I checked whether the action in controller gets initiated, it doesn't ... The button seems like it's "Frozen"...

Any ideas what could it be guys?

P.S. All this is done without refreshing the page at all. I don't want to refresh the page at all for end user...

Edit here is the btnSaveWatchList button with the class:

  <button data-remodal-action="cancel" class="remodal-cancel" id="cancelButton">Cancel</button>
    <button class="remodal-confirm btnSaveWatchlist">Save</button>

I have setup my HTML in razor like following:

  @if (ViewBag.Added != null)
                            {
                                if (ViewBag.Added == false)
                                {                        
                                    <div class="col-lg-2 col-md-3 col-sm-12 col-xs-12" id="wholeBtn">

                                     <a class="btn btn-app btnWatchList" style="min-width:100%;margin:0;height:67px">
                                    <i class="fa fa-save"></i> Add to Watchlist
                                  </a>
                                </div>
                                }
                                else if (ViewBag.Added)
                                {
                                    <div class="col-lg-2 col-md-3 col-sm-12 col-xs-12" id="addedToWatchList" style="padding:10px 0">
                                        <h4 style="text-align:center;margin-top:20px"><i class="fa fa-check" style="color:darkseagreen;font-size:25px"></i> Watching</h4>
                                    </div>
                                }
                            }
                            else
                            {
                                <div class="col-lg-2 col-md-3 col-sm-12 col-xs-12" id="wholeBtn">

                                    <a class="btn btn-app btnWatchList" style="min-width:175px;margin:0;height:67px">
                                        <i class="fa fa-save"></i> Add to Watchlist
                                    </a>
                                </div>
                            }

The onclick button looks like this:

$(".btnSaveWatchlist").on("click", function (event) {
       $.post("/User/SaveWatchList", { ment: $('#TextArea1').val(), rating: $('input[name=rating]:checked').val(), petitor: $('.txtSearch').val() }, $(this).prop('disabled', true))
                             .done(function (data) {
                                 if (data == "AllFieldsRequired") {
                                     ShowErrorMessage("All fields are required!");
                                     return;
                                 }
                                 else {
                                     $('.hideit').hide();
                                     $('.canvas').show();
                                     AnimateGreenCheck();
                                     setTimeout(function () {
                                         var result = $('<div />').append(data).find('#addedToWatchList').html();
                                         $('#wholeBtn').html(result);
                                         var l = document.getElementById('cancelButton');
                                         l.click();
                                     },
                                   3000);

                                     setTimeout(function () {
                                         ResetWatchListField();
                                     },
                                  4500);
                                 }
                             });
});

So initially this button "Add to watchlist" isn't present in DOM. It is loaded into the DOM after an search is performed on website.

Once that is done, onclick event works very fine. When post is done, I hide the button and update the DOM to show user that he added this user to watchlist.

Performing the search now again on different user that wasnt added to watchlist, and the button "Add to watchlist" with class "btnSaveWatchlist" is again loaded into the DOM.

But this time it is pletely unresponsive... I checked whether the action in controller gets initiated, it doesn't ... The button seems like it's "Frozen"...

Any ideas what could it be guys?

P.S. All this is done without refreshing the page at all. I don't want to refresh the page at all for end user...

Edit here is the btnSaveWatchList button with the class:

  <button data-remodal-action="cancel" class="remodal-cancel" id="cancelButton">Cancel</button>
    <button class="remodal-confirm btnSaveWatchlist">Save</button>
Share Improve this question edited Feb 17, 2017 at 19:41 User987 asked Feb 17, 2017 at 19:34 User987User987 3,82516 gold badges60 silver badges130 bronze badges 9
  • Where is the class btnSaveWatchlist in your HTML? – Tim Grant Commented Feb 17, 2017 at 19:36
  • @TimGrant I have shown the HTML markup above... – User987 Commented Feb 17, 2017 at 19:38
  • ...which does not appear to have the btnSaveWatchlist class. – Tim Grant Commented Feb 17, 2017 at 19:39
  • That's odd ,my bad.. I'll add it :) – User987 Commented Feb 17, 2017 at 19:41
  • @TimGrant Added the HTML for the button – User987 Commented Feb 17, 2017 at 19:42
 |  Show 4 more ments

3 Answers 3

Reset to default 3

Any ideas what could it be guys?

yeah, the difference between the markup (basically a plain string) and the Document Object Model. You attach event-listener to particular DOM-nodes, but when loading new markup, this node is disposed, and a new one is created from the markup you've provided.

And the event listener is also gone with the old node.

//listen for every 'click' event on an '.btnSaveWatchlist' that bubbles up to the `document.body`
$(document.body).on("click", ".btnSaveWatchlist", function (event) {
    //don't inline such stuff, it's pletely unreadable
    var postData = { 
        ment: $('#TextArea1').val(), 
        rating: $('input[name=rating]:checked').val(), 
        petitor: $('.txtSearch').val() 
    };

    //don't know why you put this into the $.post() call.
    //this line returns $(this), but the arguments for $.post() 
    //are url, data, successHandler and dataType.
    //and $(this) is neither a successHandler, nor a dataType
    $(this).prop('disabled', true);

    $.post("/User/SaveWatchList", postData)
        .done(function (response) {
            if (response == "AllFieldsRequired") {
                ShowErrorMessage("All fields are required!");
                return;
            } else {
                $('.hideit').hide();
                $('.canvas').show();

                AnimateGreenCheck();

                setTimeout(function() {
                    //you don't need to manually parse the response
                    var result = $('#addedToWatchList', response)
                        .html();

                    $('#wholeBtn').html( result );

                    //don't try to fire a click-event by code. 
                    //Better call the function that gets executed if this event happened

                    //since chances are good, that you used jQuery to register this click-listener
                    //triggering the click-event will probably call it.
                    //this is more reliable than relying on the click-function of a dom-node.
                    $('#cancelButton').click();
                }, 3000);

                //a function that just forwards the call to another function is useless
                //just pass the function you want to call.
                setTimeout(ResetWatchListField, 4500);
             }
        });
});

Your code is quite unclear to me at this time, so I'm not 100% sure this will solve the issue, but here's my go at it:

You are probably binding an element that you are rendering with jquery at a later time.

There are 2 ways to solve this. The easiest one (to me) is to use a parent-child style binding. This means you put the binding on the parent, and jQuery checks whether or not the child is clicked after the fact. This actually works with dynamic content (html that was loaded in through ajax or whatever)

Example:

var $parent = $('#parent'); //the element you append your html to

$parent.on('click', '.btnSaveWatchlist', function(){
  //Do whatever you want here
  //The binding will hold as long as the parent doesn't get replaced.
});

Or, there's the other way; making your function call re-set the binding every time you render the html (a tad less efficient)

Example:

Please note my ments here. I'm missing a lot of info so I put some "questions" in there.

function setBinding(){

  $(".btnSaveWatchlist").off('click');
  $(".btnSaveWatchlist").on("click", function (event) {
       $.post("/User/SaveWatchList", { ment: $('#TextArea1').val(), rating: $('input[name=rating]:checked').val(), petitor: $('.txtSearch').val() }, $(this).prop('disabled', true))
         .done(function (data) {
           if (data == "AllFieldsRequired") {
             ShowErrorMessage("All fields are required!");
             return; //this is not valid. make it true or false.
           }
           else {
             $('.hideit').hide();
             $('.canvas').show();
             AnimateGreenCheck();

             setTimeout(function () {
               var result = $('<div />').append(data).find('#addedToWatchList').html();
               $('#wholeBtn').html(result);
               var l = document.getElementById('cancelButton');

               //Why do you trigger the cancel button here? Doesn't this always cause it to cancel right away?
               l.click();
             },3000);

              setTimeout(function () {
                 ResetWatchListField();
                 //is this where you reset the html?
                 //in that case:
                 setBinding();
              }, 4500);
            }
        });
  });
}

You have to call setBinding() for a first time somewhere (like on document.ready?), or it won't work.

Note that you should call the setBinding() function after you render the button you need.

Somewhere, outside of the code you're showing in your question, you render this button. Whether it's true append() or html(), I don't know, but wherever you render this button, add this after the html(): element.html(myhtml).promise().done(setBinding);

I suggest you cerate a function with binding action.

function bindButton() {
    $(".btnSaveWatchlist").click(function () {
        $.post("/User/SaveWatchList", { ment: $('#TextArea1').val(), rating: $('input[name=rating]:checked').val(), petitor: $('.txtSearch').val() }, $(this).prop('disabled', true))
            .done(function (data) {
                if (data == "AllFieldsRequired") {
                    ShowErrorMessage("All fields are required!");
                    return;
                }
                else {
                    $('.hideit').hide();
                    $('.canvas').show();
                    AnimateGreenCheck();
                    setTimeout(function () {
                        var result = $('<div />').append(data).find('#addedToWatchList').html();
                        $('#wholeBtn').html(result);
                        var l = document.getElementById('cancelButton');
                        l.click();
                        bindButton();
                    },
                        3000);
                    setTimeout(function () {
                        ResetWatchListField();
                        bindButton();
                    },
                        4500);
                }
            });
    });
}

In your document ready, just call bindButton function. Then, after every call, you will have your button binded again, because your are cleaning the content of the div.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745351940a4623885.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信