spraff
spraff

Reputation: 33425

Why is my custom jQuery `change` event being triggered twice?

I am trying to make a jQuery-compatible composite HTML input.

In this example when either select changes, the alert is invoked twice. Why?

Given a simple container node:

<span id="x"></span>

Here is a fully working demo:

function el (type) {
    return document .createElement (type);
}

function opt (sel, value) {
    let node = el ('option');
    node .value = value;
    node .appendChild (document .createTextNode (value));
    sel .appendChild (node);
}

let x = document .getElementById ('x');
let a = el ('select');
let b = el ('select');

x .appendChild (a);
x .appendChild (b);

opt (a, 'a_1');
opt (a, 'a_2');
opt (b, 'b_1');
opt (b, 'b_2');

$(a) .change (function () {$(x) .trigger ('change');});
$(b) .change (function () {$(x) .trigger ('change');});

$(x) .change (function () {alert ('changed');});

Upvotes: 5

Views: 78

Answers (2)

Edmundo Santos
Edmundo Santos

Reputation: 8287

Does the onchange event propagate?

The jQuery documentation suggests that this event applies only to inputs, selects and textarea, in any case, what is happening is propagation (bubble) to the parent element.

If you stop the propagation, will work:

$(a) .change (function (event) {
    $(x) .trigger ('change');
    console.log('a');
    event.stopPropagation();
});

$(b) .change (function (event) {
    $(x) .trigger ('change');
    console.log('b');
    event.stopPropagation();
});

Upvotes: 0

Haresh Vidja
Haresh Vidja

Reputation: 8496

Its because when you are change value in dropdown it change parent evelement drom structure. it means you are changing value of A an B it patent of A and B is X so it change automatically so you have to stop event propagation

you have to remove below code

$(a) .change (function () {$(x) .trigger ('change');});
$(b) .change (function () {$(x) .trigger ('change');});

or you have to use preventDefault();

$(a) .change (function (e) {e.preventDefault(); $(x) .trigger ('change'); return false; });
$(b) .change (function (e) {e.preventDefault(); $(x) .trigger ('change'); return false; });

Upvotes: 3

Related Questions