Toby
Toby

Reputation: 175

How to load RxJS in a minimal Angular 2 app using systemjs?

I'm unable to get a minimal Angular 2 application using RxJS off the ground. I'm using Typescript (tsc 1.6.2) and systemjs for module loading. How do I get systemjs to load the Rx module correctly? I've run out of ideas to try and I'd appreciate any pointer to what I'm doing wrong. Module loading is a bit of magic to me. Very frustrating.

index.html:

<!DOCTYPE html>
<html>
<head>
    <title>Title</title>
    <script src="../node_modules/es6-shim/es6-shim.js"></script>
    <script src="../node_modules/systemjs/dist/system.src.js"></script>
    <script src="../node_modules/rx/dist/rx.lite.js"></script>
    <script src="../node_modules/angular2/bundles/angular2.dev.js"></script>
</head>

<body>
    <app>App loading...</app>
    <script>
        System.config({
            packages: { 'app': { defaultExtension: 'js' } }
        });
        System.import('app/app');
    </script>
</body>
</html>

app.ts:

/// <reference path="../../node_modules/rx/ts/rx.all.d.ts" />
import { bootstrap, Component, View } from 'angular2/angular2';
import * as Rx from 'rx';

@Component({
    selector: 'app'
})
@View({
        template: `Rx Test`
})
export class App {
    subject: Rx.Subject<any> = new Rx.Subject<any>();
}
bootstrap(App);

SystemJS attempts to load a file that does not exist:

enter image description here

As soon as I comment out the subject in the code above, everything runs fine as there'll be no attempt to load the non-existent file (and no rx is loaded).

Upvotes: 11

Views: 26737

Answers (3)

STEEL
STEEL

Reputation: 10067

Posting this answer after Angular 4 release. Try to load bare minimum from Rxjs, since Angular prod build even with AOT is going 300kb

Hope it helps.

import { Injectable } from '@angular/core';
import {Http} from "@angular/http";
import {Observable} from "rxjs/Observable";
import 'rxjs/add/operator/map';// load this in main.ts

import {AllUserData} from "../../../shared/to/all-user-data";

@Injectable()
export class ThreadsService {

  constructor(private _http: Http) { }

  loadAllUserData(): Observable<AllUserData> {
    return this._http.get('/api/threads')
      .map(res => res.json());
  }

}

Upvotes: 2

Eric Martinez
Eric Martinez

Reputation: 31787

Update angular2 beta 0

Angular2 is no longer bundling RxJS within Angular2 itself. Now you must import the operators individually. This was an important breaking change which I answered here. So please refer to that answer since this one is obsolete and no longer applies.

Update 12/11/2015

Alpha46 is using RxJS alpha 0.0.7 (soon to be 0.0.8). Since this ng2 alpha version you need no more the solution below, you can now import Observable, Subject among others directly from angular2/angular, so the original answer can be discarded

import {Observable, Subject} from 'angular2/angular2';

=====================================

Angular2 is not longer using the old RxJS, they moved to the new RxJS 5 (aka RxJS Next) so it will collide with Http and EventEmitter.

So first remove the import and the script to rx.lite.js.

Instead you have to do (you need no scripts nor mapping in your config)

Edit

This line is to make it work in a plnkr, but in my projects I just have to add something else

Plnkr version

import Subject from '@reactivex/rxjs/dist/cjs/Subject';

Offline version

import * as Subject from '@reactivex/rxjs/dist/cjs/Subject';

Note about offline version

If you try the first approach for plnkr in your local projects you'll probably get this message error

TypeError: Subject_1.default is not a function

So for your local (offline) version you should use the second approach (with the asterisk).

Note

There's no bracket in Subject and that's explained in this conversation (I had the same problem, lol)

Here's a plnkr not failing.

I hope it helps. If I missed something just tell me ;)

Upvotes: 9

Murhaf Sousli
Murhaf Sousli

Reputation: 13296

For angular2 alpha52 uses rxjs 5alpha.14

<script>
System.config({
  map: { rxjs: 'node_modules/rxjs' },
  packages: {
    rxjs: { defaultExtension: 'js' },
    'app': {defaultExtension: 'js'}
  }
});
System.import('app/app');
</script>

but you have to import each operator individually like this example

import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';

require('rxjs/add/operator/map');
require('rxjs/add/operator/scan');
require('rxjs/add/operator/mergemap');  //for flatmap
require('rxjs/add/operator/share');
require('rxjs/add/operator/combinelatest-static'); //for combinelatest

Upvotes: 8

Related Questions