169

I am having a service that has this method:

export class TestModelService {

    public testModel: TestModel;

    constructor( @Inject(Http) public http: Http) {
    }

    public fetchModel(uuid: string = undefined): Observable<string> {
        if(!uuid) {
            //return Observable of JSON.stringify(new TestModel());
        }
        else {
            return this.http.get("http://localhost:8080/myapp/api/model/" + uuid)
                .map(res => res.text());
        }
    }
}

in the component's constructor I am subscribing like this:

export class MyComponent {
   testModel: TestModel;
   testModelService: TestModelService;

   constructor(@Inject(TestModelService) testModelService) {
      this.testModelService = testModelService;

      testService.fetchModel("29f4fddc-155a-4f26-9db6-5a431ecd5d44").subscribe(
          data => { this.testModel = FactModel.fromJson(JSON.parse(data)); },
          err => console.log(err)
      );
   }
}

This works if an object comes from the server but I am trying to create an observable that will work with the given subscribe() call for a static string (this happens when testModelService.fetchModel() does not receive an uuid) so there is seamless handling in both cases.

Philipp Meissner
  • 5,273
  • 5
  • 34
  • 59
Michail Michailidis
  • 11,792
  • 6
  • 63
  • 106

6 Answers6

185

Perhaps you could try to use the of method of the Observable class:

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';

public fetchModel(uuid: string = undefined): Observable<string> {
  if(!uuid) {
    return Observable.of(new TestModel()).map(o => JSON.stringify(o));
  }
  else {
    return this.http.get("http://localhost:8080/myapp/api/model/" + uuid)
            .map(res => res.text());
  }
}
Steve Sanders
  • 8,444
  • 2
  • 30
  • 32
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • 2
    That was awesome! It worked! I was trying many things like Observable.from() etc.. The API documentation for Observable isn't the cleanest/most user-friendly at this point! Thanks :) – Michail Michailidis Feb 05 '16 at 08:50
  • 65
    One thing if you're using version 6, you've to `import { of } from 'rxjs';` and use `of`, instead of `Observable.of`. – vip Aug 07 '18 at 15:13
  • 3
    For Angular v7.x.x there is no `.map()` on the result of get so you need to do `.pipe(map((res:any) => res.json()))`. See here: https://stackoverflow.com/a/35220045/986160 – Michail Michailidis Feb 03 '19 at 13:02
125

As of July 2018 and the release of RxJS 6, the new way to get an Observable from a value is to import the of operator like so:

import { of } from 'rxjs';

and then create the observable from the value, like so:

of(someValue);

Note, that you used to have to do Observable.of(someValue) like in the currently accepted answer. There is a good article on the other RxJS 6 changes here.

Armen Stepanyan
  • 1,618
  • 13
  • 29
VSO
  • 11,546
  • 25
  • 99
  • 187
22

Things seem to have changed since Angular 2.0.0

import { Observable } from 'rxjs/Observable';
import { Subscriber } from 'rxjs/Subscriber';
// ...
public fetchModel(uuid: string = undefined): Observable<string> {
  if(!uuid) {
    return new Observable<TestModel>((subscriber: Subscriber<TestModel>) => subscriber.next(new TestModel())).map(o => JSON.stringify(o));
  }
  else {
    return this.http.get("http://localhost:8080/myapp/api/model/" + uuid)
            .map(res => res.text());
  }
}

The .next() function will be called on your subscriber.

Niel de Wet
  • 7,806
  • 9
  • 63
  • 100
  • 2
    I have migrated to Angular 2.1.2.. The old way seems to be still supported.. Could you please elaborate why this is a better solution or is it the convention? I will then change it in all the places in my code and I will re-accept ..Thanks – Michail Michailidis Nov 21 '16 at 11:50
  • 7
    @MichailMichailidis, with a month of retrospect, it seems to me both are equally valid, the main difference being that Thierry's solution requires you to import the `of` function of rxjs, like `import 'rxjs/add/observable/of'` – Niel de Wet Nov 21 '16 at 12:11
13

This is how you can create a simple observable for static data.

let observable = Observable.create(observer => {
  setTimeout(() => {
    let users = [
      {username:"balwant.padwal",city:"pune"},
      {username:"test",city:"mumbai"}]

    observer.next(users); // This method same as resolve() method from Angular 1
    console.log("am done");
    observer.complete();//to show we are done with our processing
    // observer.error(new Error("error message"));
  }, 2000);

})

to subscribe to it is very easy

observable.subscribe((data)=>{
  console.log(data); // users array display
});

I hope this answer is helpful. We can use HTTP call instead static data.

Druta Ruslan
  • 7,171
  • 2
  • 28
  • 38
Balwant Padwal
  • 261
  • 4
  • 8
5

As of May 2021 the new way to get an Observable from a value is:

importing:

import "rxjs/add/observable/of"
import { Observable } from "rxjs/Observable"

and using, like so::

Observable.of(your_value)
danilo
  • 7,680
  • 7
  • 43
  • 46
3

This way you can create Observable from data, in my case I need to maintain shopping cart:

service.ts

export class OrderService {
    cartItems: BehaviorSubject<Array<any>> = new BehaviorSubject([]);
    cartItems$ = this.cartItems.asObservable();

    // I need to maintain cart, so add items in cart

    addCartData(data) {
        const currentValue = this.cartItems.value; // get current items in cart
        const updatedValue = [...currentValue, data]; // push new item in cart

        if(updatedValue.length) {
          this.cartItems.next(updatedValue); // notify to all subscribers
        }
      }
}

Component.ts

export class CartViewComponent implements OnInit {
    cartProductList: any = [];
    constructor(
        private order: OrderService
    ) { }

    ngOnInit() {
        this.order.cartItems$.subscribe(items => {
            this.cartProductList = items;
        });
    }
}
Rahul Dadhich
  • 1,213
  • 19
  • 32