# Conditional suspension of Bindings

**URL:** <https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766>\
**Category:** Help Requests\
**Created:** [September 9, 2020, 9:28pm UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766 "2020-09-09T21:28:14Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Devron](https://avatars.discourse-cdn.com/v4/letter/d/ec9cab/32.png) [@Devron](https://discourse.aurelia.io/u/Devron)\
**Post date:** [September 9, 2020, 9:28pm UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/1 "2020-09-09T21:28:14Z")

</div>

Hi, I have written and app for a small portable devices (watch) that requires very low background CPU and processing usage. I’ve been trying to optimise this and using the browser debug timeline I can see that the Aurelia binding engine is calling all subscribers every seconds or so when the screen is off as I think the browser is throttling the timers. Under predefined scenarios like document.visibility = “hidden” I want to suspend the binding engine, or at least throttle the binding engine/subscriptions to update every x seconds. Obviously I only want the last change to be called when the screen comes on. I’ve played around with throttling the flushTaskQueue and flushMicroTaskQueue (just a hack test) but this does not seem to be the way to go. Can anyone point me to a way of achieving this? could it be done with a plugin? Even some pointers on where I should look to inject some code as flushQueues does not seem to be the way forward here.

Oh, and i don’t want to add throttle/denounce to all bindings as it needs to be dynamic. Unless there is a way I can dynamically apply a throttle to all my bindings in code maybe…?

Cheers

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [September 9, 2020, 11:39pm UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/2 "2020-09-09T23:39:07Z")

</div>

By default, changes are only notified when there’s something that … has been changed. I guess there’s something in the app that triggers dirty checking, causing it to be constantly firing. Maybe have a check? Normally it can comes from either:

- `getter` without `@computedFrom`
- binding to an element property that Aurelia doesn’t know how to observe

You can also use this plugin [https://github.com/jdanyow/aurelia-computed](https://github.com/jdanyow/aurelia-computed) to automatically handle your computed property. Though I’d say it’s still better that you check it carefully.

---

<div class="post-metadata">

**Author:** ![Devron](https://avatars.discourse-cdn.com/v4/letter/d/ec9cab/32.png) [@Devron](https://discourse.aurelia.io/u/Devron)\
**Post date:** [September 10, 2020, 7:19am UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/3 "2020-09-10T07:19:15Z")

</div>

There’s no dirty checking at all, I’ve made sure of this. And I am using @computedFrom appropriately. The problem is that the @computedFrom properties are being updated when the screen is off, and hence the binding in the dom. I don’t want the dom updates to run when the screen is off, and only the last property update to be applied when the screen comes on again.

Make sense?

---

<div class="post-metadata">

**Author:** ![Devron](https://avatars.discourse-cdn.com/v4/letter/d/ec9cab/32.png) [@Devron](https://discourse.aurelia.io/u/Devron)\
**Post date:** [September 10, 2020, 7:20am UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/4 "2020-09-10T07:20:33Z")

</div>

I get I could add a @computedFrom(‘signalSwicth’) and flip the switch only when I want updates to occur, but I’m looking for a way to do this globally.

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [September 10, 2020, 9:55am UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/5 "2020-09-10T09:55:13Z")

</div>

> [@Devron](#):
>
> The problem is that the @computedFrom properties are being updated when the screen is off

This is the part where it doesn’t make sense. Computed properties are constantly read whenever there’s something that constantly needs to read it. And if you’ve made sure that all getters are decorated with `@computedFrom`, then I think there’s some `setInterval` floating somewhere in your app, or the plugins that your app uses.

Can you put a breakpoint inside those getters, and see what’s calling it?

---

<div class="post-metadata">

**Author:** ![Devron](https://avatars.discourse-cdn.com/v4/letter/d/ec9cab/32.png) [@Devron](https://discourse.aurelia.io/u/Devron)\
**Post date:** [September 10, 2020, 10:08am UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/6 "2020-09-10T10:08:20Z")

</div>

Ok, maybe I’m not explaining properly. I’ll try again. I have a background task that updates my model properties every 1 second. I also have a view bound to this model. So when the background task updates the model properties, Aurelia then updates the view where I’ve bound to these properties. I will continue to run my background task and update the model every 1 second, but I want to tell Aurelia to suspend all updates of the view and not reflect the model changes when the screen is off, or if say xx seconds elapsed since last update. I hope this makes sense?

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [September 10, 2020, 10:19am UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/7 "2020-09-10T10:19:01Z")

</div>

So, to be clear, you want to keep the model updates going, but changes that are supposed to go to view will be “suspended”?

---

<div class="post-metadata">

**Author:** ![Devron](https://avatars.discourse-cdn.com/v4/letter/d/ec9cab/32.png) [@Devron](https://discourse.aurelia.io/u/Devron)\
**Post date:** [September 10, 2020, 10:19am UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/8 "2020-09-10T10:19:57Z")

</div>

Correct, conditionally suspended.

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [September 10, 2020, 10:22am UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/9 "2020-09-10T10:22:16Z")

</div>

If we have this template

```auto
<input value.bind="someProp">
<some-el value.two-way="someProp">
<some-el value.to-view="someProp">

```

There’ 3 types of flow here, despite all are in the “view”:  
view model \<-\> view (`<input/>`)  
view model \<-\> model (`<some-el/>`)  
view model -\> view model (one way with `<some-el/>`)

What will happen to the 2nd & 3rd one? Note that if it’s 2 way binding, suspended flow in one way may also stop the other.

---

<div class="post-metadata">

**Author:** ![Devron](https://avatars.discourse-cdn.com/v4/letter/d/ec9cab/32.png) [@Devron](https://discourse.aurelia.io/u/Devron)\
**Post date:** [September 10, 2020, 10:28am UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/10 "2020-09-10T10:28:16Z")

</div>

In my case the condition will be (screen is off) so there’s no user input, I just want to suspend any view updates (to-view, ${prop}) from triggering.

or .bind, .two-way for that matter

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [September 10, 2020, 10:48am UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/11 "2020-09-10T10:48:53Z")

</div>

It’s not guaranteed that everything will work properly, but you can do it like this:

- get the reference to the view of the current custom element
- get the reference to all bindings and controllers (of custom elements/attributes) in side this view
- for each binding, suspend update target
- for each controller, get the view and recursively do this process, if wanted

So with the above process, you can suspend everything from the root of your application with a simple call.

The implementation will be something like this:

```auto
import { View } from 'aurelia-framework';
import { If, Repeat } from 'aurelia-templating-resources';

View.prototype.pauseUpdateTarget = function(recursive) {
  this.bindings.forEach(binding => {
    const shouldOvererideUpdateTarget = binding.updateTarget
      && binding.updateTarget !== pausableUpdateTarget;
    if (shouldOverrideUpdateTarget) {
      binding.originalUpdateTarget = binding.updateTarget;
      binding.updateTarget = pausableUpdateTarget;
    }
    binding.paused = true;
  });

  if (recursive) {
    this.controllers.forEach(controller => {
      if (controller.view) {
        controller.view.pauseUpdateTarget(true);
      }
    });
  }
};

View.prototype.resumeUpdateTarget = function(recursive) {
  this.bindings.forEach(binding => binding.paused = false);
  if (recursive) {
    this.controllers.forEach(controller =>
      controller.view && controller.view.resumeUpdateTarget(true)
    );
  }
}

function pausableUpdateTarget() {
  if (this.paused) {
    return;
  }
  return this.originalUpdateTarget.apply(this, arguments);
}

```

And in your app root

```auto
export class AppRoot {
  created(owningView, view) {
    this.view = view;
    document.on('visibilitychange', () => {
      if (document.hidden) {
        view.pauseUpdateTarget(true);
      } else {
        view.resumeUpdateTarget(true);
      }
    });
  }
}

```

cc @fkleuver for potential configuration in v2

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [September 10, 2020, 10:54am UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/12 "2020-09-10T10:54:28Z")

</div>

We can go 1 step further and stop it from handling change notifications from source if needed, but that’s a bit more involved. Maybe try the above first and do some more monitoring?  
Edit: Can also check if target is a DOM element then stop updating, else keep the value flow.

---

<div class="post-metadata">

**Author:** ![Devron](https://avatars.discourse-cdn.com/v4/letter/d/ec9cab/32.png) [@Devron](https://discourse.aurelia.io/u/Devron)\
**Post date:** [September 10, 2020, 11:06am UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/13 "2020-09-10T11:06:01Z")

</div>

wow, thank you! Amazing work, it looks the goods… I’ll give this a go and let you know how it goes. I use Aurelia on several projects but don’t have this level of understanding of the inner workings as yet. I really appreciate the detail. Cheers

---

<div class="post-metadata">

**Author:** ![Devron](https://avatars.discourse-cdn.com/v4/letter/d/ec9cab/32.png) [@Devron](https://discourse.aurelia.io/u/Devron)\
**Post date:** [September 10, 2020, 11:22am UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/14 "2020-09-10T11:22:14Z")

</div>

wait, what is suspendableUpdateTarget and pausableUpdateTarget??

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [September 10, 2020, 11:22am UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/15 "2020-09-10T11:22:58Z")

</div>

Same, renaming without `F2`, use `pausableUpdateTarget`. Updated

---

<div class="post-metadata">

**Author:** ![Devron](https://avatars.discourse-cdn.com/v4/letter/d/ec9cab/32.png) [@Devron](https://discourse.aurelia.io/u/Devron)\
**Post date:** [September 10, 2020, 9:13pm UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/16 "2020-09-10T21:13:47Z")

</div>

So far this seems to be working as expected but I have a little more testing to do as yet… here’s a question on this, when the screen visibility changes to visible is it possible to ‘flush’ the last update to the dom ? I’m looking to get the most recent property change to the dom, and not rely on it changing within the last second via my background task as not all properties will be updated every second.

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [September 10, 2020, 11:32pm UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/17 "2020-09-10T23:32:03Z")

</div>

Probably it’s safe to do this:

```auto
View.prototype.flushChanges = function(recursive) {
  if (!this.isBound) {
    return;
  }
  this.bindings.forEach(binding => {
    if (binding.sourceExpression) {
      binding.originalUpdateTarget(binding.sourceExpression.evaluate(
        binding.source,
        binding.lookupFunctions
      ));
    }
  });

  if (recursive) {
    this.controllers.forEach(controller => {
      if (controller.view) controller.view.flushChanges(true);
    });
  }
}

```

---

<div class="post-metadata">

**Author:** ![Bart](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bart/32/1878_2.png) [@Bart](https://discourse.aurelia.io/u/Bart)\
**Post date:** [September 13, 2020, 9:23am UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/18 "2020-09-13T09:23:55Z")

</div>

Hi @bigopon,

I was able to reason about the code in your earlier post where you defined the `pauseUpdateTarget` and `resumeUpdateTarget` instance methods for the `View` class and used those in the `AppRoot`‘s `created` lifecycle hook. Very interesting. But I fail to see how your `flushChanges’ instance method in your latest post is intended to work.

Does it replace an existing implementation of a `flushChanges` instance method of the `View` class? Regrettably, I was unable to locate such a method in Aurelia’s source code for the `View` class (in `/src/view.js` in the `aurelia-templating` package). I did notice some `flushChanges` method implementations in some accessor and observer classes in the `@aurelia/runtime-html` package, but that package seems to be an Aurelia vNext package.

But if the `flushChanges` method does not already exist in the `View` class, I assume it could be considered to be an additional “custom” instance method of the `View` class? But how and when should it be used/called in that case? I currently do not understand how and when it gets called.

Or am I perhaps looking in the wrong places in the source code? Or do I need to investigate Aurelia’s internal mechanisms in some more detail to understand how this code is supposed to work?

Thanks in advance. 🙂

Edit: Sorry… Just re-read @Devron’s latest post. So it is intended to be called when screen visibility is changed to visible. 😬 😅

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [September 13, 2020, 9:48am UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/19 "2020-09-13T09:48:02Z")

</div>

> Edit:…

Yes, so to clarify the whole picture with our future selves:

```ts
export class AppRoot {
  created(owningView, view) {
    this.view = view;
    document.on('visibilitychange', () => {
      if (document.hidden) {
        view.pauseUpdateTarget(true);
      } else {
        view.resumeUpdateTarget(true);
        view.flushChanges(true);
      }
    });
  }
}

```

@Devron use case is very interesting, and for the example code above, I think we can push it further, like this:

- if binding target is not a DOM element, then proceed update
- if binding is not paused, proceed update

This will make the data flow throw the entire app, without updating any UI pieces, and should be extremely performant if you want to propagate changes down to leaf components for some side effects, maybe 😄

---

<div class="post-metadata">

**Author:** ![Devron](https://avatars.discourse-cdn.com/v4/letter/d/ec9cab/32.png) [@Devron](https://discourse.aurelia.io/u/Devron)\
**Post date:** [September 13, 2020, 10:44am UTC](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766/20 "2020-09-13T10:44:45Z")

</div>

This is exactly how I’ve applied this, but I’ve been slightly distracted with other priorities. I’ll be doing more testing on this soon. Thanks again for all your help so far!

[Next page](https://discourse.aurelia.io/t/conditional-suspension-of-bindings/3766.md?page=2)
