Ana içeriğe atla

Overview

Data fetching in Analog builds on top of concepts in Angular, such as using HttpClient for making API requests.

Using HttpClient

Using HttpClient is the recommended way to make API requests for internal and external endpoints. The context for the request is provided by the provideServerContext function for any request that uses HttpClient and begins with a /.

Server Request Context

On the server, use the provideServerContext function from the Analog router in the main.server.ts.

import 'zone.js/node';
import { enableProdMode } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { renderApplication } from '@angular/platform-server';

// Analog server context
import { provideServerContext } from '@analogjs/router/server';
import { ServerContext } from '@analogjs/router/tokens';

import { config } from './app/app.config.server';
import { AppComponent } from './app/app.component';

if (import.meta.env.PROD) {
enableProdMode();
}

export function bootstrap() {
return bootstrapApplication(AppComponent, config);
}

export default async function render(
url: string,
document: string,
serverContext: ServerContext
) {
const html = await renderApplication(bootstrap, {
document,
url,
platformProviders: [provideServerContext(serverContext)],
});

return html;
}

This provides the Request and Response, and Base URL from the server and registers them as providers that can be injected and used.

Injection Functions

import { inject } from '@angular/core';
import {
injectRequest,
injectResponse,
injectBaseURL,
} from '@analogjs/router/tokens';

class MyService {
request = injectRequest(); // <- Server Request Object
response = injectResponse(); // <- Server Response Object
baseUrl = injectBaseURL(); // <-- Server Base URL
}

Request Context Interceptor

Analog also provides requestContextInterceptor for the HttpClient that handles transforming any request to URL beginning with a / to a full URL request on the server, client, and during prerendering.

Use it with the withInterceptors function from the @angular/common/http packages.

import {
provideHttpClient,
withFetch,
withInterceptors,
} from '@angular/common/http';
import { ApplicationConfig } from '@angular/core';
import { provideClientHydration } from '@angular/platform-browser';
import { provideFileRouter, requestContextInterceptor } from '@analogjs/router';
import { withNavigationErrorHandler } from '@angular/router';

export const appConfig: ApplicationConfig = {
providers: [
provideFileRouter(withNavigationErrorHandler(console.error)),
provideHttpClient(
withFetch(),
withInterceptors([requestContextInterceptor])
),
provideClientHydration(),
],
};

Make sure the requestContextInterceptor is last in the array of interceptors.

Making Requests

In your component/service, use HttpClient along with [/docs/features/api/overview](API routes) with providing a full URL.

An example API route that fetches todos.

// src/server/routes/v1/todos.ts -> /api/v1/todos
import { eventHandler } from 'h3';

export default eventHandler(async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/todos');
const todos = await response.json();

return todos;
});

An example service that fetches todos from the API endpoint.

// todos.service.ts
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';

import { Todo } from './todos';

@Injectable({
providedIn: 'root',
})
export class TodosService {
http = inject(HttpClient);

getAll() {
return this.http.get<Todo[]>('/api/v1/todos');
}

getData() {
return this.http.get<Todo[]>('/assets/data.json');
}
}

Data requests also use Angular's TransferState to store any requests made during Server-Side Rendering, and are transferred to prevent an additional request during the initial client-side hydration.