Skip to content

About

Client side OData typescript library for Angular

Topics

Resources

Contributing

Security policy

Stars

52 stars

Watchers

4 watching

Forks

Repository files navigation

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.

// 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

npm i angular-odata

2. Register the client

// 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

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:

ng generate angular-odata:apigen --name=TripPin --metadata='https://services.odata.org/V4/TripPinServiceRW/$metadata'
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

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

About

Client side OData typescript library for Angular

Topics

Resources

Contributing

Security policy

Stars

52 stars

Watchers

4 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages