Js mutation observer

Author: g | 2025-04-23

★★★★☆ (4.3 / 832 reviews)

download xactimate free

If a mutation observer is added by some JS is it possible for other JS to detect, remove, replace or change that observer? My concern is that if some JS aims to corrupt some

antietam internet

Mutation Observer in JS - LinkedIn

But transparently wrapped by observable proxies. raw can access the original non-reactive object. Modifying and accessing properties on the raw object doesn't trigger reactions.Using raw at property access console.log(person.name));// this logs 'Bob'person.name = 'Bob';// `name` is used from the raw non-reactive object, this won't log anythingraw(person).name = 'John';">import { observable, observe, raw } from '@nx-js/observer-util';const person = observable();const logger = observe(() => console.log(person.name));// this logs 'Bob'person.name = 'Bob';// `name` is used from the raw non-reactive object, this won't log anythingraw(person).name = 'John';Using raw at property mutation console.log(`${person.name}: ${raw(person).age}`));// this logs 'Bob: 20'person.name = 'Bob';// `age` is used from the raw non-reactive object, this won't log anythingperson.age = 33;">import { observable, observe, raw } from '@nx-js/observer-util';const person = observable({ age: 20 });observe(() => console.log(`${person.name}: ${raw(person).age}`));// this logs 'Bob: 20'person.name = 'Bob';// `age` is used from the raw non-reactive object, this won't log anythingperson.age = 33;Platform supportNode: 6.5 and aboveChrome: 49 and aboveFirefox: 38 and aboveSafari: 10 and aboveEdge: 12 and aboveOpera: 36 and aboveIE is not supportedAlternative buildsThis library detects if you use ES6 or commonJS modules and serve the right format to you. The exposed bundles are transpiled to ES5 to support common tools - like UglifyJS minifying. If you would like a finer control over the provided build, you can specify them in your imports.@nx-js/observer-util/dist/es.es6.js exposes an ES6 build with ES6 modules.@nx-js/observer-util/dist/es.es5.js exposes an ES5 build with ES6 modules.@nx-js/observer-util/dist/cjs.es6.js exposes an ES6 build with commonJS modules.@nx-js/observer-util/dist/cjs.es5.js exposes an ES5 build with commonJS modules.If you use a bundler, set up an alias for @nx-js/observer-util to point to your desired build. You can learn how to do it with webpack here and with rollup here.ContributingContributions are always welcomed! Just send a PR for fixes and doc updates and open issues for new features beforehand. Make sure that the tests and the Exploring DOM Changes: Live Examples with Mutation Observers Watch this space for changes! Add New Element and Change Color // Get the element to observe const targetNode = document.getElementById('target'); // Define configurations for the observer const config = { attributes: true, childList: true, subtree: true, attributeOldValue: true }; // Callback function to execute when mutations are observed const callback = function(mutationsList, observer) { for (const mutation of mutationsList) { const message = document.createElement('p'); if (mutation.type === 'childList') { message.textContent = 'A child node has been added or removed.'; message.style.color = 'green'; } else if (mutation.type === 'attributes') { message.textContent = 'The ' + mutation.attributeName + ' attribute was modified.'; message.style.color = 'blue'; } document.getElementById('log').appendChild(message); } }; // Create an observer instance linked to the callback function const observer = new MutationObserver(callback); // Start observing the target node for configured mutations observer.observe(targetNode, config); // Function to add new elements function addNewElement() { const newElement = document.createElement('div'); newElement.textContent = 'New element added!'; targetNode.appendChild(newElement); } // Function to change attributes function changeAttribute() { const currentColor = targetNode.style.backgroundColor; targetNode.style.backgroundColor = currentColor === 'lightgray' ? 'lightblue' : 'lightgray'; } "> Source Code: (back to article) Result: Report an issue

How (and why) observe DOM in JS with Mutation Observer?

Useful when you are expecting a DOM change.The promise basicsAt the most basic form, a promise needs to know when something is resolved, and when something is rejected. What you’re looking for is the means to a .then() or .catch() method. Those two little guys are your eventualities.Start with your end goal in mindPart of my own personal struggle with understanding promises is that I think I start in the wrong direction. I start from the promise instead of what I want to do. So, if you’re new to promises, and/or curious how we can use them with mutation observers, let’s go ahead and say that this is our end goal:attributePromise(document.querySelector('video'), 'class').then((element)=> { // do something because the video's classname attribute changed}).catch((element)=> { // do something because the video never got a class name change});Begin with the wrapper functionStarting from the back, we know we want to make a function that takes an element and an attribute name as two separate arguments. So we’re looking for something like this:function attributePromise(element,attributeName) { return new Promise((resolve,reject) => { });}Add your MutationObserverWe’ll throw in the observer we’ve already learned about, and its configuration. It just doesn’t quite seem like we’ve reached the finish line yet, though. For one thing, we need to actually loop through the mutation, and see if it’s…mutated.For another, what if it never changes? How do we account for the scenario where the element never changes at all?function attrPromise(element, attributeName) { return new Promise((resolve,reject) => { const observerConfig = {attributes: true,attributeOldValue:true}; const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { // uhhh... stuff will go here? }); }); observer.observe(element, observerConfig); });}Add some timed rejectionWhat we’ll do is make a variable called hasChanged, and we’ll set it to false. Then, we’ll throw a timer that will check every 500ms to see if that hasChanged is true.function attributePromise(element, attributeName) { const rejectTime = 500; return new Promise((resolve,reject) => { let hasChanged = false; const observerConfig = {attributes: true,attributeOldValue:true}; const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { }); }); window.setTimeout(()=>;{ if (!hasChanged) { reject(element); } },rejectTime); observer.observe(element, observerConfig); });}Then, check your mutantsNow we get into into the forEach() loop. What we want to do is compare mutation.attributeName to the attributeName that’s been provided as an argument.If the two match, we’ll do three things:Set hasChanged to true so that our timer can take a breatherDisconnect the observer because we don’t need it any moreResolve the promisefunction attrPromise(element, attributeName) { const rejectTime = 500; return new Promise((resolve,reject) => { let hasChanged = false; const observerConfig = {attributes: true,attributeOldValue:true}; const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.attributeName == attributeName) { hasChanged = true; observer.disconnect(); resolve(element, element.getAttribute(attributeName)); } }); }); window.setTimeout(()=>{ if (!hasChanged) { reject(element); } },rejectTime); observer.observe(element, observerConfig); });}Get off the Happy PathSo far, we’ve written a “happy path” Mutation Promise. Meaning that attributeName will always be an argument that’s been provided, and you’ll always want it to eventually reject. But, let’s go off the happy path by adding. If a mutation observer is added by some JS is it possible for other JS to detect, remove, replace or change that observer? My concern is that if some JS aims to corrupt some

Mutation observer - fa.javascript.info

Like plain JS objects.import { observable } from '@nx-js/observer-util';const counter = observable({ num: 0 });// observables behave like plain JS objectscounter.num = 12;ReactionsReactions are functions, which use observables. They can be created with the observe function and they are automatically executed whenever the observables - used by them - change.Vanilla JavaScript console.log(counter.num));// this calls countLogger and logs 1counter.num++;">import { observable, observe } from '@nx-js/observer-util';const counter = observable({ num: 0 });const countLogger = observe(() => console.log(counter.num));// this calls countLogger and logs 1counter.num++;React Component {counter.num});">import { store, view } from 'react-easy-state';// this is an observable storeconst counter = store({ num: 0, up() { this.num++; }});// this is a reactive component, which re-renders whenever counter.num changesconst UserComp = view(() => div onClick={counter.up}>{counter.num}div>);Preact Component{store.title} }}">import { observer } from "preact-nx-observer";let store = observable({ title: "This is foo's data"});@observer // Component will now re-render whenever store.title changes.class Foo extends Component { render() { return h1>{store.title}h1> }}More examplesDynamic properties console.log(profile.name));// logs 'Bob'profile.name = 'Bob';">import { observable, observe } from '@nx-js/observer-util';const profile = observable();observe(() => console.log(profile.name));// logs 'Bob'profile.name = 'Bob';Nested properties console.log(`${person.name.first} ${person.name.last}`));// logs 'Bob Smith'person.name.first = 'Bob';">import { observable, observe } from '@nx-js/observer-util';const person = observable({ name: { first: 'John', last: 'Smith' }, age: 22});observe(() => console.log(`${person.name.first} ${person.name.last}`));// logs 'Bob Smith'person.name.first = 'Bob';Getter properties console.log(person.name));// logs 'Ann Smith'person.firstName = 'Ann';">import { observable, observe } from '@nx-js/observer-util';const person = observable({ firstName: 'Bob', lastName: 'Smith', get name() { return `${this.firstName} ${this.lastName}`; }});observe(() => console.log(person.name));// logs 'Ann Smith'person.firstName = 'Ann';Conditionals { if (person.gender === 'male') { console.log(`Mr. ${person.name}`); } else { console.log(`Ms. ${person.name}`); }});// logs 'Ms. Potato'person.gender = 'female';">import { observable, observe } from '@nx-js/observer-util';const person = observable({ gender: 'male', name: 'Potato'});observe(() => { if (person.gender === 'male') { console.log(`Mr. ${person.name}`); } else { console.log(`Ms. ${person.name}`); }});// logs 'Ms. Potato'person.gender = 'female';Arrays console.log(users.join(', ')));// logs 'Bob'users.push('Bob');// logs 'Bob, John'users.push('John');// And in my simple little mind, I figured, I don't care. If something changes, just rerun the count to count images.Look at that code and see if you can figure out the issue. If you can, leave me a comment below.So yes, this "worked", but this is what happened:I clicked the button to add a new imageThe mutation observer fired and was like, cool, new shit to do, run renderCountrenderCount got the images and updated the HTML to reflect the new countHey guess what, renderCount changed the DOM tree, let's run the observer againRepeat until the heat death of the universeI had to tweak things a bit, but here's the final version, and I'll explain what I did:class ImgCounter extends HTMLElement { #myObserver; constructor() { super(); } connectedCallback() { // create the div we'll use to monitor images: this.innerHTML += ''; this.renderCount(); const mutationObserver = (mutationList, observer) => { for(const m of mutationList) { if(m.target === this) { this.renderCount(); } } }; this.myObserver = new MutationObserver(mutationObserver); this.myObserver.observe(this, { childList: true, subtree: true }); } disconnectedCallback() { this.myObserver.disconnect(); } renderCount() { let imgs = this.querySelectorAll('img'); this.querySelector('#imgcountertext').innerHTML = `There are ${imgs.length} images in me.`; }}if(!customElements.get('img-counter')) customElements.define('img-counter', ImgCounter);document.querySelector('#testAdd').addEventListener('click', () => { document.querySelector('img-counter').innerHTML = 'New: ' + document.querySelector('img-counter').innerHTML;});I initially had said I didn't care about what was in the list of items changed in the mutation observer, but I noticed that the target value was different when I specifically added my image count report. To help with this, I'm now using a div tag with an ID and renderCount modifies that.When a new image (or anything) is added directly inside the component, my target value is img-counter, or this, which means I can run renderCount on it. When renderCount runs, the target of the mutation is its own div.Also, I noticed that the MutationObserver talks specifically called out the disconnect method as a way of ending the DOM observation. That feels pretty important, and web components make it easy with the disconnectedCallback method.All in all, it works well now (as far as I know ;), and you can test it yourself below: See the Pen Img Counter WC 2 by Raymond Camden (@cfjedimaster) on CodePen.Remember, MutationObserver can absolutely be used outside of web components. Also note that if you only want to respond to an attribute change in a web component, that's really easy as it's baked into the spec. As always, let me

Mutation observer - ar.javascript.info

Logs 'Bob'users.pop();">import { observable, observe } from '@nx-js/observer-util';const users = observable([]);observe(() => console.log(users.join(', ')));// logs 'Bob'users.push('Bob');// logs 'Bob, John'users.push('John');// logs 'Bob'users.pop();ES6 collections { for (let [name, age] of people) { console.log(`${name}, ${age}`); }});// logs 'Bob, 22'people.set('Bob', 22);// logs 'Bob, 22' and 'John, 35'people.set('John', 35);">import { observable, observe } from '@nx-js/observer-util';const people = observable(new Map());observe(() => { for (let [name, age] of people) { console.log(`${name}, ${age}`); }});// logs 'Bob, 22'people.set('Bob', 22);// logs 'Bob, 22' and 'John, 35'people.set('John', 35);Inherited properties console.log(`${user.name} is a ${user.job}`));// logs 'Bob is a developer'user.name = 'Bob';// logs 'Bob is a stylist'user.job = 'stylist';// logs 'Unknown is a stylist'delete user.name;">import { observable, observe } from '@nx-js/observer-util';const defaultUser = observable({ name: 'Unknown', job: 'developer'});const user = observable(Object.create(defaultUser));// logs 'Unknown is a developer'observe(() => console.log(`${user.name} is a ${user.job}`));// logs 'Bob is a developer'user.name = 'Bob';// logs 'Bob is a stylist'user.job = 'stylist';// logs 'Unknown is a stylist'delete user.name;Reaction schedulingReactions are scheduled to run whenever the relevant observable state changes. The default scheduler runs the reactions synchronously, but custom schedulers can be passed to change this behavior. Schedulers are usually functions which receive the scheduled reaction as argument. setTimeout(reaction, 1000);const person = observable({ name: 'Josh' });observe(() => console.log(person.name), { scheduler });// this logs 'Barbie' after a one second delayperson.name = 'Barbie';">import { observable, observe } from '@nx-js/observer-util';// this scheduler delays reactions by 1 secondconst scheduler = reaction => setTimeout(reaction, 1000);const person = observable({ name: 'Josh' });observe(() => console.log(person.name), { scheduler });// this logs 'Barbie' after a one second delayperson.name = 'Barbie';Alternatively schedulers can be objects with an add and delete method. Check out the below examples for more.More examplesReact SchedulerThe React scheduler simply calls setState on relevant observable changes. This delegates the render scheduling to React Fiber. It works roughly like this. this.setState() }); }}">import { observe } from '@nx-js/observer-util';class ReactiveComp

Comparing Mutation Event and Mutation Observer: The Evolution

Moderator: Moderators fifonik Posts: 162 Joined: Fri Dec 02, 2016 3:52 am Location: Brisbane, AU Search for webmon I've implemented search functionality for webmon page.Happy to share the code if someone interested in.Unfortunately, I cannot supply proper PR as do not know how to organise everything correctly for gargoyle.In my case I've just inserted everything in single www/webmon.sh:- One line in html (added input)- A few JS functions at the end of the html in script-sectionP.S. Should I just post it here? Lantis Moderator Posts: 7037 Joined: Mon Jan 05, 2015 5:33 am Location: Australia Re: Search for webmon Post by Lantis » Mon Jul 08, 2024 8:02 am Sure, post it here. If it's all in the html I will probably rework it but that's fine. for the latest releasesPlease be respectful when posting. I do this in my free time on a volunteer basis. fifonik Posts: 162 Joined: Fri Dec 02, 2016 3:52 am Location: Brisbane, AU Re: Search for webmon Post by fifonik » Mon Jul 08, 2024 8:18 am www/webmon.shCode: Select all + ... // to be added at the end of the file before resetData(); function webmonSearch(input, container){ const table = container.getElementsByTagName('table')[0]; if (!table) return; // The 'table-striped' used to highlight odd/even rows using CSS // Unfortunately, this cannot be used if some rows are hidden // So removing the class and later assign odd/even classes directly to the rows table.classList.remove('table-striped'); const tbody = table.getElementsByTagName('tbody')[0]; if (!tbody) return; const s = input.value.trim(); if (s == '') { for (let i = 0, k = tbody.rows.length; i 0) value = value.slice(proto + 3).toUpperCase(); row.dataset.value = value; } if(host.indexOf(S) >= 0 || value.indexOf(S) >= 0){ row.style.display = ''; // 'table-row' can also be used row.className = visibleIndex++ % 2 ? 'even' : 'odd'; } else { row.style.display = 'none'; } } } } function webmonSearchInit(inputId, containerId){ const input = document.getElementById(inputId); if(!input) return; const container = document.getElementById(containerId); if(!container){ // No container for the table exists -- hide filter input input.style.display='none'; return; } // todo@ add debounce input.addEventListener('keyup', evt => webmonSearch(input, container), false); const observer = new MutationObserver((mutationList, observer) => { if(input.value.trim() == '') return; for (const mutation of mutationList) { if (mutation.type === 'childList' && mutation.addedNodes) { // New table added, re-filtering webmonSearch(input, container); break; } } }); observer.observe(container, { childList: true }); } webmonSearchInit('domain_search', 'webmon_domain_table_container'); Lantis Moderator Posts: 7037 Joined: Mon Jan 05, 2015 5:33 am Location:. If a mutation observer is added by some JS is it possible for other JS to detect, remove, replace or change that observer? My concern is that if some JS aims to corrupt some

How to get observed element by a mutation observer

Reading Time: 5 minutesSometimes you may run into a challenging situation: You want some JavaScript to execute, but only if some other element has changed. At work, we’ve recently run into a situation with this kind of challenge. We’re using a library on videos, but how can we make sure that our JavaScript only runs after the video library runs? Well, we do it by mixing two really cool technologies: MutationObserver and Promise.Learning the MutationObserverSo what is a MutationObserver ?It’s an interface that allows you to observe a mutation in the DOM1. It’s a way to find out if elements have changed. We can discover if the element has gotten new attributes, or if it’s had child elements added or removed. So that makes this super handy for those situations when things out of our control are messing with our DOM.First, make an observerlet’s suppose you have a video, and you want to know if that video gets any new attributes added to it. First, we make a new observer.const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { console.log(mutation); // do something! });});A few things to note here:The argument passed in to your new MutationObserver is a callbackYou will need to iterate over the mutations to find the mutations you wantSecond, make a configurationBefore we start observing anything, we need to give some instructions on what to observe. You have a pretty good selection on how to configure your observer. With the exception of attributeFilter, all of these are boolean values, useful for answering questions you may have about the element:childListHave elements been added/removed directly in this element?attributesHas the element had any changes to attributes?characterDataHas any text inside of the element changed?subtreeHave elements more than one level deep changed?attributeOldValueDo you want the original value of the attribute?characterDataOldValueDo you want the original text of the element?attributeFilterWhat specific attributes should be watched?All we want to know is if a class name is changing. Easy enough!const observerConfig = { attributes: true, attributeOldValue: true};Next step: start observingWe’ve created the observer. We’ve created a configuration for it. Now, we just want to put it to useobserver.observe( document.querySelector('.myVideo'), observerConfig);We use the observe method, and pass in two arguments:Element to observeConfiguration to useBut it feels kinda weirdIf you’re thinking, “neat, but it feels weird,” you’re not alone. My long experience with JavaScript in the DOM tells me I should be able to do something like this:document .querySelector('.video') .addEventListener('mutation',mutationCallback)But, how would we be able to decide which mutations to watch (i.e. pass in a configuration)?¯_(ツ)_/¯Maybe that’s why it’s not an event to listen to on an element.And then the promiseSimply put, a promise is an object that may produce a single value at some time in the future2. I like to think of promises as an eventuality. Eventualities are events that will happen, but you don’t have the details of what happens. So a promise is a way to make sure that something always happens. This makes promises exceptionally helpful for AJAX. But it also makes them

Comments

User7305

But transparently wrapped by observable proxies. raw can access the original non-reactive object. Modifying and accessing properties on the raw object doesn't trigger reactions.Using raw at property access console.log(person.name));// this logs 'Bob'person.name = 'Bob';// `name` is used from the raw non-reactive object, this won't log anythingraw(person).name = 'John';">import { observable, observe, raw } from '@nx-js/observer-util';const person = observable();const logger = observe(() => console.log(person.name));// this logs 'Bob'person.name = 'Bob';// `name` is used from the raw non-reactive object, this won't log anythingraw(person).name = 'John';Using raw at property mutation console.log(`${person.name}: ${raw(person).age}`));// this logs 'Bob: 20'person.name = 'Bob';// `age` is used from the raw non-reactive object, this won't log anythingperson.age = 33;">import { observable, observe, raw } from '@nx-js/observer-util';const person = observable({ age: 20 });observe(() => console.log(`${person.name}: ${raw(person).age}`));// this logs 'Bob: 20'person.name = 'Bob';// `age` is used from the raw non-reactive object, this won't log anythingperson.age = 33;Platform supportNode: 6.5 and aboveChrome: 49 and aboveFirefox: 38 and aboveSafari: 10 and aboveEdge: 12 and aboveOpera: 36 and aboveIE is not supportedAlternative buildsThis library detects if you use ES6 or commonJS modules and serve the right format to you. The exposed bundles are transpiled to ES5 to support common tools - like UglifyJS minifying. If you would like a finer control over the provided build, you can specify them in your imports.@nx-js/observer-util/dist/es.es6.js exposes an ES6 build with ES6 modules.@nx-js/observer-util/dist/es.es5.js exposes an ES5 build with ES6 modules.@nx-js/observer-util/dist/cjs.es6.js exposes an ES6 build with commonJS modules.@nx-js/observer-util/dist/cjs.es5.js exposes an ES5 build with commonJS modules.If you use a bundler, set up an alias for @nx-js/observer-util to point to your desired build. You can learn how to do it with webpack here and with rollup here.ContributingContributions are always welcomed! Just send a PR for fixes and doc updates and open issues for new features beforehand. Make sure that the tests and the

2025-03-28
User5789

Exploring DOM Changes: Live Examples with Mutation Observers Watch this space for changes! Add New Element and Change Color // Get the element to observe const targetNode = document.getElementById('target'); // Define configurations for the observer const config = { attributes: true, childList: true, subtree: true, attributeOldValue: true }; // Callback function to execute when mutations are observed const callback = function(mutationsList, observer) { for (const mutation of mutationsList) { const message = document.createElement('p'); if (mutation.type === 'childList') { message.textContent = 'A child node has been added or removed.'; message.style.color = 'green'; } else if (mutation.type === 'attributes') { message.textContent = 'The ' + mutation.attributeName + ' attribute was modified.'; message.style.color = 'blue'; } document.getElementById('log').appendChild(message); } }; // Create an observer instance linked to the callback function const observer = new MutationObserver(callback); // Start observing the target node for configured mutations observer.observe(targetNode, config); // Function to add new elements function addNewElement() { const newElement = document.createElement('div'); newElement.textContent = 'New element added!'; targetNode.appendChild(newElement); } // Function to change attributes function changeAttribute() { const currentColor = targetNode.style.backgroundColor; targetNode.style.backgroundColor = currentColor === 'lightgray' ? 'lightblue' : 'lightgray'; } "> Source Code: (back to article) Result: Report an issue

2025-04-21
User1522

Useful when you are expecting a DOM change.The promise basicsAt the most basic form, a promise needs to know when something is resolved, and when something is rejected. What you’re looking for is the means to a .then() or .catch() method. Those two little guys are your eventualities.Start with your end goal in mindPart of my own personal struggle with understanding promises is that I think I start in the wrong direction. I start from the promise instead of what I want to do. So, if you’re new to promises, and/or curious how we can use them with mutation observers, let’s go ahead and say that this is our end goal:attributePromise(document.querySelector('video'), 'class').then((element)=> { // do something because the video's classname attribute changed}).catch((element)=> { // do something because the video never got a class name change});Begin with the wrapper functionStarting from the back, we know we want to make a function that takes an element and an attribute name as two separate arguments. So we’re looking for something like this:function attributePromise(element,attributeName) { return new Promise((resolve,reject) => { });}Add your MutationObserverWe’ll throw in the observer we’ve already learned about, and its configuration. It just doesn’t quite seem like we’ve reached the finish line yet, though. For one thing, we need to actually loop through the mutation, and see if it’s…mutated.For another, what if it never changes? How do we account for the scenario where the element never changes at all?function attrPromise(element, attributeName) { return new Promise((resolve,reject) => { const observerConfig = {attributes: true,attributeOldValue:true}; const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { // uhhh... stuff will go here? }); }); observer.observe(element, observerConfig); });}Add some timed rejectionWhat we’ll do is make a variable called hasChanged, and we’ll set it to false. Then, we’ll throw a timer that will check every 500ms to see if that hasChanged is true.function attributePromise(element, attributeName) { const rejectTime = 500; return new Promise((resolve,reject) => { let hasChanged = false; const observerConfig = {attributes: true,attributeOldValue:true}; const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { }); }); window.setTimeout(()=>;{ if (!hasChanged) { reject(element); } },rejectTime); observer.observe(element, observerConfig); });}Then, check your mutantsNow we get into into the forEach() loop. What we want to do is compare mutation.attributeName to the attributeName that’s been provided as an argument.If the two match, we’ll do three things:Set hasChanged to true so that our timer can take a breatherDisconnect the observer because we don’t need it any moreResolve the promisefunction attrPromise(element, attributeName) { const rejectTime = 500; return new Promise((resolve,reject) => { let hasChanged = false; const observerConfig = {attributes: true,attributeOldValue:true}; const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.attributeName == attributeName) { hasChanged = true; observer.disconnect(); resolve(element, element.getAttribute(attributeName)); } }); }); window.setTimeout(()=>{ if (!hasChanged) { reject(element); } },rejectTime); observer.observe(element, observerConfig); });}Get off the Happy PathSo far, we’ve written a “happy path” Mutation Promise. Meaning that attributeName will always be an argument that’s been provided, and you’ll always want it to eventually reject. But, let’s go off the happy path by adding

2025-03-29
User8823

Like plain JS objects.import { observable } from '@nx-js/observer-util';const counter = observable({ num: 0 });// observables behave like plain JS objectscounter.num = 12;ReactionsReactions are functions, which use observables. They can be created with the observe function and they are automatically executed whenever the observables - used by them - change.Vanilla JavaScript console.log(counter.num));// this calls countLogger and logs 1counter.num++;">import { observable, observe } from '@nx-js/observer-util';const counter = observable({ num: 0 });const countLogger = observe(() => console.log(counter.num));// this calls countLogger and logs 1counter.num++;React Component {counter.num});">import { store, view } from 'react-easy-state';// this is an observable storeconst counter = store({ num: 0, up() { this.num++; }});// this is a reactive component, which re-renders whenever counter.num changesconst UserComp = view(() => div onClick={counter.up}>{counter.num}div>);Preact Component{store.title} }}">import { observer } from "preact-nx-observer";let store = observable({ title: "This is foo's data"});@observer // Component will now re-render whenever store.title changes.class Foo extends Component { render() { return h1>{store.title}h1> }}More examplesDynamic properties console.log(profile.name));// logs 'Bob'profile.name = 'Bob';">import { observable, observe } from '@nx-js/observer-util';const profile = observable();observe(() => console.log(profile.name));// logs 'Bob'profile.name = 'Bob';Nested properties console.log(`${person.name.first} ${person.name.last}`));// logs 'Bob Smith'person.name.first = 'Bob';">import { observable, observe } from '@nx-js/observer-util';const person = observable({ name: { first: 'John', last: 'Smith' }, age: 22});observe(() => console.log(`${person.name.first} ${person.name.last}`));// logs 'Bob Smith'person.name.first = 'Bob';Getter properties console.log(person.name));// logs 'Ann Smith'person.firstName = 'Ann';">import { observable, observe } from '@nx-js/observer-util';const person = observable({ firstName: 'Bob', lastName: 'Smith', get name() { return `${this.firstName} ${this.lastName}`; }});observe(() => console.log(person.name));// logs 'Ann Smith'person.firstName = 'Ann';Conditionals { if (person.gender === 'male') { console.log(`Mr. ${person.name}`); } else { console.log(`Ms. ${person.name}`); }});// logs 'Ms. Potato'person.gender = 'female';">import { observable, observe } from '@nx-js/observer-util';const person = observable({ gender: 'male', name: 'Potato'});observe(() => { if (person.gender === 'male') { console.log(`Mr. ${person.name}`); } else { console.log(`Ms. ${person.name}`); }});// logs 'Ms. Potato'person.gender = 'female';Arrays console.log(users.join(', ')));// logs 'Bob'users.push('Bob');// logs 'Bob, John'users.push('John');//

2025-04-23

Add Comment