Angular OData

A typed, fluent client for OData services in Angular.

Handbook · API reference · Demo · Contributing

CI status   Angular OData on npm


OData is a standard for REST APIs: every service describes its data in a $metadata document and accepts the same query options ($filter, $select, $expand, $orderby, …). angular-odata lets your Angular application talk to any OData service without writing URLs by hand: you build requests with typed TypeScript code and get back typed results.

Example :
// GET People?$select=UserName,FirstName&$filter=contains(UserName, 'russell')&$top=10
client
  .entitySet<Person>('People')
  .query((q) => {
    q.filter(({ e, t }) => e().contains(t.UserName, 'russell'));
    q.select(['UserName', 'FirstName']);
    q.top(10);
  })
  .fetch()
  .subscribe(({ entities }) => console.log(entities));

Features

  • Typed query builder: $filter, $select, $expand, $orderby, $search, $compute, $apply and paging, with field names checked by the compiler.
  • Complete OData API: entity sets, entities, navigation properties, functions, actions, singletons, media and $batch requests.
  • Code generation: one command creates interfaces, services and models from your service's $metadata.
  • Models and collections: change tracking, validation and save() / destroy().
  • Caching: in-memory, Web Storage or IndexedDB, with fetch policies such as cache-first and cache-and-network.
  • Several APIs in the same application, each with its own configuration.

Quick start

1. Install

Example :
npm i angular-odata

2. Register the client

Example :
// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideODataClient } from 'angular-odata';

export const appConfig: ApplicationConfig = {
  providers: [
    provideODataClient({
      config: { serviceRootUrl: 'https://services.odata.org/V4/TripPinServiceRW/' },
    }),
  ],
};

Applications that use NgModules can import ODataModule.forRoot({ config }) instead.

3. Query your service

Example :
import { Component, inject, signal } from '@angular/core';
import { ODataClient } from 'angular-odata';

interface Person {
  UserName: string;
  FirstName: string;
  LastName: string;
}

@Component({
  selector: 'app-people',
  template: `
    @for (person of people(); track person.UserName) {
      <p>{{ person.FirstName }} {{ person.LastName }}</p>
    }
  `,
})
export class PeopleComponent {
  private client = inject(ODataClient);
  people = signal<Person[]>([]);

  ngOnInit() {
    this.client
      .entitySet<Person>('People')
      .query((q) => {
        q.orderBy('LastName');
        q.top(10);
      })
      .fetch()
      .subscribe(({ entities }) => this.people.set(entities ?? []));
  }
}

4. Optional: generate a typed API

Instead of writing interfaces and services by hand, generate them from the $metadata of your service:

Example :
ng generate angular-odata:apigen --name=TripPin --metadata='https://services.odata.org/V4/TripPinServiceRW/$metadata'
Example :
import { PeopleService, TripPinConfig } from './trip-pin';

// app.config.ts
provideODataClient({ config: TripPinConfig });

// Any component or service
const people = inject(PeopleService);
people
  .entity('russellwhyte')
  .fetch()
  .subscribe(({ entity }) => console.log(entity));

A few more examples

Example :
const people = client.entitySet<Person>('People');

// Create, update and delete
people.create({ UserName: 'jdoe', FirstName: 'John', LastName: 'Doe' }).subscribe();
people.entity('jdoe').modify({ FirstName: 'Johnny' }).subscribe();
people.entity('jdoe').destroy().subscribe();

// Expand related entities: $expand=Trips($select=Name,Budget)
people
  .entity('russellwhyte')
  .query((q) =>
    q.expand(({ e, t }) =>
      e().field(t.Trips, (f) => f.select(({ e, t }) => e().field(t.Name).field(t.Budget))),
    ),
  )
  .fetch()
  .subscribe(({ entity }) => console.log(entity?.Trips));

// Follow the server's next links and get every entity
people.fetchAll().subscribe(({ entities }) => console.log(entities.length));

Documentation

  • Handbook: guides for configuration, resources, the query builder, services, models, caching and code generation.
  • API reference: every class and method, generated from the source code.
  • Demo application: a complete Angular application that uses the TripPin and Northwind sample services.

Compatibility

  • Angular: 20 or later.
  • OData: version 4 is fully supported; versions 3 and 2 have basic support.

Contributing

Bug reports and pull requests are welcome. Read the contributing guide to get started.

License

MIT

results matching ""

    No results matching ""