# Feature request: ValueTree::setPropertyExcludingAllListeners()

**URL:** <https://forum.juce.com/t/feature-request-valuetree-setpropertyexcludingalllisteners/41263>\
**Category:** Feature Requests\
**Created:** [August 17, 2020, 11:06am UTC](https://forum.juce.com/t/feature-request-valuetree-setpropertyexcludingalllisteners/41263 "2020-08-17T11:06:00Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![jamiebullock](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/jamiebullock/32/459_2.png) [@jamiebullock](https://forum.juce.com/u/jamiebullock)\
**Post date:** [August 17, 2020, 11:06am UTC](https://forum.juce.com/t/feature-request-valuetree-setpropertyexcludingalllisteners/41263/1 "2020-08-17T11:06:00Z")

</div>

`ValueTree` has a very useful method `setPropertyExcludingListener()` which enables a specific listener to be excluded from update notifications.

However, sometimes we want to set a piece of state and have none of the listeners notified. It would therefore be useful to either be able to exclude all listeners, or pass in a list of listeners to be excluded.

---

<div class="post-metadata">

**Author:** ![refusesoftware](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/refusesoftware/32/20561_2.png) [@refusesoftware](https://forum.juce.com/u/refusesoftware)\
**Post date:** [August 18, 2020, 10:57pm UTC](https://forum.juce.com/t/feature-request-valuetree-setpropertyexcludingalllisteners/41263/2 "2020-08-18T22:57:24Z")

</div>

Yes, I would argue that `ValueTree::setPropertyExcludingAllListeners()` would be good for modularity/encapsulation, as one object doesn’t necessarily know all the other Listeners that have been added to a ValueTree.

---

<div class="post-metadata">

**Author:** ![refusesoftware](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/refusesoftware/32/20561_2.png) [@refusesoftware](https://forum.juce.com/u/refusesoftware)\
**Post date:** [August 18, 2020, 11:01pm UTC](https://forum.juce.com/t/feature-request-valuetree-setpropertyexcludingalllisteners/41263/3 "2020-08-18T23:01:55Z")

</div>

And, sorry to piggyback on this FR, but while changes were being made, would it be possible to have these as well?

`ValueTree::addChildExcludingAllListeners()`  
`ValueTree::removeChildExcludingAllListeners()`

---

<div class="post-metadata">

**Author:** ![nfect](https://avatars.discourse-cdn.com/v4/letter/n/a6a055/32.png) [@nfect](https://forum.juce.com/u/nfect)\
**Post date:** [July 1, 2021, 7:22pm UTC](https://forum.juce.com/t/feature-request-valuetree-setpropertyexcludingalllisteners/41263/4 "2021-07-01T19:22:56Z")

</div>

yeah, excluding a listener or a list of listeners, or even all listeners with addchild and set property would make my days SOOOO much better.

---

<div class="post-metadata">

**Author:** ![ImJimmi](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/imjimmi/32/10843_2.png) [@ImJimmi](https://forum.juce.com/u/ImJimmi)\
**Post date:** [July 1, 2021, 11:48pm UTC](https://forum.juce.com/t/feature-request-valuetree-setpropertyexcludingalllisteners/41263/5 "2021-07-01T23:48:42Z")

</div>

Can someone explain a good use case for this?

Personally, I don’t think it makes sense to provide a listener mechanism where one object can prevent other listeners from receiving the callbacks they’re expecting, especially when those objects don’t necessarily know about each other.

How would that look as an API? “Hey you can register as a listener to this object and _sometimes_ be notified about changes but also sometimes not, kinda depends whether these other guys want you to be notified. Oh no sorry, I can’t tell you who stopped you getting these callbacks, that’s a secret.”

The intent of the existing `excludingListener` method is to allow an object that listens to a tree to set a property on the tree without being notified of the change itself - otherwise you can get stuck in infinite loops. The suggestion to add a method to allow for multiple listeners to be excluded is not so bad because the caller will at least _know_ what objects it’s blocking, however a method to exclude all listeners completely defeats the purpose of the listener/observer pattern.

---

<div class="post-metadata">

**Author:** ![ImJimmi](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/imjimmi/32/10843_2.png) [@ImJimmi](https://forum.juce.com/u/ImJimmi)\
**Post date:** [July 1, 2021, 11:52pm UTC](https://forum.juce.com/t/feature-request-valuetree-setpropertyexcludingalllisteners/41263/6 "2021-07-01T23:52:29Z")

</div>

Seems that really what you’d want to do is take a _deep_ copy of the tree being modified, set the new property on that, then you can copy it back to the original tree when you’re ready.

You could wrap that up in a free function, then your listener mechanism still works as intended and everybody’s happy.

---

<div class="post-metadata">

**Author:** ![nfect](https://avatars.discourse-cdn.com/v4/letter/n/a6a055/32.png) [@nfect](https://forum.juce.com/u/nfect)\
**Post date:** [October 23, 2022, 12:15am UTC](https://forum.juce.com/t/feature-request-valuetree-setpropertyexcludingalllisteners/41263/7 "2022-10-23T00:15:23Z")

</div>

I’m not sure, but I believe you can set a property without notifying listeners by accessing the tree property [“”] tree[identifier] = newvalue. And there is a ton of use case where you don’t want to notify at all. As example, imagine you have an object that is costly to update, and you know that this object always requires many properties to update, instead of updating at each value tree change received, you can make it update when you want. I don’t think that getting that little bit more of control is a bad thing.

---

<div class="post-metadata">

**Author:** ![ImJimmi](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/imjimmi/32/10843_2.png) [@ImJimmi](https://forum.juce.com/u/ImJimmi)\
**Post date:** [October 23, 2022, 12:29pm UTC](https://forum.juce.com/t/feature-request-valuetree-setpropertyexcludingalllisteners/41263/8 "2022-10-23T12:29:27Z")

</div>

> [@nfect](#):
>
> As example, imagine you have an object that is costly to update, and you know that this object always requires many properties to update, instead of updating at each value tree change received, you can make it update when you want.

That doesn’t sound like good architecture to me - sounds like those objects are too tightly coupled.

The costly object should either decide for itself when’s best to respond to the value changes, or you should use some sort of events system so the object writing the properties can send an alert when it’s finished. Or maybe you can split up the costly object into multiple units each handling a single property to avoid repeatedly doing one big, costly operation when any of the properties changes.

---

<div class="post-metadata">

**Author:** ![oxxyyd](https://avatars.discourse-cdn.com/v4/letter/o/e47c2d/32.png) [@oxxyyd](https://forum.juce.com/u/oxxyyd)\
**Post date:** [October 23, 2022, 7:14pm UTC](https://forum.juce.com/t/feature-request-valuetree-setpropertyexcludingalllisteners/41263/9 "2022-10-23T19:14:34Z")

</div>

I’d say that this is the perfect use case for the AsyncUpdater.

Let your object that’s costly to update inherit from AsyncUpdater (as well as being a ValuetreeListener). Then when the valueTreePropertyChanged callback is triggered by changes in your objects parameters, you do a call to AsyncUpdater::triggerAsyncUpdate(). These triggerAsyncUpdate:s will be coalesced into one single call to AsyncUpdater::handleAsyncUpdate() in which you do your costly update.

Meaning, regardless if you update one or ten properties of the costly object (at the same time and place in the code, that is) it will only trigger one costly update. And the undomanagement will work too…

---

<div class="post-metadata">

**Author:** ![nfect](https://avatars.discourse-cdn.com/v4/letter/n/a6a055/32.png) [@nfect](https://forum.juce.com/u/nfect)\
**Post date:** [October 23, 2022, 7:57pm UTC](https://forum.juce.com/t/feature-request-valuetree-setpropertyexcludingalllisteners/41263/10 "2022-10-23T19:57:16Z")

</div>

> [@ImJimmi](#):
>
> The costly object should either decide for itself when’s best to respond to the value changes, or you should use some sort of events system so the object writing the properties can send an alert when it’s finished.

sounds about right

> [@oxxyyd](#):
>
> And the undomanagement will work too…

🙌

---

<div class="post-metadata">

**Author:** ![oxxyyd](https://avatars.discourse-cdn.com/v4/letter/o/e47c2d/32.png) [@oxxyyd](https://forum.juce.com/u/oxxyyd)\
**Post date:** [October 23, 2022, 8:05pm UTC](https://forum.juce.com/t/feature-request-valuetree-setpropertyexcludingalllisteners/41263/11 "2022-10-23T20:05:57Z")

</div>

Maybe a small example to lighten things up…

```auto
#include "JuceHeader.h"

#define IDENTIFIER(a) const Identifier a(#a);

namespace ID
{
	IDENTIFIER(bw)
	IDENTIFIER(qFactor)
	IDENTIFIER(speed)
	IDENTIFIER(feedback)
	IDENTIFIER(gain)
	IDENTIFIER(freq)
	IDENTIFIER(complexObject)
}

UndoManager undomanager;

class ComplexObject : public AsyncUpdater, ValueTree::Listener
{
public:
	ComplexObject()
	: valueTree(ID::complexObject)
	, bandWidth(valueTree, ID::bw, &undomanager, 100.0f)
	, qFactor(valueTree, ID::qFactor, &undomanager, 0.5f)
	, gain(valueTree, ID::gain, &undomanager, 1.0f)
	, speed(valueTree, ID::speed, &undomanager, 10.0f)
	, freq(valueTree, ID::freq, &undomanager, 1000.0f)
	, feedback(valueTree, ID::feedback, &undomanager, 0.25f)
	// etc...
	{
		valueTree.addListener(this);
	}

	void handleAsyncUpdate() override
	{
		//do costly complex updates to the complex object 
	}

	void valueTreePropertyChanged(ValueTree& valueTree, const Identifier& property) override
	{
		if (valueTree.getType() == ID::complexObject)
			triggerAsyncUpdate();	//all these calls will coalesce into one call of handleAsyncUpdate
	}

	void doSomeFunnyUpdates()
	{
		/*do updates to one, a few or all parameters => will trigger only one call to 
		* handleAsyncUpdate() i.e rebuild of the complex object
		* */

		undomanager.beginNewTransaction("Changed the complex object");

		bandWidth = Random::getSystemRandom().nextFloat();
		qFactor = Random::getSystemRandom().nextFloat();
		speed = Random::getSystemRandom().nextFloat();
		//... optionally fill up w/ more
	}

private:

	ValueTree valueTree;

	CachedValue<float> bandWidth;
	CachedValue<float> qFactor;
	CachedValue<float> gain;
	CachedValue<float> speed;
	CachedValue<float> freq;
	CachedValue<float> feedback;
	//etc

};

#undef IDENTIFIER

```
