Subscribe to two Knockout JS observables so that I am notified only once if either of them changes

Currently, I have a timestamp filter feature that allows users to adjust the start and end times. When a user modifies either the start or end time, the subscribe callback functions correctly. However, if a user changes both the start and end times at once, my subscribing function is triggered twice as anticipated. Is there a way for me to prevent this behavior and ensure that the function is only called once? Any advice on how I can accomplish this?

Answer №1

If you're using KO 3.4.0 or later, you have the option to implement deferred updates on a computed property that depends on both start and end, ensuring changes are detected even when these values change in complementary ways:

let eitherX = 1;
const either = ko.computed(() => {
    start();
    end();
    return ++eitherX;
});
either.extend({deferred: true});

Check out this Live Example:

const start = ko.observable(10);
const end = ko.observable(20);
let eitherX = 1;
const either = ko.computed(() => {
    start();
    end();
    return ++eitherX;
});
either.extend({deferred: true});

console.log("Subscribing");
// Enabling deferred updates
either.subscribe(() => console.log("notified"));
console.log("changing start");
start(11);
console.log("changing end");
end(19);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

In prior versions of Knockout, you can utilize a rate limit set at 0:

let eitherX = 1;
const either = ko.computed(() => {
    start();
    end();
    return ++eitherX;
});
either.extend({rateLimit: 0});

Here's how it works in action:

const start = ko.observable(10);
const end = ko.observable(20);
let eitherX = 1;
const either = ko.computed(() => {
    start();
    end();
    return ++eitherX;
});
either.extend({rateLimit: 0});

console.log("Subscribing");
// Applying rate limit
either.subscribe(() => console.log("notified"));
console.log("changing start");
start(11);
console.log("changing end");
end(19);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>


To ensure proper reactivity, include eitherX in your setup so that the value of either is always distinct upon recomputation. Otherwise, if you solely rely on start and end in defining either, any changes made to one while simultaneously modifying the other will not trigger notifications due to unaltered output.

Answer №2

It is crucial to consider the scenario where both filters need to be programmatically altered simultaneously, yet only a single callback should be activated. On the contrary, if users are expected to adjust the filters sequentially, it introduces a different challenge.

The uncertainty of whether the user will modify the endtime after adjusting the starttime poses a dilemma. How can one determine the appropriate duration to wait for the starttime trigger before proceeding?

An option worth exploring is incorporating a "Confirm filter" button following the completion of both input filter adjustments, which would then trigger the callback.

Another approach involves engaging in two separate callbacks, although this may lead to interruptions if the second callback is triggered mid-process, an outcome that can be deemed undesirable, wouldn't you agree?

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What encodings does FileReader support?

Are you looking to easily read user-input files as text? If you can count on modern browser usage, then using FileReader is the way to go (and it works exceptionally well). reader.readAsText(myfile, encoding); It's worth noting that encoding defaul ...

Generating TypeScript user-defined type guards from interfaces programmatically

Within my Angular2 project, I have defined an Interface called GridMetadata: grid-metadata.ts export interface GridMetadata { activity: string; createdAt: object; totalReps: number; updatedAt: object; } In my Service, there is a public method na ...

Tips for storing user information in Firebase using React?

Is there a better way to maintain user sessions in my app? I've noticed that every time a user signs up, if the page reloads, they are logged out. I've tried looking into persistence in the official documentation but I'm still confused about ...

Upon attempting to run `yarn dev` with Webpack 5, I encountered the following error message: "Library name must be a string or

Seeking assistance from my fellow developers. Has anyone encountered this particular issue before? Error output displayed in text: yarn run v1.17.3 $ webpack-dev-server webpack --config ./webpack.dev.config.js --mode development i 「wds」: Project is ...

Having trouble changing the cursor for draggables in Chrome while using vue.js?

In my attempt to change the cursor of a draggable item in Chrome, I have encountered difficulties. Despite trying various methods, nothing seems to be working. The solutions I found on Stackoverflow are outdated and incompatible with the current version of ...

Unable to display results in the control: select2 version 4 ajax data is not showing up

Ever since transitioning to version 4 of the select2 plugin, I've encountered an issue with my ajax requests. Although I receive a response in the console showing as an array, the results are not appearing in the select2 control. The HTTP response l ...

Assign an appropriate label to this sonarqube input field

Sonarqube flagged an issue with the following line of code: <div class="dropdown-language"> <label>{{'GENERALE.LINGUA' | translate }}</label> <select #langSelect (change)="translate.use(langSe ...

Challenges arise when adjusting frame size for mobile and desktop devices

I am trying to achieve an auto-resize feature for my frame's height when the screen width is smaller than a certain value. I want it to behave like Sketchfab, as demonstrated in this video: http://www.youtube.com/watch?v=_y5ckVFGHKU&feature=youtu. ...

Implement the morgan express middleware from exports

For my logging needs in an Express application, I have decided to utilize the morgan package. Initially, I was able to integrate morgan by using it directly in my server.js file like so: app.use(morgan('tiny')), which worked perfectly. However, I ...

Selecting a pair of radio buttons to toggle the visibility of different div elements using JavaScript

I've been working on two radio button categories that control the visibility of different input fields. I'm making progress, but I'm still struggling to get it to work perfectly. Below are the images for reference: The combination of &apos ...

Activate button upon Enter key press

Looking to modify this code so that the "calculate" function is triggered upon pressing enter instead of the button. How can this be achieved? The current functionality is working fine, but I want to enhance it with an enter key press. <!DOCTYPE html> ...

Combining HTML elements to form a fresh element

Consider the following code snippet for selecting and displaying a date: <div> <input type="text" class="txt txtDate"/> <input type="button" class="btn btnDate" value="Select from Calendar&q ...

Numerous buttons available for inputting into individual text boxes all on one page

<html> <body> <script> function enterNumber(num) { var txt=document.getElementById("output").value; txt=txt + num; document.getElementById("output").value=txt; } </script> Select numbers: <br> <input type="button" val ...

Two buttons next to each other positioned below my magnified picture

I'm currently working on implementing a feature where clicking an image enlarges it and displays two buttons at the bottom, but I'm facing some challenges with getting the buttons to show up. Any assistance would be greatly appreciated! Addition ...

What is the most effective method for determining the distance between two UK Postcodes?

Can you suggest a reliable method for calculating the distance between two UK postcodes in order to determine if they are within range? I do not intend to display a map, but instead provide a list of results for valid locations. For example, showing loca ...

This issue arises when attempting to display a Facebook like box within an iframe using Fancybox

As a newcomer to JavaScript, I've been trying to display a fancybox iframe containing my Facebook fan page like box when my website first loads, but have been unsuccessful so far. I've included all the necessary calls to the js files in fancybox ...

Encountering an issue with MUI Props: "Must provide 4 to 5 type arguments."

I'm attempting to use a custom component and pass in AutocompleteProps as a prop, all while utilizing typescript. Here's my current setup: type Props = { autoCompleteProps?: AutocompleteProps<T> label: string loading?: boolean } cons ...

Exploring the method of implementing a "template" with Vue 3 HeadlessUI TransitionRoot

I'm currently working on setting up a slot machine-style animation using Vue 3, TailwindCSS, and HeadlessUI. At the moment, I have a simple green square that slides in from the top and out from the bottom based on cycles within a for-loop triggered by ...

Enhancing the tooltip inner content in Bootstrap with a description:

Can you help me troubleshoot the code below? I am trying to add a description to numbers in my tooltip, but it doesn't seem to be working. Here is the HTML: <input id="contract-length" class="slider slider-step-2 slider-contract-length" ...

Having difficulty displaying GLTF object using three.js

I am attempting to display a GLTF object provided by the guidance from three.js (https://github.com/mrdoob/three.js/blob/master/examples/models/gltf/DamagedHelmet) In order to achieve this, I have used the loader mentioned in their documentation () Follo ...