Como forçar programaticamente um evento onchange em uma entrada?

123

Como forçar programaticamente um evento onchange em uma entrada?

Eu tentei algo como isto:

var code = ele.getAttribute('onchange');
eval(code);

Mas meu objetivo final é acionar qualquer função de ouvinte, e isso não parece funcionar. Também não atualiza apenas o atributo 'value'.

Soldarnal
fonte

Respostas:

142

Crie um Eventobjeto e passe-o para o dispatchEventmétodo do elemento:

var element = document.getElementById('just_an_example');
var event = new Event('change');
element.dispatchEvent(event);

Isso acionará ouvintes de eventos, independentemente de terem sido registrados chamando o addEventListenermétodo ou configurando a onchangepropriedade do elemento.


Se você deseja que o evento borbulhe, é necessário passar um segundo argumento para o Eventconstrutor:

var event = new Event('change', { bubbles: true });

Informações sobre a compatibilidade do navegador:

Miscreant
fonte
2
Sim, o MDN Criando e acionando eventos é um bom recurso!
Jakub Holý
1
É assim que se faz corretamente, de forma nativa. Agora com suporte em todos os navegadores: caniuse.com/#feat=dispatchevent
Willem Mulder
1
Esta é uma resposta verdadeira para esta pergunta. Temos que conseguir isso de uma maneira moderna.
Константин Ван
1
Estou tentando fazer o equivalente no IE11, mas não está funcionando ao tentar alterar um campo de entrada reactjs. var evt = document.createEvent('CustomEvent'); evt.initCustomEvent('input', true, false, { }); elem.dispatchEvent(evt);
Bodosko
3
Por que todo mundo está dizendo que esta é a melhor resposta? De acordo com o documento do evento vinculado, mesmo a versão atual do IE ainda não suporta isso.
precisa
96

No jQuery eu uso principalmente:

$("#element").trigger("change");
Danita
fonte
2
você me ajudou! Eu estava definindo o valor de uma caixa de seleção (marcada ou não) usando código e o evento não foi disparado no IE, não importa o que eu fiz. Tentei blur () focus () e algumas outras coisas. depois de definir o valor, chamei o trigger e adicionei um evento click para chamar o trigger também. Isso causa vários incêndios, mas isso não importa para mim. No IE, adiciono caixas de seleção através do código e você deve clicar nelas duas vezes antes que o evento de alteração seja acionado. Obrigado por esta dica.
Dustin Davis
6
Como uma atualização, $ ("# element"). Change (); faz a mesma coisa desde o jquery 1.0.
CookieOfFortune 23/07
3
Observe que isso NÃO aciona uma troca nativa. Ele será acionado apenas em todos os ouvintes de troca que foram vinculados pelo jQuery!
Willem Mulder
Alguma ajuda aqui por favor? Nenhum destes solução parece trabalhar para mim .. stackoverflow.com/questions/51216332/...
Gabe
61

ugh não use eval para nada . Bem, existem certas coisas, mas são extremamente raras. Em vez disso, você faria o seguinte:

document.getElementById("test").onchange()

Procure aqui mais opções: http://jehiah.cz/archive/firing-javascript-events-properly

Kolten
fonte
3
eval para objetivando JSON;)
Aaron Powell
3
json2.js para objetivar o JSON! JSON.parse já está disponível em navegadores modernos
jinglesthula
12
Essa técnica funciona apenas se o manipulador de alterações foi anexado pela configuração "onchange". Ele não gera um evento 'real' que aciona manipuladores de eventos w3c ou microsoft. Veja o link para mais detalhes.
Stephen Nelson
6
Acho que esta resposta está desatualizada agora, a resposta de Miscreant está usando new Event(...)e dispatchEventé a solução certa hoje em dia, ao que parece.
Jakub Holý
4
Esta resposta está obsoleta ; o código acima não funcionará se você costumava Element.addEventListenermanipular eventos. Para alcançá-lo de uma maneira moderna, consulte a resposta de @ Miscreant.
Константин Ван
23

Por alguma razão, ele.onchange () está lançando uma exceção de "método não encontrado" para mim no IE na minha página, então acabei usando essa função no link fornecido por Kolten e chamando fireEvent (ele, 'change'), que funcionava :

function fireEvent(element,event){
    if (document.createEventObject){
        // dispatch for IE
        var evt = document.createEventObject();
        return element.fireEvent('on'+event,evt)
    }
    else{
        // dispatch for firefox + others
        var evt = document.createEvent("HTMLEvents");
        evt.initEvent(event, true, true ); // event type,bubbling,cancelable
        return !element.dispatchEvent(evt);
    }
}

No entanto, criei uma página de teste que confirmou que a chamada deveria onchange () funcionar:

<input id="test1" name="test1" value="Hello" onchange="alert(this.value);"/>
<input type="button" onclick="document.getElementById('test1').onchange();" value="Say Hello"/>

Edit: A razão pela qual ele.onchange () não funcionou foi porque eu realmente não havia declarado nada para o evento onchange. Mas o fireEvent ainda funciona.

Soldarnal
fonte
2
Eu gosto desse método de detecção de navegador (por detecção de objeto) melhor do que o exemplo que forneci.
Chris MacDonald
Isso não funciona mais para o Firefox 23: "element.dispatchEvent não é uma função"
Oliver
4
Olá, colegas googlers. É 2016! Hoje em dia nós escrever código como element.dispatchEvent(new Event('change', true, true))em vez de tudo o que arcanos e principalmente obsoleta createEvente initEventmaterial.
Ericsoco 28/05
3

Esta é a resposta mais correta para o IE e o Chrome:

javascript=>

var element = document.getElementById('xxxx');
var evt = document.createEvent('HTMLEvents');
evt.initEvent('change', false, true);
element.dispatchEvent(evt);
Peter Lo
fonte
2

Retirado da parte inferior do QUnit

function triggerEvent( elem, type, event ) {
    if ( $.browser.mozilla || $.browser.opera ) {
        event = document.createEvent("MouseEvents");
        event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,
            0, 0, 0, 0, 0, false, false, false, false, 0, null);
        elem.dispatchEvent( event );
    } else if ( $.browser.msie ) {
        elem.fireEvent("on"+type);
    }
}

É claro que você pode substituir o material $ .browser pelos seus próprios métodos de detecção do navegador para torná-lo independente do jQuery.

Para usar esta função:

var event;
triggerEvent(ele, "change", event);

Isso basicamente dispara o evento DOM real como se algo tivesse realmente mudado.

Chris MacDonald
fonte
1

Se você adicionar todos os seus eventos com este trecho de código:

//put this somewhere in your JavaScript:
HTMLElement.prototype.addEvent = function(event, callback){
  if(!this.events)this.events = {};
  if(!this.events[event]){
    this.events[event] = [];
    var element = this;
    this['on'+event] = function(e){
      var events = element.events[event];
      for(var i=0;i<events.length;i++){
        events[i](e||event);
      }
    }
  }
  this.events[event].push(callback);
}
//use like this:
element.addEvent('change', function(e){...});

então você pode simplesmente usar element.on<EVENTNAME>()onde <EVENTNAME>está o nome do seu evento e chamará todos os eventos com<EVENTNAME>

Wntiv Senyh
fonte
-2

Para acionar qualquer evento em Javascript.

 document.getElementById("yourid").addEventListener("change", function({
    //your code here
})
Hareesh Seela
fonte
2
isso é ouvir eventos, não ativá-los.
invalidusername
-4

se você estiver usando jQuery, você teria:

$('#elementId').change(function() { alert('Do Stuff'); });

ou MS AJAX:

$addHandler($get('elementId'), 'change', function(){ alert('Do Stuff'); });

Ou no HTML bruto do elemento:

<input type="text" onchange="alert('Do Stuff');" id="myElement" />

Depois de reler a pergunta, acho que não li o que deveria ser feito. Nunca encontrei uma maneira de atualizar um elemento DOM de maneira a forçar um evento de mudança. O melhor é fazer um método de manipulador de eventos separado, como este:

$addHandler($get('elementId'), 'change', elementChanged);
function elementChanged(){
  alert('Do Stuff!');
}
function editElement(){
  var el = $get('elementId');
  el.value = 'something new';
  elementChanged();
}

Como você já está escrevendo um método JavaScript que fará a alteração, são necessárias apenas 1 linha adicional.

Ou, se você estiver usando a estrutura Microsoft AJAX, poderá acessar todos os manipuladores de eventos através de:

$get('elementId')._events

Isso permitiria que você fizesse algumas ações no estilo de reflexão para encontrar os manipuladores de eventos certos a serem disparados.

Aaron Powell
fonte
1
Eu acredito que ele quer disparar o evento real, não executar uma função quando o evento é disparado ... eu acho . lol
Kolten 25/09/08
-5

Usando o JQuery, você pode fazer o seguinte:

// for the element which uses ID
$("#id").trigger("change");

// for the element which uses class name
$(".class_name").trigger("change");
STEEL ITBOY
fonte
indefinido não é uma função.
Hristo Venev