1

I keep getting an empty Array, when using Angulars toSignal function.

The observable returns an array of 5 objects.

But the signal returns an empty array.

Below is the Service code, and Component code.

API Service

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class SpringAPIService {

  private readonly baseUrl = 'http://localhost:8080';

  http = inject(HttpClient)

  getData(endpoint: string): Observable<any> {
    const url = `${this.baseUrl}/${endpoint}`;
    const headers = new HttpHeaders().set('Content-Type', 'application/json');
    const observable = this.http.get(url, { headers });
    return observable;
  }

}

Angular 17 Component

import { Component, Injector, Signal, inject, runInInjectionContext, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SpringAPIService } from '../spring-api.service';
import { toSignal } from '@angular/core/rxjs-interop';

@Component({
  selector: 'app-projects',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './projects.component.html',
  styleUrl: './projects.component.scss'
})
export class ProjectsComponent {

  http: SpringAPIService = inject(SpringAPIService);
  injector = inject(Injector);
  data: Signal<any> = signal([])

  ngOnInit() {
    runInInjectionContext(this.injector, () => {
      this.data = toSignal(this.http.getData('projects'), { initialValue: [] });
      console.log(this.data())
    });
 
  }

}
4
  • 1
    From the docs "by subscribing to that Observable. The returned Signal will always have the most recent value emitted by the subscription" Commented Nov 25, 2023 at 14:40
  • my goal is to try and get a http request, and store it in a signal (rather than an observable). my http request works, but it returns an observable. But I'd like to work with a signal in the actual component. How is that done? Commented Nov 25, 2023 at 18:56
  • 1
    @Sachin your problem is that you are logging the signal value before the request has completed, so you are logging the initialValue. Try printing the value of the signal in the template and see if you get the results expected. Commented Nov 26, 2023 at 18:15
  • I think that was why. I've managed to get it working, when I read the signal elsewhere, e.g. in the template. Thanks! Commented Nov 26, 2023 at 19:02

1 Answer 1

0

When you just log the signal you will get its current value, in your case initial value [] and will not get any further updates.

If you want to react to signal changes, you can use effect, computed or HTML binding. Here is example of effect:

export class App {
  http: SpringAPIService = inject(SpringAPIService);
  data = toSignal(this.http.getData('users'), { initialValue: [] });

  constructor() {
    // if this is ran after HTTP request completes, you will get updated data (only once)
    // setTimeout(() => console.log('+++ DATA', this.data()), 2000);
    effect(() => {
      console.log('+++ DATA', this.data());
    });
  }
}

in this case you will get 2 logs: first with initial data and then with fetched data.

Please note that by default you can create effect only within INJECTION CONTEXT.

I created a STACKBLITZ to demonstrate it.

Sign up to request clarification or add additional context in comments.

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.