简体   繁体   中英

How to write jquery selectors for dynamically generated html elements?

I'm currently writing an object oriented module which assigns callback to dynamically generated elements.

function Instant(containerID) {
    this.var1 = 0;
    this.var2 = 0;
    this.containerID = containerID;
    // and more variables...
};

And here containerID is the id of a DIV which is dynamically generated. I populate this DIV via Ajax Request which reads a file like the following:

<!-- content.html -->
<div class="general_container">
    <div class="top_container">
        <!-- plenty of divs, spans etc -->
    </div>

    <div class="tweet_section">
        <!-- plenty of divs, spans etc -->
    </div>
</div>

Now the important part is, I assign all callbacks like the following:

Instant.prototype.addCallbacks = function() {
    $(this.containerID + " bar").click(function() {
        $(this.containerID + " bar").foo();
    });

    $(this.containerID + " bar").click(function() {
        $(this.containerID + " bar").foo();
    });

    $(this.containerID+ " bar").click(function(e) {
        $(this.containerID + "bar, " + this.containerID+ " bar").foo();
    });
});


As you see, I always have to put this.containerID before each selector to assign events. (Therefore, I make sure I'm selecting only one element) Now, my code is full of clutter as I have plenty of this.containerID s. I don't know if there is a smarter method to make my code easy. Any help will be appreciated.

Here is a sample JSFiddle .

Note that this is not my real module, I just made it up to make it clear!

Then you shouldn't be using IDs. You should be using classes instead.

It would take long to edit your code , but here's a hint: Add a handler to the parent. Use event delegation, like .on() . Then have it listen for all children, now or future.

Create a separate java script file and put your add callbacks function in there and just pass the containerID. That way, you can re-use it later. However, looks like you cannot get rid of containterID since you will be needing that to do your add, subtract, save etc..

in your current file shown as above,

Instant.prototype.addCallbacks = createAddCallbacks(this.ContainerID);

create addCallbacks.js

function createAddCallbacks(containerId)
{
Instant.prototype.addCallbacks = function() {
    $(containerId + " bar").click(function() {
        $(containerId + " bar").foo();
    });

    $(containerId + " bar").click(function() {
        $(containerId + " bar").foo();
    });

    $(containerId+ " bar").click(function(e) {
        $(containerId + "bar, " + containerIdD+ " bar").foo();
    });
});
}

So, I think I find a better method according to this post
I wanted to limit the scope of my selector.

Firstly, I'll create a jQuery instance variable

function Instant(containerID) {
    this.var1 = 0;
    this.var2 = 0;
    this.container= $('#'+containerID);
    // and more variables...
};

and adding a new prototype like this

Instant.prototype.$ = function(selector){
    return this.container.find(selector);
};

I'll only use this.$(selector) function which is better.

Like @JosephTheDreamer said, use Event Delegation . ( Jquery.fn.on ) Using event delegation you set one handler to multiple targets. It means just one handler in memory and dynamic event handlers set.

I made a demonstration modifying your code, take a look...

Instant.prototype.addCallbacks = function () {
    var selfContainer = null, // DOMElement container
        me = this; // Object reference

    $('body').on("click", ".selection_container .btn-add", function () { //Using event delegation
        selfContainer = $(this).parents(".general_container"); //set DOMElement
        selfContainer.find("input[name=currentValue]").val(++me.instantValue);
    });

    $('body').on("click", ".selection_container .btn-subtract", function () {
        selfContainer.find("input[name=currentValue]").val(--me.instantValue);
    });

   $('body').on("click", ".selection_container .btn-reset", function () {
        me.instantValue = 0;
        selfContainer.find('input[name=currentValue]').val(0);
    });

    $('body').on("click", ".selection_container .btn-save", function () {
        me.savedValue = me.instantValue;
    });

    $('body').on("click", ".selection_container .btn-load", function () {
        me.instantValue = me.savedValue;
        selfContainer.find('input[name=currentValue]').val(me.savedValue);
    });
};

Hope it helps...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM