---
title: Bitovi Academy - RxJS in Angular
description: Learn how to read and write observables in Angular.
---

- ![AI implementation](https://www.bitovi.com/hubfs/AIConsultingIcon.svg)
  
  [AI implementation](https://www.bitovi.com/services/ai-consulting?hsLang=en-us)
- ![Systems engineering](https://www.bitovi.com/hubfs/icon%20-%20backend.svg)
  
  [Systems engineering](https://www.bitovi.com/services/systems-engineering-consulting?hsLang=en-us)
- ![Project management](https://www.bitovi.com/hubfs/icon%20-%20PM.svg)
  
  [Project management](https://www.bitovi.com/services/agile-project-management-consulting?hsLang=en-us)
- ![Product design](https://www.bitovi.com/hubfs/icon%20-%20design.svg)
  
  [Product design](https://www.bitovi.com/services/product-design-consulting?hsLang=en-us)
- ![Frontend development](https://www.bitovi.com/hubfs/icon%20-%20frontend.svg)
  
  [Frontend development](https://www.bitovi.com/services/frontend-development-consulting?hsLang=en-us)
- [View more
  
  →
  
  ](https://www.bitovi.com/digital-consulting-services?hsLang=en-us)

We're Experts in...

- [JavaScript](https://www.bitovi.com/services/frontend/javascript-consulting?hsLang=en-us)
- [AI training](https://www.bitovi.com/ai-training-for-software-engineers?hsLang=en-us)
- [Angular](https://www.bitovi.com/services/frontend/angular-consulting?hsLang=en-us)
- [Design Systems](https://www.bitovi.com/services/axure-figma-migration?hsLang=en-us)
- [React](https://www.bitovi.com/services/frontend/react-consulting?hsLang=en-us)
- [Temporal](https://www.bitovi.com/services/backend/temporal-consulting?hsLang=en-us)
- [React Native](https://www.bitovi.com/services/frontend/react-consulting/react-native?hsLang=en-us)
- [Node.js](https://www.bitovi.com/services/backend/nodejs-consulting-1?hsLang=en-us)

Showcase

![Yum! Brands](https://www.bitovi.com/hubfs/yum-showcase-link-1.png)

[View case study](https://www.bitovi.com/en/bitovi-yum-case-study?hsLang=en-us)

More Projects

- [![Levi's](https://www.bitovi.com/hubfs/levis.svg)](https://www.bitovi.com/web-application-consulting-work/levis-ecommerce-responsive-redesign?hsLang=en-us)
- [![Christie's International Real Estate](https://www.bitovi.com/hubfs/christies.svg)](https://design.bitovi.com/christies)
- [![BAFS](https://www.bitovi.com/hubfs/bafs.svg)](https://www.bitovi.com/ux-design-consulting/ux-case-studies/bafs-ppp?hsLang=en-us)
- [View more
  
  →
  
  ](https://www.bitovi.com/our-software-consulting-work?hsLang=en-us)

Open Source Tools

We build powerful tools and open source them to support the community.

[See what we've built →](https://www.bitovi.com/open-source?hsLang=en-us)

- [![Blog](https://www.bitovi.com/hubfs/icon%20-%20blog.svg)
  
  BlogWe post about perfecting software delivery
  
  ](https://bitovi.com/blog)
- [![Partnerships](https://www.bitovi.com/hubfs/Handshake-1.svg)
  
  PartnershipsLearn about Bitovi's technology partners
  
  ](https://www.bitovi.com/partnerships?hsLang=en-us)
- [![Academy](https://www.bitovi.com/hubfs/limbo/icons/icon-academy.svg)
  
  AcademyFree courses to build delivery skills
  
  ](https://www.bitovi.com/academy/?hsLang=en-us)
- [![Open source tools](https://www.bitovi.com/hubfs/icon%20-%20open%20source.svg)
  
  Open source toolsUse our tools or contribute to our open source mission.
  
  ](https://www.bitovi.com/open-source?hsLang=en-us)

Let's Connect

- [![Discord](https://www.bitovi.com/hubfs/DiscordLogo.svg)
  
  Discord
  
  ](https://discord.gg/J7ejFsZnJ4)
- [![LinkedIn](https://www.bitovi.com/hubfs/LinkedinLogo.svg)
  
  LinkedIn
  
  ](https://www.linkedin.com/company/bitovi/)
- [![GitHub](https://www.bitovi.com/hubfs/GithubLogo.svg)
  
  GitHub
  
  ](https://github.com/bitovi/)

![Eggbot](https://www.bitovi.com/hubfs/build_assets/bitovi-limbo-cms-react/338/js_client_assets/assets/eggbot-LTGhdSGL.png)

Name *

Work Email *

Phone

What's your project?

Send

### Contact Us

(312) 620-0386contact@bitovi.com

- [ Advanced JavaScript ](https://www.bitovi.com/academy/learn-advanced-javascript.html?hsLang=en-us)
- [ DOM and jQuery ](https://www.bitovi.com/academy/learn-dom-jquery.html?hsLang=en-us)
- [ Debug JavaScript ](https://www.bitovi.com/academy/learn-to-debug-javascript.html?hsLang=en-us)
- [ Learn TypeScript ](https://www.bitovi.com/academy/learn-typescript.html?hsLang=en-us)
- [ Learn React Native ](https://www.bitovi.com/academy/learn-react-native.html?hsLang=en-us)
- [ Learn Web Components ](https://www.bitovi.com/academy/learn-web-components.html?hsLang=en-us)
- [ Agile Program Management With Jira ](https://www.bitovi.com/academy/learn-agile-program-management-with-jira.html?hsLang=en-us)
- [ Learn RxJS ](https://www.bitovi.com/academy/learn-rxjs.html?hsLang=en-us) 
    - [ Basics ](https://www.bitovi.com/academy/learn-rxjs/basics.html?hsLang=en-us)
    - [ RxJS in Angular ](https://www.bitovi.com/academy/learn-rxjs/angular.html?hsLang=en-us)
    - [ Clean card number ](https://www.bitovi.com/academy/learn-rxjs/clean-card-number.html?hsLang=en-us)
    - [ Card error ](https://www.bitovi.com/academy/learn-rxjs/card-error.html?hsLang=en-us)
    - [ Debugging ](https://www.bitovi.com/academy/learn-rxjs/debugging.html?hsLang=en-us)
    - [ Error on blur ](https://www.bitovi.com/academy/learn-rxjs/error-on-blur.html?hsLang=en-us)
    - [ Expiry ](https://www.bitovi.com/academy/learn-rxjs/expiry.html?hsLang=en-us)
    - [ CVC ](https://www.bitovi.com/academy/learn-rxjs/cvc.html?hsLang=en-us)
    - [ Disable pay button ](https://www.bitovi.com/academy/learn-rxjs/disable-pay-button.html?hsLang=en-us)
    - [ Request payment ](https://www.bitovi.com/academy/learn-rxjs/request-payment.html?hsLang=en-us)
    - [ Show paying ](https://www.bitovi.com/academy/learn-rxjs/show-paying.html?hsLang=en-us)
    - [ Disable while pending ](https://www.bitovi.com/academy/learn-rxjs/disable-while-pending.html?hsLang=en-us)
- [ Giving a Training ](https://www.bitovi.com/academy/training.html?hsLang=en-us)
- [ Learn Technology Consulting ](https://www.bitovi.com/academy/learn-technology-consulting.html?hsLang=en-us)
- [ Learn React ](https://www.bitovi.com/academy/learn-react.html?hsLang=en-us)
- [ Learn NgRx ](https://www.bitovi.com/academy/learn-ngrx.html?hsLang=en-us)
- [ Learn Graphql ](https://www.bitovi.com/academy/learn-graphql.html?hsLang=en-us)
- [ Learn Docker ](https://www.bitovi.com/academy/learn-docker.html?hsLang=en-us)
- [ Learn CanJS ](https://www.bitovi.com/academy/learn-canjs.html?hsLang=en-us)
- [ Learn Angular ](https://www.bitovi.com/academy/learn-angular.html?hsLang=en-us)
- [ Advanced TypeScript ](https://www.bitovi.com/academy/advanced-typescript.html?hsLang=en-us)

[View More Courses](https://www.bitovi.com/academy/#courses) [ ]

# RxJS in Angular `page`

Learn how to read and write observables in Angular.

## Video

Who has time to read? This video covers the content on this page. Watch fullscreen.

## The problem

In this section, we will:

- Create a CodePen setup with Angular and the HTML of our form.
- Write values to a [Subject](https://rxjs.dev/guide/subject) and write out the value of the subject in the template.

## Observables and the $ suffix

At Bitovi, we follow the [ts.dev Style Guide](https://ts.dev/style/#naming-style) and prefer to suffix Observables with `$`.

Although [not enforced](https://angular.io/guide/rx-library#naming-conventions-for-observables), it is useful to visually differentiate between observable and non-observable values.

## How to solve this problem

- Create a `userCardNumber$` `BehaviorSubject`.
- Write the value of the `cardNumber` input to the `userCardNumber$` `BehaviorSubject` on the `input` event.
- Write the value of `cardNumber` out in the template under the `</form>` element like:
  
  ```
  </form>
  UserCardNumber: {{ GET-CARD-NUMBER-HERE }} <br />
  ```

## What you need to know

Click *"Run in your browser"* at the bottom of the following example to launch a CodePen with Angular and the HTML of the credit card form. You will edit this CodePen for the remainder of this tutorial.

```
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.4.0/rxjs.umd.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/3.19.0/core.js"></script>
<script src="https://unpkg.com/@angular/core@12.2.16/bundles/core.umd.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/zone.js/0.11.4/zone.min.js"></script>
<script src="https://unpkg.com/@angular/common@12.2.16/bundles/common.umd.js"></script>
<script src="https://unpkg.com/@angular/compiler@12.2.16/bundles/compiler.umd.js"></script>
<script src="https://unpkg.com/@angular/platform-browser@12.2.16/bundles/platform-browser.umd.js"></script>
<script src="https://unpkg.com/@angular/platform-browser-dynamic@12.2.16/bundles/platform-browser-dynamic.umd.js"></script>
<my-app></my-app>
<script type="typescript">
  // app.js
  const { Component, VERSION } = ng.core;

  @Component({
    selector: 'my-app',
    template: `
      <form>
        <div class="message"></div>

        <input type="text" name="cardNumber" placeholder="Card Number" />

        <input type="text" name="expiry" placeholder="MM-YY" />

        <input type="text" name="cvc" placeholder="CVC" />

        <button>
          PAY
        </button>
      </form>
    `
  })
  class AppComponent {

      constructor() {

      }
  }

  // main.js
  const { BrowserModule } = ng.platformBrowser;
  const { NgModule } = ng.core;
  const { CommonModule } = ng.common;

  @NgModule({
    imports: [
      BrowserModule,
      CommonModule,
    ],
    declarations: [AppComponent],
    bootstrap: [AppComponent],
    providers: []
  })
  class AppModule {}

  const { platformBrowserDynamic } = ng.platformBrowserDynamic;

  platformBrowserDynamic()
    .bootstrapModule(AppModule)
    .catch(err => console.error(err));
</script>
<style>
  @import url('https://fonts.googleapis.com/css?family=Raleway:400,500');
  body {
    background-color: rgba(8, 211, 67, 0.3);
    padding: 2%;
    font-family: 'Raleway', sans-serif;
    font-size: 1em;
  }
  input {
    display: block;
    width: 100%;
    box-sizing: border-box;
    font-size: 1em;
    font-family: 'Raleway', sans-serif;
    font-weight: 500;
    padding: 12px;
    border: 1px solid #ccc;
    outline-color: white;
    transition: background-color 0.5s ease;
    transition: outline-color 0.5s ease;
  }
  input[name='cardNumber'] {
    border-bottom: 0;
  }
  input[name='expiry'],
  input[name='cvc'] {
    width: 50%;
  }
  input[name='expiry'] {
    float: left;
    border-right: 0;
  }
  input::placeholder {
    color: #999;
    font-weight: 400;
  }
  input:focus {
    background-color: rgba(130, 245, 249, 0.1);
    outline-color: #82f5f9;
  }
  input.is-error {
    background-color: rgba(250, 55, 55, 0.1);
  }
  input.is-error:focus {
    outline-color: #ffbdbd;
  }
  button {
    font-size: 1em;
    font-family: 'Raleway', sans-serif;
    background-color: #08d343;
    border: 0;
    box-shadow: 0px 1px 3px 1px rgba(51, 51, 51, 0.16);
    color: white;
    font-weight: 500;
    letter-spacing: 1px;
    margin-top: 30px;
    padding: 12px;
    text-transform: uppercase;
    width: 100%;
  }
  button:disabled {
    opacity: 0.4;
    background-color: #999999;
  }
  form {
    background-color: white;
    box-shadow: 0px 17px 22px 1px rgba(51, 51, 51, 0.16);
    padding: 40px;
    margin: 0 auto;
    max-width: 500px;
  }
  .message {
    margin-bottom: 20px;
    color: #fa3737;
  }
</style>

```

Initialize a [BehaviorSubject](https://rxjs.dev/api/index/class/BehaviorSubject) instance on a `class` like the following:

```
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.4.0/rxjs.umd.min.js"></script>
<script type="typescript">
  const { BehaviorSubject } = rxjs;

  class AppComponent {
    userCardNumber$ = new BehaviorSubject<string>();
  }

  const app = new AppComponent();
  console.log(app.userCardNumber$) // logs Observable
</script>
```

A `BehaviorSubject` is just like a `Subject` except that it remembers its last value. Any new subscribers will immediately be sent the last value.

```
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.4.0/rxjs.umd.min.js"></script>
<script type="typescript">
  const { BehaviorSubject } = rxjs;

  const subject = new BehaviorSubject<string>();

  subject.next("THE PAST");

  subject.subscribe((value) => console.log(value));
  // logs "THE PAST"
</script>
```

Emit a value on a Subject by calling `subject.next()`:

```
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.4.0/rxjs.umd.min.js"></script>
<script type="typescript">
  const { BehaviorSubject } = rxjs;

  class AppComponent {
    userCardNumber$ = new BehaviorSubject<string>();
  }

  const app = new AppComponent();

  app.userCardNumber$.subscribe(console.log); // logs undefined

  app.userCardNumber$.next("1111-2222-3333-4444"); // logs "1111-2222-3333-4444"
</script>
```

You can call `subject.next()` in the DOM as follows:

```
<input
  type="text"
  name="cardNumber"
  placeholder="Card Number"
  (input)="userCardNumber$.next($event.target.value)"
/>
```

Use `| async` to write out an observable’s value in a template as follows:

```
UserCardNumber: {{ userCardNumber$ | async }} <br />
```

Read more about this technique [here](https://angular.io/guide/observables-in-angular#async-pipe).

## The solution

Click to see the solution

```
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.4.0/rxjs.umd.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/3.19.0/core.js"></script>
<script src="https://unpkg.com/@angular/core@12.2.16/bundles/core.umd.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/zone.js/0.11.4/zone.min.js"></script>
<script src="https://unpkg.com/@angular/common@12.2.16/bundles/common.umd.js"></script>
<script src="https://unpkg.com/@angular/compiler@12.2.16/bundles/compiler.umd.js"></script>
<script src="https://unpkg.com/@angular/platform-browser@12.2.16/bundles/platform-browser.umd.js"></script>
<script src="https://unpkg.com/@angular/platform-browser-dynamic@12.2.16/bundles/platform-browser-dynamic.umd.js"></script>
<my-app></my-app>
<script type="typescript">
  // app.js
  const { Component, VERSION } = ng.core;
  const { BehaviorSubject } = rxjs;

  @Component({
    selector: 'my-app',
    template: `
      <form>
          <div class="message"></div>

          <input
            type="text"
            name="cardNumber"
            placeholder="Card Number"
            (input)="userCardNumber$.next($event.target.value)"
          />

          <input type="text" name="expiry" placeholder="MM-YY" />

          <input type="text" name="cvc" placeholder="CVC" />

          <button>
            PAY
          </button>
      </form>
      UserCardNumber: {{ userCardNumber$ | async }} <br />
    `
  })
  class AppComponent {
    userCardNumber$ = new BehaviorSubject<string>();

    constructor() {

    }
  }

  // main.js
  const { BrowserModule } = ng.platformBrowser;
  const { NgModule } = ng.core;
  const { CommonModule } = ng.common;

  @NgModule({
    imports: [
      BrowserModule,
      CommonModule,
    ],
    declarations: [AppComponent],
    bootstrap: [AppComponent],
    providers: []
  })
  class AppModule {}

  const { platformBrowserDynamic } = ng.platformBrowserDynamic;

  platformBrowserDynamic()
    .bootstrapModule(AppModule)
    .catch(err => console.error(err));
</script>
<style>
  @import url('https://fonts.googleapis.com/css?family=Raleway:400,500');
  body {
    background-color: rgba(8, 211, 67, 0.3);
    padding: 2%;
    font-family: 'Raleway', sans-serif;
    font-size: 1em;
  }
  input {
    display: block;
    width: 100%;
    box-sizing: border-box;
    font-size: 1em;
    font-family: 'Raleway', sans-serif;
    font-weight: 500;
    padding: 12px;
    border: 1px solid #ccc;
    outline-color: white;
    transition: background-color 0.5s ease;
    transition: outline-color 0.5s ease;
  }
  input[name='cardNumber'] {
    border-bottom: 0;
  }
  input[name='expiry'],
  input[name='cvc'] {
    width: 50%;
  }
  input[name='expiry'] {
    float: left;
    border-right: 0;
  }
  input::placeholder {
    color: #999;
    font-weight: 400;
  }
  input:focus {
    background-color: rgba(130, 245, 249, 0.1);
    outline-color: #82f5f9;
  }
  input.is-error {
    background-color: rgba(250, 55, 55, 0.1);
  }
  input.is-error:focus {
    outline-color: #ffbdbd;
  }
  button {
    font-size: 1em;
    font-family: 'Raleway', sans-serif;
    background-color: #08d343;
    border: 0;
    box-shadow: 0px 1px 3px 1px rgba(51, 51, 51, 0.16);
    color: white;
    font-weight: 500;
    letter-spacing: 1px;
    margin-top: 30px;
    padding: 12px;
    text-transform: uppercase;
    width: 100%;
  }
  button:disabled {
    opacity: 0.4;
    background-color: #999999;
  }
  form {
    background-color: white;
    box-shadow: 0px 17px 22px 1px rgba(51, 51, 51, 0.16);
    padding: 40px;
    margin: 0 auto;
    max-width: 500px;
  }
  .message {
    margin-bottom: 20px;
    color: #fa3737;
  }
</style>

```

###### On this page...

###### Get help

If you need [help](https://discord.gg/J7ejFsZnJ4) with an exercise, please reach out to us on [Discord](https://discord.gg/J7ejFsZnJ4)

If you find a bug, please [create an issue](https://github.com/bitovi/academy/issues/new) or email [contact@bitovi.com](mailto:contact@bitovi.com?Subject=Training%20Suggestion)

## Join the Bitovi Newsletter

 Do you want to receive updates about new Bitovi Academy courses, Bitovi open source projects, and dev community news? If so, please provide your email. We won’t spam you or give it away for any reason!  
*By providing your email you agree to receive communications from Bitovi*

![](https://bitovi.github.io/academy/static/img/close.svg)

```json
{
     "@context": "http://schema.org",
     "@type": "Organization",
     "mainEntityOfPage":{
          "@type":"WebPage",
          "@id":"https://www.bitovi.com/academy/learn-rxjs/angular.html",
          "description": "Learn how to read and write observables in Angular. 
"
     },
     "url": "http://bitovi.com",
     "logo": "https://www.bitovi.com/hubfs/bitovi-logo-23-1.svg",
     "image": "https://www.bitovi.com/hubfs/bitovi-logo-x2.png",
     "name": "Bitovi Web App Consulting",
     "alternateName": "Bitovi",
      "naics": "541511",
      "description": "Bitovi is a UX, UI design and front-end JavaScript development consulting company",
     "address": {
          "@type": "PostalAddress",
          "streetAddress": "1134 Pine Tree Lane ",
          "addressLocality": "Libertyville",
          "addressRegion": "IL",
          "addressCountry": "United States",
          "postalCode": "60048"
     },
     "areaServed": {
          "@type": "GeoCircle",
          "geoMidpoint": {
               "@type": "GeoCoordinates",
               "latitude": "41.8781",
               "longitude": "87.6298"
          },
          "geoRadius": "5000 km"
     },
     "telephone": "312-620-0386",
     "email": "contact@bitovi.com",
     "sameAs": [
          "https://www.facebook.com/BitoviLLC/",
          "https://twitter.com/bitovi",
          "https://www.linkedin.com/company/bitovi"
     ]
}
```