176

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.

6 Answers 6

189

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());
  }
}
Sign up to request clarification or add additional context in comments.

3 Comments

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 :)
One thing if you're using version 6, you've to import { of } from 'rxjs'; and use of, instead of Observable.of.
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: stackoverflow.com/a/35220045/986160
137

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.

Comments

23

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.

2 Comments

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
@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'
14

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.

1 Comment

can you update the typo from observable.subscripe to observable.subscribe
6

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 it, like so::

Observable.of(your_value)

Comments

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;
        });
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.