2017-03-31 1 views
0

TL; DR:Wie mache ich DOM/Event-Listener auf neu angehängte Knoten aufmerksam?

Ich benutze $(..).append(node), aber neu hinzugefügte Knoten nicht für die Aufnahme trotz sie (angeblich) passende jQuery Selektoren betrachtet.

Frage

Ich habe einige Code unten, dass verwendet Kontrollkästchen aber emuliert Verhalten Optionsfeld. Mit anderen Worten, nur ein Kontrollkästchen kann (gültig) jederzeit ausgewählt werden. Es sollte nicht mehr als eine ausgewählt werden.

Wenn Sie das folgende Beispiel ausführen und auf die ersten 3 Kontrollkästchen klicken, verhalten sie sich wie Optionsfelder. Nur eine wird ausgewählt, egal wie oft Sie klicken.

Wenn Sie jedoch Punkt hinzufügen, werden neu hinzugefügte Punkte nicht für die JS in Betracht gezogen werden, auch in der Theorie, obwohl es ihnen greifen sollte ...

Im Einzelnen: Sie können die neu hinzugefügte Checkbox auswählen und Es wird zusätzlich zu einem bereits ausgewählten ausgewählt. Das ist falsch, da immer nur 1 ausgewählt werden sollte und alle anderen nicht ausgewählt werden sollten.

Was passiert und wie kann ich neu hinzugefügt Knoten in jQuery Selektoren enthalten?

$(function() { 
 

 
    //check first box 
 
    $("input.duty:first").prop("checked", true); 
 

 
    //clicking unchecked box should check that box 
 
    //unchecks all others 
 
    $(".duty").on('click', function(event) { 
 
    $("input.duty").prop("checked", false); 
 
    $(this).prop("checked", true); 
 
    }); 
 

 
    $("#addCasePoint").on("click", function() { 
 
    var newRowIndex = $('#newRowIndex').text(); 
 
    var template = $('#casePointTemplate').data('template'); 
 
    template = template.replace(/__index__/g, newRowIndex); 
 
    $('#casePointsFieldset').append(template); 
 
    $('#newRowIndex').text(++newRowIndex); 
 
    return false; 
 
    }); 
 

 
    //deletes case point 
 
    $("#selection").on("click", ".removeCase", function() { 
 
    var caseCount = $('#selection .casePointFieldset').length 
 
    if (caseCount === 1) return false; //keep at least one row 
 
    $(this).closest("fieldset").remove(); 
 
    return false; 
 
    }); 
 
});
.casePointFieldset { 
 
    display: inline-block; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<form id="selection"> 
 
    <fieldset id="casePointsFieldset"> 
 
    <legend>Case Points</legend> 
 
    <div id="pointFieldset"> 
 
     <fieldset class="casePointFieldset"> 
 
     <div> 
 
      <label><span>Duty:</span> <input name="point[1]" class="duty" value="1" type="checkbox"></label> 
 
     </div> 
 
     <button class="removeCase">Remove</button> 
 
     </fieldset> 
 
     <fieldset class="casePointFieldset"> 
 
     <div> 
 
      <label><span>Duty:</span> <input name="point[1]" class="duty" value="1" type="checkbox"></label> 
 
     </div> 
 
     <button class="removeCase">Remove</button> 
 
     </fieldset> 
 
     <fieldset class="casePointFieldset"> 
 
     <div> 
 
      <label><span>Duty:</span> <input name="point[1]" class="duty" value="1" type="checkbox"></label> 
 
     </div> 
 
     <button class="removeCase">Remove</button> 
 
     </fieldset> 
 
    </div> 
 
    <!-- include template --> 
 
    <span id="casePointTemplate" data-template="<fieldset class=&quot;casePointFieldset&quot;><div><label><span>Duty:</span> <input name=&quot;point[__index__]&quot; class=&quot;duty&quot; value=&quot;1&quot; type=&quot;checkbox&quot;></label></div><button class=&quot;removeCase&quot;>Remove</button></fieldset>"> 
 
    </span> 
 
    </fieldset> 
 

 
    <button id="addCasePoint">Add Point</button> 
 
</form>

+1

* Event Delegation * wäre ein gutes Thema für Sie zu Google und erfahren Sie ein wenig über. –

Antwort

2

Das Problem ist, wie Sie zu ihnen binden. Die .click Funktion (oder .on('click')) funktioniert im Prinzip wie folgt aus:

  1. alle der finden zur Zeit bestehenden Elemente, die einen Selektor ($('.your.selector.here')) entsprechen
  2. Bringen Sie einen Event-Handler zu jedem diesen Elemente

Beachten Sie, wie ich erwähnte, dass es an diejenigen bindet, die bereits existieren? Das heißt, es wird nicht automatisch an neu erstellte gebunden. Sie können jedoch .on verwenden, um an das übergeordnete Element dieser Elemente zu binden und dann auf Ereignisse in einem Selektor zu warten. Ich werde Ihnen zeigen, was ich meine:

$('#addItem').click(function() { 
 
    $('.container').append('<button class="item">Item</button>'); 
 
}); 
 

 
// Notice that I'm binding to the parent 
 
// then specifying which events from it's children 
 
// I want to listen to (click events from .item elements) 
 
$('.container').on('click', '.item', function() { 
 
    console.log("I'm an item"); 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div class="container"> 
 
    <button class="item">Item</button> 
 
</div> 
 
<button id="addItem">Add New Item</button>

Wenn Sie Ihren on('click' ändern, so zu arbeiten, dann werden Sie keine Probleme haben.

+1

danke. Ich fand, dass ich auch neue Ereignisse binden konnte, indem ich ': last' auswähle, wenn ich einen neuen Knoten hinzufüge. Aber was Sie haben, ist besser (weniger Code-Duplizierung) – Dennis

1

Der einfachste Weg sein wird, das Ereignis an das Dokument angehängt wird. In der Vergangenheit wurde dies mit der live() Methode gemacht.

$(document).on('click', '.duty', function(event) { 
     $("input.duty").prop("checked", false); 
     $(this).prop("checked", true); 
    }); 
Verwandte Themen