How do I rebind the dialog after it is being rewri

2019-07-17 05:47发布

I have a table of students and in each row are their names, a select list to select their attendance for their lesson and then a "Message" link when clicked will popup a a dialog to send a message to the student.

The table is dynamically driven by a select list of courses. For example, a teacher selects a course and then the table is repopulated with all the students within that course. This is done through AJAX. The table body is basically getting written every time a course is selected. My problem is this, when a new course is selected, the div for the dialog becomes visible inside the cell of the Message link. I suspect the problem is to do with AJAX and not being able to rebind the link and click event. How do I therefore overcome this?

This is my table generated in PHP (http://pastebin.com/CTD3WfL6):

public function createTable($cid)
{   

    $userModel = new Users();
    $attendanceModel = new Attendance();
    $students = $userModel->getStudents($cid);

    $table2 = '<table id="tutorTable">';
    $tableHeaders = 
    '<thead>
        <th>Student Name</th>
        <th>Attendance</th>
        <th>Message</th>
        <th>Mobile</th>
        <th>Parent Name</th>
        <th>Message</th>
    </thead>
    <tbody>';
    $table2 .= $tableHeaders;
    foreach($students as $student)
    {
        $table2 .= 
        '<tr><td id="studentName">'.$student['firstname'].' '.$student['lastname'].'</td>
             <td>
                <select class="attendSelect" id="studentSelect"'.$student['id'].'>
                    <option value="Attended">Attended</option>
                    <option value="Absent">Did not Attend</option>
                    <option value="Excused Absent">Excused</option>
                    <option value="Late">Excused</option>
                    <option value="Excused Late">Did not Attend</option>
                </select>
            </td>
            <td>            
                <a href="#MessageStudent" class="popUpLink">Message</a>
                <div class="popUpDialog"  id="'.$student['id'].'" title="Message '.$student['firstname'].' '.$student['lastname'].'">                                       
                    <form id="studentForm" action="" method="POST">     
                        <fieldset>
                            <input type="hidden" value="message_send" name="action"/>
                            <input type="hidden" value="'.$student['id'].'" name="studentId"/>
                            <textarea rows="3" cols=35" name="message"></textarea>
                            <input type="submit" value="Send Message"/>
                        </fieldset>
                    </form>
                </div>      
            </td>       
            <td>'.$student['phone1'].'</td>
            <td>Parent name goes here</td>
            <td>
                <a href="mailto:ParentsEmail@email.com" id="parentEmail">Message</a>            
            </td>       
        </tr>';
    }

    $table2 .= '</tbody></table>';

    return $table2;     
}

This is the jQuery to handle the dialog and the table:

/** Dialog Handler **/
 $('.popUpLink').each(function()
{

    $divDialog = $(this).next('.popUpDialog');
    $.data(this, 'dialog', $divDialog.dialog(
    {
        autoOpen: false,
        modal: true,
        title: $divDialog.attr('title')

    }));
}).on('click',function() 
{ 
    $.data(this, 'dialog').dialog('open'); 
    return false; 
}); 
/**AJAX to handle table **/
$('#courseSelect').on('change', function()
{       
    var cid = $('#courseSelect').val();

    $.getJSON('?ajax=true&cid=' + cid, function(data)
    {     
        var lessonSelect = "";
        var count = 1;
        /** populate select list of lessons **/
        for(var i in data.lessons)
        { 
            lessonSelect += '<option id="' + count + '" value="' + data.lessons[i].id+ '">' + data.lessons[i].name + '</option>'        
            count++;            
        };

        var lessonDialog = '<p>' + data.lessons[0].name + '</p>';
        var launchLessonDiv = '<a href=" ' + data.launchLesson.reference + ' ">Launch Lesson</a>';
        var courseDialog = '<p>' + data.course.fullname + '</p>';

        $('#lessonSelect').html(lessonSelect);
        $('#lessonDialog').html(lessonDialog);//insert lesson information into lesson dialog
        $('#launchLessonDiv').html(launchLessonDiv);//insert link to launch lesson
        $('#courseDialog').html(courseDialog);

        /**Repopulate table **/
        //var lessonCount = 1;
        //var table = createTutorTable(data, cid, lessonCount); 
        //$('table#tutorTable>tbody').html(table);
        $('form#tutorTableForm').html(data.table);  


    });//getJSON      
});//Course select

Everything works fine until a new course is selected and the textarea becomes visible inside the cell. I've only just started jQuery last month so bear with me!

10条回答
疯言疯语
2楼-- · 2019-07-17 06:13

You are overwriting the table so the state of the dialog gets lost every time.

查看更多
Bombasti
3楼-- · 2019-07-17 06:16
$('#tutorTable').delegate('.clickElement', 'click' function(){
     var elem = $(this);  //which will be your div/dialog if you supply the right selector 

     /*No need to rebind events since this handler will be attached to the #tutorTable
     It will listen for the desired event and delegate it back 
     to the element that matches the supplied selector.*/


});
查看更多
叛逆
4楼-- · 2019-07-17 06:18

generally,jQuery binds all the element with event on load time however it can not be bonded to the dynamic functions by .click() methods for this use .live method which is far more effective in dynamic event binding.
You can also try using live function. http://docs.jquery.com/Events/live and read with example at http://api.jquery.com/live/

after applying it will be something like

$('.popUpLink').live('click',function()
{
    $.data(this, 'dialog').dialog('open');
    return false;
});
查看更多
聊天终结者
5楼-- · 2019-07-17 06:19

Here is a simpler example. I hope it demonstrates what you are asking. You can see a working version at http://jsfiddle.net/4wEPm/2/

When you overwrite the content of the table with ajax, the references to the dialog box is lost. I think it's easier just to reinitialize the dialog boxes again.

I am using a delegate on the table (based on your example the table element doesn't get overwritten, just the rows). This way the click listener will persist after the ajax call. Whenever the dialog div is initialized by jquery, the div is moved to the end of the page. So, I added a reference to the dialog object in the anchor, just for easy access to invoke dialog('open'). Since I am handling the initialization, and opening of the dialog box in the same click function, the dialog div needs to be hidden to begin with.

Also, in the ajax call, it's best to clean up the old dialog boxes, as new one will get created.

<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" />
<div>
<table id="t1" border="1">
<tr>
    <td><a href="" class="popup">message 1</a>
        <div class="dlog" style="display: none">dialog 1</div>
        <p>stuff</p>
        <p>
        <button class="btn"> faking ajax </button>
        </p>
    </td>
</tr>
<tr>
    <td><a href="" class="popup">message 2</a>
        <div class="dlog" style="display: none">dialog 2</div>
        <p>stuff</p>
        <p>
        <button class="btn"> faking ajax </button>
        </p>
    </td>
</tr>
</table>
<br/><br/>

<script>
$("#t1").on('click', '.popup', function(e){
/* 
   initialize the dialog box on the first click of the message link
   and insert a reference to the newly created dialog box, the next
   time the link is clicked, don't need to initialize, just invoke open
 */ 
if (typeof $(this).data("dialog-ref") == "undefined"){
    $(this).data("dialog-ref", $(this).next('.dlog').dialog({ modal: true }));
}else {
    $(this).data("dialog-ref").dialog('open');
}
return false; // don't follow the link.
});


// this is just to fake the ajax calls and overwrites the table content.
$("#t1").on('click', '.btn', function(){

    // clean up of the old dialog boxes, because the new content will have new dialog boxes.
    $('#t1 .popup').each(function() {
        try {
            $(this).data('dialog-ref').dialog('destroy');
        }catch(err) {
        }
    });

    var x = Math.floor(Math.random() * 100);
    var table = $("<tr><td><a href='' class='popup'>message "+x+"</a><div class='dlog' style='display: none'>dialog "+x+"</div><p>stuff</p><button class='btn'> faking ajax </button></td></tr><tr><td><a href='' class='popup'>message "+(x+1)+"</a><div class='dlog' style='display: none'>dialog "+(x+1)+"</div><p>stuff</p><p><button class='btn'> faking ajax </button></p></td></tr>");
    $("#t1").html(table);
});    
</script>

查看更多
登录 后发表回答