@mmuscat/angular-resource
v0.1200.0-next.1
Published
Data fetching library for Angular Composition API
Downloads
1
Maintainers
Readme
Angular Resource
Data fetching library for Angular Composition API.
Quick Start
npm install @mmuscat/angular-resource
yarn add @mmuscat/angular-resource
Example
Query
function getTodosByUserId() {
const http = inject(HttpClient)
return function (userId) {
return http.get(url, {
params: { userId },
})
}
}
const GetTodosByUserId = new Query(getTodosByUserId)
Mutation
function createTodo() {
const http = inject(HttpClient)
return function (data) {
return http.post(url, data)
}
}
const CreateTodo = new Mutation(createTodo, {
operator: exhaustAll,
})
Usage
function setup() {
const userId = use("123")
const [createTodoStatus, createTodo] = inject(CreateTodo)
const getTodosByUserId = inject(GetTodosByUserId)
const todos = getTodosByUserId(userId, {
refetch: [createTodo],
initialValue: [],
})
return {
todos,
createTodo,
createTodoStatus,
}
}
@Component({
template: `
<spinner *ngIf="todos.pending"></spinner>
<div *ngIf="todos.error">Something went wrong</div>
<todo *ngFor="let todo of todos.value"></todo>
<add-todo (save)="createTodo($event)"></create-todo>
`,
})
export class MyComponent extends ViewDef(setup) {}
Api Reference
Query
Queries are services created from factory functions that return another function that produces an observable stream. Supports dependency injection.
function myQuery() {
const http = inject(HttpClient)
return function (params) {
return http.get(url, {
params,
})
}
}
const MyQuery = new Query(myQuery)
Inject the token in a component and create the query params and an initial value.
function setup() {
const myQuery = inject(MyQuery)
const params = use(Function)
const result = myQuery(params, {
initialValue: null,
})
return {
result,
}
}
This returns a Value
that emits Resource
notifications.
QueryConfig
interface QueryConfig {
operator?: <T>() => OperatorFunction<Observable<T>, T> // defaults to switchMap
}
The default operator
used to map higher order observables can be overridden.
const MyQuery = new Query(myQuery, {
operator: concatMap,
})
QueryOptions
interface QueryOptions<T> {
initialValue: T
refetch?: Observable<any>[]
}
The query can be configured with refetch
to pull fresh data whenever another stream emits a value. If refetch
is given a Resource
observable,
it will wait until it is done
before it runs the query again.
function setup() {
const myQuery = inject(MyQuery)
const [mutation, mutate] = inject(MyMutation)
const fetch = use(Function)
const result = myQuery(fetch, {
initialValue: null,
refetch: [mutation],
})
}
Caching
Queries are memoized by stringifying arguments. Make sure the params passed to queries are serializable to JSON.
function setup() {
const myQuery = inject(MyQuery)
const fetch = use(Function)
const result = myQuery(fetch, {
initialValue: null
})
fetch([1, 2, 3]) // stringified to "[1, 2, 3]" to use as cache key
}
Mutation
Mutations are services created from factory functions that return another function that produces an observable stream.
function myMutation() {
const http = inject(HttpClient)
return function (params) {
return http.post(url, params)
}
}
const MyMutation = new Mutation(myMutation)
MutationConfig
interface MutationConfig {
operator?: <T>() => OperatorFunction<Observable<T>, T> // defaults to exhaust
}
The default operator
used to flatten higher order observables can be overridden.
const MyMutation = new Mutation(myMutation, {
operator: concat,
})
Returning mutation from a ViewDef
Use the array destructure pattern to obtain an Emitter
that can be used to trigger the mutation outside the ViewDef
factory.
function setup() {
const [mutation, mutate] = inject(MyMutation)
return {
mutation, // mutation status
mutate, // trigger mutation
}
}
@Component({
template: `
<spinner *ngIf="mutation.pending"></spinner>
<button (click)="mutate(params)">Mutate</button>
`,
})
export class MyComponent extends ViewDef(setup) {}
Resource
Interface that represents the state of a Query
or Mutation
interface Resource<T> {
value: T
error: unknown
pending: boolean
done: boolean
}
pending
is true if there are any active queries or mutations in the queue. done
is true when there are no more pending
transactions, until the next request is made. error
is set when an error is caught and resets when a new request is made.
cancel
Cancel pending queries
const getTodosByUserId = inject(GetTodosByUserId)
const todos = getTodosByUserId(userId)
cancel(todos)
Cancel pending mutations
const createTodo = inject(CreateTodo)
createTodo(todo)
cancel(createTodo)
invalidate
Invalidate a single query
const getTodosByUserId = inject(GetTodosByUserId)
const todos = getTodosByUserId(userId)
invalidate(todos)
Invalidate a single query with specific arguments
const getTodosByUserId = inject(GetTodosByUserId)
const todos = getTodosByUserId(userId)
invalidate(todos, "123")
Invalidate all queries by injection token
const getTodosByUserId = inject(GetTodosByUserId)
const todos = getTodosByUserId(userId)
invalidate(GetTodosByUserId)