2012-02-19 30 views
13

chọn của tôi là:jQuery selector không cập nhật sau khi tự động thêm các yếu tố mới

$('section#attendance input:last') 

Tuy nhiên, tôi thêm một đầu vào cho phần # tham dự. Tôi muốn bộ chọn bây giờ chọn phần tử đó (vì nó phải là vì :last. Tuy nhiên, vì lý do nào đó, nó không, và tôi không chắc chắn tại sao?

Đây là mã đầy đủ của tôi:

$('section#attendance input:last').keydown(function(e) { 
     if (e.which == 9) 
     { 
      var $this = $(this); 
      var num = parseInt($this.attr('name').match(/\d+(,\d+)?/)[0]) + 1; 
      $this.parent().append('<input type="text" name="attendance[' + num +']" value="Name and Position" class="medium" />'); 
     } 
    }); 

Mã mới:

$("section#attendance").on("keydown", "input:last", function(e) { 
    if (e.which == 9) { 
     var $this = $(this); 
     var num = parseInt($this.attr('name').match(/\d+(,\d+)?/)[0]) + 1; 
     $this.after('<input type="text" name="attendance[' + num +']" value="Name and Position" class="medium" />'); 
    } 
}); 

EDIT: vấn đề này có vẻ là trên 'đầu vào: cuối cùng', vì nó hoạt động nếu tôi chỉ sử dụng đầu vào Ngoài ra, nếu tôi thêm lớp 'cuối cùng' vào. phần tử cuối cùng, nó hoạt động khi tôi sử dụng 'input.last' làm công cụ chọn.

Trả lời

11

Tùy thuộc vào những gì phiên bản jQuery bạn đang sử dụng, bạn nên sử dụng một trong hai .delegate() (trước jQuery 1.7) hoặc .on() (jQuery 1.7+) để xử lý sự kiện được ủy quyền sẽ xử lý các sự kiện cho các phần tử được thêm động. Lưu ý .live() đã không được chấp nhận từ tất cả các phiên bản của jQuery nên không còn được sử dụng nữa.

Sử dụng .on(), bạn có thể sử dụng này:

$("#attendance").on("keydown", "input:last", function(e) { 
    if (e.which == 9) { 
     var $this = $(this); 
     var num = parseInt($this.attr('name').match(/\d+(,\d+)?/)[0]) + 1; 
     $this.parent().append('<input type="text" name="attendance[' + num +']" value="Name and Position" class="medium" />'); 
    } 
}); 

Sử dụng .delegate() sẽ tương tự (trừ các đối số là theo một thứ tự khác nhau). Bạn có thể thấy cả hai tài liệu trong tài liệu jQuery .delegate().on().

Thao tác xử lý sự kiện được ủy quyền hoạt động bằng cách sử dụng khả năng "sủi bọt" của một số sự kiện javascript. Điều này cho phép bạn đính kèm một trình xử lý sự kiện vào một đối tượng cha mẹ (không đến và đi) và để nó xem xét từng sự kiện "bong bóng" từ một đứa trẻ, kiểm tra xem sự kiện có xuất phát từ một đối tượng hay không bộ chọn thích hợp và nếu có, hãy thực thi mã xử lý sự kiện của bạn. Bằng cách này, khi các đối tượng đến và đi, các sự kiện của chúng vẫn được xử lý một cách thích hợp.

Như ban đầu bạn đang làm việc, bạn sẽ ràng buộc trình xử lý sự kiện trực tiếp với đối tượng khớp với bộ chọn 'section#attendance input:last' tại thời điểm mã ràng buộc sự kiện chạy.Từ đó trở đi, nó được liên kết trực tiếp với đối tượng cụ thể đó bất kể đối tượng đó vẫn khớp với bộ chọn hay nếu các đối tượng mới được thêm vào DOM phù hợp với bộ chọn. Xử lý sự kiện được ủy quyền sử dụng .delegate() hoặc .on() cho phép hành vi xử lý sự kiện trở nên năng động hơn - tự động điều chỉnh theo các thay đổi trong DOM. Bạn chỉ cần liên kết sự kiện với một đối tượng cha mẹ chung sẽ không thay đổi và nó có thể tự động giám sát tất cả các con của nó.

+1

Hey, tôi đã thử điều này, nhưng vì một lý do nào đó, nó dường như không hoạt động. Tôi đã cập nhật bài đăng của mình bằng mã mới và tôi đã xem qua các tài liệu cho .on(), nhưng tôi không thể tìm ra điều gì sai. Chúc mừng sự giúp đỡ! – chintanparikh

+0

Vấn đề là thẻ đầu vào bạn thêm không có đúng loại thuộc tính tên mà mã của bạn đang mong đợi. Bạn đã không tiết lộ HTML của bạn, nhưng nó không nhìn tôi như mã của bạn có thể làm việc vì cách nó phân tích số ra khỏi thuộc tính name. Regex của bạn khớp với hai số có dấu phẩy ở giữa, nhưng thẻ nhập mới mà bạn thêm không có định dạng đó. Bạn có thể thấy một phiên bản đơn giản hơn ở đây: http://jsfiddle.net/jfriend00/uVHwK/. Chúng tôi sẽ phải xem HTML của bạn để tư vấn cụ thể hơn. – jfriend00

5

Để phản ứng với nội dung được chèn động, bạn sẽ phải sử dụng các sự kiện được ủy quyền. Chức năng hiện được đề xuất để thực hiện điều này là .on() (live không được dùng nữa, binddelegate được thay thế).

+3

'bind' và' delegate' không được dùng nữa. –

+2

Bạn nói đúng. 'live' không được chấp nhận,' bind' và 'delegate' được thay thế. – nijansen

1

Vấn đề rất có thể là do bạn đang sử dụng sự kiện keydown. Điều đó thực sự sử dụng liên kết với bộ chọn. Chỉ ràng buộc các mục hiệu ứng tồn tại khi nó được đính kèm lần đầu tiên. Tài liệu JQuery cho biết:

bind() gắn các sự kiện vào các phần tử tồn tại hoặc khớp với công cụ chọn tại thời điểm thực hiện cuộc gọi. Bất kỳ phần tử nào được tạo sau đó hoặc khớp với nhau sẽ chuyển tiếp vì lớp đã được thay đổi, sẽ không kích hoạt sự kiện bị ràng buộc.

Bạn nên xem xét để thay thế KeyDown với một cái gì đó như sau:

$('section#attendance).on("keydown", "input:last", function(e) {...}); 
4

Không sử dụng trực tiếp! Sử dụng on

Phương thức trực tiếp đã không được chấp nhận do hiệu suất kém, thay vào đó hãy sử dụng phương thức on.

$('section#attendance').on('keydown', 'input:last', function(e) { 
    /* ... code ... */ 
}); 

Cũng không có lý do gì để có thẻ section trước bộ chọn id của bạn.

Các vấn đề liên quan