40

Is it possible to observer mutations on a DOM node that doesn't exist yet?

Example:

My app creates a div at some point: <div id="message" data-message-content="foo" data-message-type="bar" />.

I want to watch for the creation & change of this div.

var mutationObserver = new MutationObserver(function(mutations){ // Some code to handle the mutation. }); mutationObserver.observe( document.querySelector('#message'), { attributes: true, subtree: true, childList: true, characterData: false } ); ); 

Right now this returns an error since #message is null (the div hasn't been created yet).

Failed to execute 'observe' on 'MutationObserver': parameter 1 is not of type 'Node'.

An obvious solution is to watch the body and check if any of the mutations are the creation of div#Message, but this seems like a bad idea / or possibly bad for performance.

4
  • How are you creating the element? Can't you add this in the same method that creates it so it is actually created then? Commented Aug 10, 2016 at 18:51
  • Unfortunately no - this is for a Google Chrome plugin. Plugins have a few annoying scope restrictions. Basically this observer exists in an entirely different scope than the window / functions that create the div. Commented Aug 10, 2016 at 18:54
  • 1
    The obvious solution is the only one, unless the site emits some kind of event prior to adding that node. Commented Aug 10, 2016 at 19:02
  • Refer this answer how I fixed it stackoverflow.com/questions/61212681/… Commented Apr 15, 2020 at 11:50

1 Answer 1

110

Only an existing node can be observed.

You can use document.getElementById() in MutationObserver callback, it's super fast compared to enumeration of all mutated nodes (see also Performance of MutationObserver).

function waitForAddedNode(params, callback) { new MutationObserver(mutations => { var el = document.getElementById(params.id); if (el) { this.disconnect(); callback(el); } }).observe(params.parent || document, { subtree: !!params.recursive || !params.parent, childList: true, }); } 

Usage:

waitForAddedNode({ id: 'message', //parent: document.querySelector('.container'), recursive: true, }, el => { console.log(el); }); 
Sign up to request clarification or add additional context in comments.

1 Comment

An ingenious approach as you're not relying on the mutations properties (where I have had difficulty) but just checking the required element exists each time. A bit like polling with a timeout. Relies on element having an id though...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.