2016-08-02 15 views
2

Ich habe eine Liste von Orten in Google Maps, auf die ein Benutzer klicken kann. Wenn sie klicken, erzeuge ich eine Vorlage, die die Informationen für diesen Ort anzeigt. Im Moment habe ich ein Container-Div, das ich mit der neu erzeugten Vorlage .replaceWith() anrufe.Listener zu dynamisch hinzugefügtem HTML innerhalb von Closure hinzufügen?

Wenn ein Benutzer versucht, auf eine Schaltfläche in dieser Vorlage zu klicken, möchte ich eine ortspezifische Aktion ausführen (z. B. den Ort anheften). Um dies zu tun, brauche ich die Ort-ID irgendwo gespeichert, damit der Listener-Code weiß, was zu tun ist. Ich hatte gehofft, einen Verschluss zu verwenden, um die Hörer on the fly zu erstellen, so dass ich die ID des Orts „umschließen“ könnte, dass der Betrachter Details wird immer für:

function selectPlace(place_id) { 

    // Swap out the old template 
    $("#listing-placeholder").replaceWith(listing_info_template(place)); 

    // Create a listener to handle clicks while remembering the place_id 
    (function(){ 
     $('.save_button').click(function(){ 
      alert("Clicked handler for " + place_id); 
     }); 
    })(); 
} 

Dies scheint nicht überhaupt zu arbeiten ; mein Zuhörer feuert nie. Es scheint, dass dies mit der Tatsache zusammenhängt, dass .save_button innerhalb der Vorlage liegt (dynamisch hinzugefügt). Nicht sicher, warum das so ist.

Ich zögere, .on() zu verwenden, denn dann müsste ich die ID irgendwo in die Vorlage setzen, was sich für mich echt hacky anfühlt. Ich weiß, dass backbonejs Ereignisse irgendwie an dynamisch eingefügte Vorlagen bindet, so dass jeder relevante Kontext für Ereignisse noch verfügbar ist - das ist effektiv, was ich hier nachahmen möchte.

Also, irgendwelche Vorschläge, wie ich einen Listener zu einem dynamisch erstellten Element in einer Weise hinzufügen kann, dass der Listener Schlüsselinformationen über das "Objekt" erhält, das konzeptionell darstellt, ohne den HTML mit zusätzlichen Metadaten aufzublähen (I habe Leute gesehen, die die IDs wie "save_button-" machen und dann auf dem Armaturenbrett teilen, aber das scheint extrem hacky?)?

Danke!

+0

untersuchen Vielleicht Local Storage mit dem Zustand des ausgewählten Id zu erhalten: https://developer.mozilla.org/en/docs/Web/API/Window/localStorage. Dann kannst du jquerys 'on' verwenden. –

+0

Du schlägst vor, dass ich die ID irgendwo im HTML speichern und dann als einen Index in meinen lokalen Speicher verwenden soll, richtig? Ich habe darüber nachgedacht, aber es fühlt sich falsch an, die ID im html zu speichern - sollte es nicht eine Art Schließung geben, die das kann? Backbone scheint in der Lage zu sein, den Objektkontext an den HTML- und Listener zu binden, ohne die ID in den HTML-Code einzufügen. – droptic

+0

Nicht der HTML-Code, aber Sie haben viele Optionen, um die ausgewählte ID zu speichern.Lokaler Speicher, erstelle eine Variable mit einem boader scope, oder wie du in html erwähnt hast (wie ein verstecktes Feld, aber ja, das ist hässlich) und wahrscheinlich ein paar mehr. –

Antwort

1

ich eine Variable mit einem breiten Anwendungsbereich verwendet haben, halten ausgewählt Id in der schnelles und schmutziges Beispiel unten.

var selectedId; //Holds seleced ID 
 

 
function selectPlace(place_id) { 
 

 
    // Swap out the old template 
 
    //$("#listing-placeholder").replaceWith(listing_info_template(place)); 
 
    $("#listing-placeholder").replaceWith($("#section" + place_id)); 
 
    //Sotre the ID here 
 
    selectedId = place_id; 
 
} 
 

 
$(document).ready(function() { 
 
    $("#cbId").change(function() { 
 
    selectPlace($(this).val()) 
 
    }); 
 

 
    //Set up event listener. Change #target as appropriate for you 
 
    $("#target").on("click", ".save_button", function() { 
 
    alert(selectedId); 
 
    }); 
 

 
});
#sections { 
 
    display: none; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 
<div> 
 
    <label>Select a section 
 
    <select id="cbId"> 
 
     <option></option> 
 
     <option>1</option> 
 
     <option>2</option> 
 
     <option>3</option> 
 
    </select> 
 
    </label> 
 
</div> 
 
<div id="target"> 
 
    <div id="listing-placeholder"> 
 
    I'm the place holder 
 
    </div> 
 
</div> 
 
<div id="sections"> 
 
    <!--No Event Listeners Will be bound directly untill template is replaced --> 
 
    <div id="section1"> 
 
    <h2>I'm section 1</h2> 
 
    <input type="button" value="Save Button" class="save_button"> 
 
    </div> 
 
    <div id="section2"> 
 
    <h2>I'm section 2</h2> 
 
    <input type="button" value="Save Button" class="save_button"> 
 
    </div> 
 
    <div id="section3"> 
 
    <h2>I'm section 3</h2> 
 
    <input type="button" value="Save Button" class="save_button"> 
 
    </div> 
 
</div>

+0

Dies ist wahrscheinlich am einfachsten, jetzt habe ich darüber nachgedacht. Ich bin definitiv neugieriger darüber, wie das funktionieren würde, wenn ich mehr als einen Gegenstand hätte (eine Liste zum Beispiel). Ich versuche immer noch herauszufinden, wie man Daten für ein Objekt an einen Callback "bindet", so dass der Callback Zugriff auf die relevanten Kontextdaten hat, wenn ich auf diesen Eintrag in der Liste klicke. BackboneJS scheint dies leicht zu erreichen, aber es scheint wirklich schwierig, wenn nicht unmöglich in normalen Jquery? – droptic

+0

Denken Sie daran, dass diese Variable mehr als eine ID enthalten kann. Es kann komplexe Javascript-Objekte enthalten, wenn Sie es auch brauchen. Sehen Sie sich auch die Datenattribute an: https://developer.mozilla.org/en/docs/Web/Guide/HTML/Using_data_attributes und https://api.jquery.com/data/. Beachten Sie mit der Jquery API, die Sie an den HTML-Body anhängen können. –

+0

Und zum Vergleich von jQuery mit Backbone, vergleichen Sie mit Framework mit verschiedenen Objekten. JQuery, wenn primär auf DOM-Manipulation konzentriert, während Backbone ein MVP-Framework ist. –

1

Ich werde nur versuchen, Ihren tatsächlichen Ansatz zu korrigieren, indem Sie den Parameter an Ihre Schließung übergeben, aber Sie können einen besseren Ansatz finden.

In Ihrem Fall müssen Sie auch die place_id als Parameter zur Schließung passieren, ist dies, wie Ihr Code sein sollte:

function selectPlace(place_id) { 

    // Swap out the old template 
    $("#listing-placeholder").replaceWith(listing_info_template(place)); 

    // Create a listener to handle clicks while remembering the place_id 
    (function(id){ 
     $('.save_button').click(function(){ 
      alert("Clicked handler for " + id); 
     }); 
    })(place_id); 
} 

ich den Variablennamen geändert, so dass Sie den Unterschied zwischen den beiden bekommen Parameter.

+0

Wenn ich das tue, feuert der Listener überhaupt nicht (keine Warnung, wenn ich klicke), gleich wie vorher. – droptic

+0

Dies funktioniert meistens (https://jsfiddle.net/jpn6kg34), aber da ein Handler jedes Mal hinzugefügt wird, wenn 'selectPlace' aufgerufen wird, müssen Sie zuerst die Handler löschen (https://jsfiddle.net/jpn6kg34/1/) –

0

Sie müssen tatsächlich .on verwenden, es ist die Art, wie jQuery alle dynamisch hinzugefügten Elemente abgleicht. Aber Sie brauchen nichts „Hacky“ zu tun, müssen Sie nur noch den Hörer an ein übergeordnetes Element binden

`$(parent).on('click', '.save_button', {}); 
+0

Wenn ich dies tue, habe ich keine kontextuellen Informationen, also wenn der Listener feuert, werde ich nicht die ID oder andere Kontextinformationen für das Objekt haben. Gibt es einen Weg darum, ohne zusätzliche Attribute auf dem HTML-Element selbst zu speichern? (das scheint hacky zu mir zu sein) – droptic

0
function selectPlace(place_id) { 

    // Swap out the old template 
    $("#listing-placeholder").replaceWith(listing_info_template(place)); 

    // Create a listener to handle clicks while remembering the place_id 

     $(document).on('click', '.save_button').click(function(){ 
      alert("Clicked handler for " + place_id); 
     }); 
} 
+0

Wenn ich dies tue, addieren sich alle Zuhörer und ich ende mit drei "on" Zuhörern, wenn ich drei Punkte in der Liste ausgewählt habe. Der Alarm wird also dreimal mit drei verschiedenen IDs ausgelöst, wenn er nur mit der ID des aktuell ausgewählten IDs ausgelöst werden soll. – droptic

Verwandte Themen