DEV Community

Cover image for Why Angular Isn’t the Observable Framework You Think It Is
Dario Mannu for ReactiveHTML

Posted on

Why Angular Isn’t the Observable Framework You Think It Is

When many developers hear "observables", one framework often jumps to mind: Angular. It’s been closely tied to RxJS for years, marketed as the reactive framework of choice.

But here’s the catch: Angular doesn’t actually live in the observable world. Instead, it constantly forces you to switch gears — juggling RxJS streams on one side, and its own reactivity model (async pipes, now signals) on the other.

And that’s where the cracks start to show.

You’re wiring async pipes everywhere.

You’re managing BehaviorSubjects by hand.

You always have to unsubscribe.

And now, with signals, you’re asked to learn yet another reactive abstraction.

It’s not seamless. It’s not elegant. And it’s certainly not the pure observable experience RxJS developers dream about.

Enter Rimmel.js: Built on Streams from Day One

Imagine a UI library where you don’t need two paradigms. Where event sources and data sinks just bind to streams and your UI is simply a declarative destination for your data. That’s what Rimmel.js was designed to do.

This isn’t Angular with a bolt-on async pipe. This is [stream-oriented programming] — where observables aren’t guests at the table, they are the table.

And the difference is dramatic.

Angular vs Rimmel in Practice

Counter Example

Angular version

@Component({
  selector: 'app-counter',
  template: `
    <button (click)="increment()">+</button>
    <span>{{ count$ | async }}</span>
  `,
})
export class CounterComponent {
  private count = new BehaviorSubject(0);
  count$ = this.count.asObservable();

  increment() {
    this.count.next(this.count.value + 1);
  }
}
Enter fullscreen mode Exit fullscreen mode

Rimmel.js version

const Counter = () => {
  const total = new BehaviorSubject(0).pipe(
    scan(x=>x+1)
  );

  return rml`
    <button onclick="${total}">
      click me <span>${total}</span>
    </button>
  `;
};
Enter fullscreen mode Exit fullscreen mode

No async pipes. No imperative methods. Just streams, neatly and directly connected to the UI.

Angular Signals vs Rimmel Observables

Angular’s recent push for signals looks shiny at first glance. They promise "fine-grained reactivity" and "fewer recalculations". But here’s what actually happens:

You now have two reactive paradigms: signals and RxJS.

Data from an observable still has to be bridged into a signal.

Events from your UI still go through imperative steps.

Your app ends up with split logic: streams for async work, signals for rendering.

You learn one reactive model, then constantly translate it into another.

That’s unnecessary complexity.

With Rimmel.js, you don’t need signals at all. Observables are already expressive, composable, and powerful enough to handle both async data and complex state. By cutting out the extra layer, you stay in one mental model: streams in, streams out.

The result? Code that feels neat, light, direct, and more predictable.

Why This Matters for Developers

Rimmel.js gives you:

True first-class observables. No pipes, no wrappers.

Cleaner code. Every part of your app speaks one language: streams.

Future-proof thinking. Stream-oriented programming scales elegantly with complexity.

Instant familiarity. If you know RxJS, you already know most of Rimmel.js.

Instead of wrestling with multiple reactivity systems, you can finally focus on what matters: building features, not boilerplate.

The Takeaway

Angular might be the framework you think of when you think "observables", but the reality is that Angular’s observable support is skin-deep. It keeps you juggling async pipes, signals, and RxJS — a constant context-switching tax.

Rimmel.js flips that script. By embracing a stream-oriented paradigm, it turns observables into the natural fabric of your application. Your knowledge of RxJS doesn’t just transfer — it thrives.

Learn More

Top comments (0)