There are certain situations in which you’ll want access to the latest values from multiple Observables whenever any one of them produces a value. This is exactly what
combineLatest was designed for, and in this lesson we’ll use it to build up an image url that requires values from 3 different inputs - triggered every time any one of them change.
The combine latest operator takes a number of observables, and when any one of them produces a value, it gives you back that value along with the latest values from all of the others. We can see it in action by building this tiny app.
Here, we are using an image placeholder service. We pass the URL with the size you want, the background color, the font color, and any text you want as a query parameter. We have this text import field to handle the text and then two selects. One for the background color and the font color.
We want to update the source of this image when any of these fields change. If we type here, we'll need to get the value that was typed in, along with the current background color, the current font color. Then we can rebuild the URL and update the image source.
This is a perfect use case for combine latest. Let me show you why. To save time, I already have a reference to the from event helper that ships with RxJS, as well as references to the four DOM elements that are needed.
The first step to solving problems like this with RxJS, is to look at each of your data sources and turn those into observable sequences. In our case, the first one is a text input, so we can use the from event helper to get a value every time a character is typed.
We use the dollar sign as the last character, as a convention to show that this is an observable. Then we'll call from event, pass along the text DOM element. We're listening for key up events. Then we use the selector function to project the value of the text input field, instead of the input field itself.
We'll need to give this an initial value. We can use whatever's in the text input field on page load. We call start with, and we'll say text.value. This is an observable that will produce a value every time there is a key up event on this DOM element.
We can quickly prove by subscribing to this and just logging to the console. Here you see an empty line. This is because the text import has no value on page load. As we type here, you can see we're getting the characters.
We need to do the same thing for the background color and the font color. The only difference is that because these are select elements, we'll be listening for the change event instead of the key up event. We have three separate observables that can all produce values at different points in time.
The next step is to ensure that, whenever any one of them produce a value, we always have access to the latest from all of the others. This is where combine latest comes in. We call Rx, observable, combine latest. This takes an array of observables so we can pass along our text, background color, font color.
The second argument is the selector function, in which we will actually receive the values from these observables. We'll create local references matching the same names, and then to make it clear, what values we actually have here.
If we log these to the console, and then subscribe to this, straightaway you can see the initial value from page load. You're not seeing any text here because this field is empty, but you are seeing these hex values from the select elements.
Watch what happens when I type inside this text field. You see that for each character, it gives us the value of the text input, but it also gives us the hex values from these selects. What's really cool is that it works for any of the other inputs also.
Changing the background color to white, still gives us the latest value from the text input as well as the new value that we just changed, and then the latest from this one. We have all the values we need to be able to build up this new URL.
We can replace the sections we're interested in. This will be the background color. This is the font color. For the text, we'll ensure that it's safe for a URL. We can pick this with inside the subscription and update this image source.
We'll get access to the URL. Then we'll set the source of the image. Note that this image is the one that's slightly off-screen here. You can already see that this image has changed. The placeholder service that we're using will put the size of the image as the text if you provide an empty string.
Here, we are setting the parameter text equal to an empty string in this case. That's why it's doing that. If we type in here "egghead," you can see it's updated. We can change the background color or the font color. That's the basics of how to use combine latest.
Take another look at this code. Notice that we're not having to track the state of any of the input fields ourselves. It's completely declarative. Here, we've scratched the surface, but imagine going forward that you wanted to put a debounce on this text field.
Because here we have complete separation of concerns, we could very easily add a debounce to the text input of, say, 500 milliseconds. No other part of our code needs to know about that. The function that builds up the URL only knows about these three values.
It doesn't know how it got them or when they arrived. Inside the subscription, where it updates in this image source, this also knows nothing about how this was generated. It knows it receives a URL, and it sets the source attribute on the image.
Although we tend to put things like this in-line to save space on screen, technically, this is a pure function. This could be elsewhere in your code base where it's easier to test or swap out. A final recap for combine latest. We use the from event helper to create observable sequences from these inputs.
They can each produce values at different points in time. Because we want to build up a new URL when any one of them changes, it means that every time we always need all three values. That's the key to understanding combine latest.
It creates a new observable that produces values based on whatever you return from this function. The function is called anytime one of the source observables produce a value. Every key up and change event will cause this selector function to be run, which produces a new URL, which we can then use to update the image source.