Skip to content

Instantly share code, notes, and snippets.

@dhilgarth
Created December 18, 2018 08:46
Show Gist options
  • Save dhilgarth/783ed994be6e3af0c236fc36f327c9cd to your computer and use it in GitHub Desktop.
Save dhilgarth/783ed994be6e3af0c236fc36f327c9cd to your computer and use it in GitHub Desktop.
Passing meta data for interceptors to Angular HttpClient
export class LoadingInterceptorConfig {
constructor(public disableLoadingIndicator: boolean = false) {
}
}
import { HttpParams } from '@angular/common/http';
import { Type } from '@angular/core';
export interface IWithMetaData {
meta: IMetaData;
}
export interface IMetaData {
add<T>(data: T): void,
get<T>(type: Type<T>): T
}
interface IMetaDataInternal {
metaData: { [key: string]: any }
}
function add<T>(this: IMetaDataInternal, data: T): void {
this.metaData[data.constructor.name] = data;
}
function get<T>(this: IMetaDataInternal, type: Type<T>): T | undefined {
return this.metaData[type.name];
}
function hasMetaData(obj: any): obj is IWithMetaData {
return obj.meta && obj.meta.get && obj.meta.add;
}
export function getMetaData<T>(httpParams: HttpParams, type: Type<T>): T | undefined {
if (hasMetaData(httpParams)) {
return httpParams.meta.get(type);
}
return undefined;
}
export function withMetaData(httpParams: HttpParams): HttpParams & IWithMetaData {
const meta: IMetaData & IMetaDataInternal = {
add,
get,
metaData: {}
};
return Object.assign(httpParams, {meta});
}
import { getMetaData } from '../some/path/meta-data'
import { LoadingInterceptorConfig } from '../some/path/LoadingInterceptorConfig'
// ...
private overlayDisabled(req: HttpRequest<any>): boolean {
const config = getMetaData(req.params, LoadingInterceptorConfig);
return !!config && config.disableLoadingIndicator;
}
// ...
import { withMetaData } from '../some/path/meta-data'
import { LoadingInterceptorConfig } from '../some/path/LoadingInterceptorConfig'
// if you don't want to pass any other parameters:
const params = withMetaData(new HttpParams());
// if you have other parameters to pass:
const params = withMetaData(queryParameters);
params.meta.add(new LoadingInterceptorConfig(this.disableLoadingIndicator));
// Important: Don't perform any other operations on `params` after you added the metadata.
// As HttpParams is immutable, this would mean that our meta data would be lost.
this.httpClient.get<...>(`${this.basePath}/api/x/y`, {params});
@moshmage
Copy link

moshmage commented Jul 8, 2019

Just letting you know I ended up using this (with some slight modifications) until Angular gets its shit together with the shitty excuses.
Kudos, mate.

PS: I did have to make a facet to the HttpClient so I could use the meta params as a options,

// MyRequestOptions is a remnant from a preivous implementation that redeclared HttpRequestOptonArgs with more props

export interface MyRequestOptions {
  skipErrorHandler?: boolean;
  hideLoader?: boolean;
  external?: boolean;
  suppressError?: boolean;
  ignoreSomething?: boolean;
}

const LoadInterceptorMeta = (options: MyRequestOptions): {params: HttpParamsWithMeta} => {
  const params: HttpParamsWithMeta = withMeta();
  const {skipErrorHandler, suppressError, external, hideLoader, ignoreCrId} = options;

  [
    new LoaderInterceptorConfig(hideLoader),
    new ExernalInterceptorConfig(external),
    new ErrorInterceptorConfig(skipErrorHandler, suppressError),
    new SomethingInterceptorConfig(ignoreSomething)
  ].forEach(interceptor => params.meta.add(interceptor));

  return {params};
};

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

  constructor(private http: HttpClient) { }

  get(url: string, options: MyRequestOptions) {
    return this.http.get(url, LoadInterceptorMeta(options));
  }

@dhilgarth
Copy link
Author

Great, happy to hear it was helpful

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment