This is part three of a multi-part series where I provide some simple examples of Reactive design using RxJS.

In this example I'm going to show how to create a Subject that updates a DOM element when the subject changes value.

Sample Code

This example adds to the previous example by using the observable input as the source for the subject. The HTML becomes:

<div id="fullName">Full Name</div>

<label for="firstName">First Name</label>
<input type="text" id="firstName">

And the code:

const { fromEvent, Observable, Subject } = rxjs;
const { map } = rxjs.operators;

// Create the observable attached to the firstName input box
var firstName: Observable<string> = fromEvent(document.querySelector('#firstName'), 'input')
  .pipe(map(event => event.target.value));

// Get the fullName DOM element
var fullNameDOM = document.querySelector('#fullName');

// Create a subject to be used to publish values to the fullName DOM
var fullName: Subject<string> = new Subject();

// Connect the fullName subject so that when it changes it updates 
// the fullName DOM element
fullName.asObservable().subscribe((value) => fullNameDOM.innerText = value);

// Subscribe to the firstName observable and use it to publish to
// the fullName subject.
firstName.subscribe((value) => fullName.next(value))

Explanation

To get from the original example to this example, we make three main changes.

The first change is to add a new DOM element that we're calling fullName.

<div id="fullName">Full Name</div>

In code we get a reference to that DOM element.

var fullNameDOM = document.querySelector('#fullName');

Next, we create a Subject, which is a special type of Observable which allows values to be multicast to many Observables.

var fullName: Subject<string> = new Subject();

Once we have a subject, we create a subscription to the subject and use it to publish values to the fullNameDOM.

fullName.asObservable().subscribe((value) => fullNameDOM.innerText = value);

You'll notice that we use asObservable to get to the Observable API of the Subject, and then use the subscribe function to subscribe to it.

The lambda function passed to subscribe takes the resulting value, which at this point is a string thanks to the pipeline .pipe(map(event => event.target.value)), and uses that value to set the innerText property on the fullNameDOM element.

Note: Although I don't show it, this pipe is also a great spot for escaping the value to make it HTML safe to prevent XSS.

Finally, to hook it all together, we modify the subscription to firstName and instead of sending it to the console.log function we send it to the fullName subject by using its next function.

firstName.subscribe((value) => fullName.next(value))

Every time the user changes the value of the input text, the browser fires an event which is handled by the fromEvent and converted into a string using the pipe and published to firstName.

With this final subscription, that value is passed to the fullName via .next(), which in turn has an Observable subscription (fullName.asObservable().subscribe) which takes that text value and sets it on fullNameDOM.innerText with the lambda function (value) => fullNameDOM.innerText = value.

If you want to play with this, check it out on CodePen.