0

I am using ie 11. I am adding a row to a table. I am using a modal popup to enter the data and I am making an AJAX call to update the underlying data. When that is done, I am using JQuery to add the row to the table. This all works fine except for one thing. The end of the tablerow contains a button. All the other buttons on the table work, but the new button does not. When I look in developer tools the button for the new row has the same mark up as the mark up for the others, so it should work in the same way. So the table looks this;

        <table class="GridTbl" id="surveyList">
            <thead>
                <tr>
                    <th>Survey</th>
                    <th>Contract</th>
                    <th>Select</th>
                </tr>
            </thead>
            <tbody>
                @foreach (var contract in
                    SessionObjectsMSurvey.ContractList.Where(x => x.SurveyId > 0)
                                        .OrderByDescending(x => x.SurveyCreated))
                {
                    <tr>
                        <td>@contract.SurveyTitle</td>
                        <td>@contract.ContractTitle</td>
                        <td>
                            <button class="btn btn-xs btn-primary selectContract"
                                    data-msurvey-row-id="@contract.RowId">
                                Select
                            </button>
                        </td>
                    </tr>
                }
            </tbody>
        </table>

I add the row of data here. Notice the button has a class of selectContract. This works

var addRowToTable = function (data) {
    var row =
    '<tr>' +
        '<td>{{surveyTitle}}</td>' +
        '<td>{{contractTitle}}</td>' +
        '<td>' +
        '<button class="btn btn-xs btn-primary selectContract" data-msurvey-row-id="{{rowId}}">Select</button>' +
        '</td>' +
    '</tr>';


    //Add row
    $('#surveyList').prepend(row.compose({
        'surveyTitle': data.SurveyTitle,
        'contractTitle': data.ContractTitle,
        'rowId': data.RowId
    }));
};

And this is the click event which usually works but not for the new row. The button on the new row does fire an event, I do not know where the event handler is, it should be this one but it isn't;

$(".selectContract").on("click", function (e) {
    e.preventDefault();
    var $this = $(this);
    var rowId = $this.data("msurvey-row-id");
    var url = GetHiddenField("msurvey-get-contract-and-survey-url");
    dataService.getContractAndSurvey(rowId, displayContractInfo, url);
});
arame3333
  • 9,887
  • 26
  • 122
  • 205
  • 2
    Use event delegation: [What is DOM Event delegation?](http://stackoverflow.com/a/1688293/402037) -> `$(#surveyList").on("click", "button.selectContract", function(e) { ... })` – Andreas Oct 27 '15 at 11:46
  • @Ed Cottrell No. I am already using on, which was the solution. – arame3333 Oct 27 '15 at 11:47
  • 1
    @arame3333 it seems youre not understanding the principle of on() http://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements – Alex Oct 27 '15 at 11:48
  • @arame3333 No, you are using `on` *without event delegation*. The solution in the question to which I linked is to use `on` *with event delegation*, which is the standard way to address this issue. – elixenide Oct 27 '15 at 11:49
  • OK, just checking that now. I forgot about that. I just tried $(".selectContract").on("click", "button", function (e) { but this did not work. – arame3333 Oct 27 '15 at 11:56
  • @arame3333 that isn't how you would handle it. See Alex's answer. The first parameter must be a selector for an element that is not itself dynamically added or modified. – elixenide Oct 27 '15 at 11:58
  • Thank you guys, got there in the end. Thanks especially to Ed Cottrell. – arame3333 Oct 27 '15 at 12:05
  • @arame3333 glad it helped! – elixenide Oct 28 '15 at 05:28

1 Answers1

4

Just to add some clarification. You said in the comments that you are already using on() for event delegation:

$(".selectContract").on("click", function (e) {

But what happens here exactly? You are using on() indeed, but only to the selector as it exists when running that block of code (= direct event binding). Or said otherwise: You have to bind the on method on a parent which is consistent, for instance like so:

$('#surveyList').on("click", ".selectContract", function (e) {

This will work for all elements inside #surveyList of class ".selectContract" whenever, dynamically created = event delegation.

Have an indepth look at this Event binding on dynamically created elements?

On() does not necessarily mean event delegation. You can also use it in combination with off().

Community
  • 1
  • 1
Alex
  • 9,911
  • 5
  • 33
  • 52