mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
feat: remove hard dependency on @angular/http (#3792)
* Makes `@angular/http` an optional dependency since it is only being used by the icon module. An error will be thrown only if the user runs into something that requires the `HttpModule`. * Moves the various icon error classes into `icon-errors.ts`. * Moves the icon registry provider next to the registry itself, instead of in the same file as the icon directive. Fixes #2616.
This commit is contained in:
committed by
Andrew Seguin
parent
2481ee398b
commit
b011b45ac8
@@ -1,6 +1,4 @@
|
||||
import {
|
||||
Response,
|
||||
ResponseOptions} from '@angular/http';
|
||||
import {Response, ResponseOptions} from '@angular/http';
|
||||
|
||||
/**
|
||||
* Fake URLs and associated SVG documents used by tests.
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import {MdError} from '../core';
|
||||
|
||||
/**
|
||||
* Exception thrown when attempting to load an icon with a name that cannot be found.
|
||||
* @docs-private
|
||||
*/
|
||||
export class MdIconNameNotFoundError extends MdError {
|
||||
constructor(iconName: string) {
|
||||
super(`Unable to find icon with the name "${iconName}"`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown when attempting to load SVG content that does not contain the expected
|
||||
* <svg> tag.
|
||||
* @docs-private
|
||||
*/
|
||||
export class MdIconSvgTagNotFoundError extends MdError {
|
||||
constructor() {
|
||||
super('<svg> tag not found');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown when the consumer attempts to use `<md-icon>` without including @angular/http.
|
||||
* @docs-private
|
||||
*/
|
||||
export class MdIconNoHttpProviderError extends MdError {
|
||||
constructor() {
|
||||
super('Could not find Http provider for use with Angular Material icons. ' +
|
||||
'Please include the HttpModule from @angular/http in your app imports.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown when an invalid icon name is passed to an md-icon component.
|
||||
* @docs-private
|
||||
*/
|
||||
export class MdIconInvalidNameError extends MdError {
|
||||
constructor(iconName: string) {
|
||||
super(`Invalid icon name: "${iconName}"`);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
import {Injectable, SecurityContext} from '@angular/core';
|
||||
import {Injectable, SecurityContext, Optional, SkipSelf} from '@angular/core';
|
||||
import {SafeResourceUrl, DomSanitizer} from '@angular/platform-browser';
|
||||
import {Http} from '@angular/http';
|
||||
import {MdError} from '../core';
|
||||
import {Observable} from 'rxjs/Observable';
|
||||
import {
|
||||
MdIconNameNotFoundError,
|
||||
MdIconSvgTagNotFoundError,
|
||||
MdIconNoHttpProviderError,
|
||||
} from './icon-errors';
|
||||
import 'rxjs/add/observable/forkJoin';
|
||||
import 'rxjs/add/observable/of';
|
||||
import 'rxjs/add/operator/map';
|
||||
@@ -14,27 +18,6 @@ import 'rxjs/add/operator/catch';
|
||||
import 'rxjs/add/observable/throw';
|
||||
|
||||
|
||||
/**
|
||||
* Exception thrown when attempting to load an icon with a name that cannot be found.
|
||||
* @docs-private
|
||||
*/
|
||||
export class MdIconNameNotFoundError extends MdError {
|
||||
constructor(iconName: string) {
|
||||
super(`Unable to find icon with the name "${iconName}"`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown when attempting to load SVG content that does not contain the expected
|
||||
* <svg> tag.
|
||||
* @docs-private
|
||||
*/
|
||||
export class MdIconSvgTagNotFoundError extends MdError {
|
||||
constructor() {
|
||||
super('<svg> tag not found');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration for an icon, including the URL and possibly the cached SVG element.
|
||||
* @docs-private
|
||||
@@ -44,9 +27,6 @@ class SvgIconConfig {
|
||||
constructor(public url: SafeResourceUrl) { }
|
||||
}
|
||||
|
||||
/** Returns the cache key to use for an icon namespace and name. */
|
||||
const iconKey = (namespace: string, name: string) => namespace + ':' + name;
|
||||
|
||||
/**
|
||||
* Service to register and display icons used by the <md-icon> component.
|
||||
* - Registers icon URLs by namespace and name.
|
||||
@@ -83,7 +63,7 @@ export class MdIconRegistry {
|
||||
*/
|
||||
private _defaultFontSetClass = 'material-icons';
|
||||
|
||||
constructor(private _http: Http, private _sanitizer: DomSanitizer) {}
|
||||
constructor(@Optional() private _http: Http, private _sanitizer: DomSanitizer) {}
|
||||
|
||||
/**
|
||||
* Registers an icon by URL in the default namespace.
|
||||
@@ -386,7 +366,11 @@ export class MdIconRegistry {
|
||||
* cached, so future calls with the same URL may not cause another HTTP request.
|
||||
*/
|
||||
private _fetchUrl(safeUrl: SafeResourceUrl): Observable<string> {
|
||||
let url = this._sanitizer.sanitize(SecurityContext.RESOURCE_URL, safeUrl);
|
||||
if (!this._http) {
|
||||
throw new MdIconNoHttpProviderError();
|
||||
}
|
||||
|
||||
const url = this._sanitizer.sanitize(SecurityContext.RESOURCE_URL, safeUrl);
|
||||
|
||||
// Store in-progress fetches to avoid sending a duplicate request for a URL when there is
|
||||
// already a request in progress for that URL. It's necessary to call share() on the
|
||||
@@ -408,8 +392,24 @@ export class MdIconRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
export function ICON_REGISTRY_PROVIDER_FACTORY(
|
||||
parentRegistry: MdIconRegistry, http: Http, sanitizer: DomSanitizer) {
|
||||
return parentRegistry || new MdIconRegistry(http, sanitizer);
|
||||
}
|
||||
|
||||
export const ICON_REGISTRY_PROVIDER = {
|
||||
// If there is already an MdIconRegistry available, use that. Otherwise, provide a new one.
|
||||
provide: MdIconRegistry,
|
||||
deps: [[new Optional(), new SkipSelf(), MdIconRegistry], [new Optional(), Http], DomSanitizer],
|
||||
useFactory: ICON_REGISTRY_PROVIDER_FACTORY
|
||||
};
|
||||
|
||||
/** Clones an SVGElement while preserving type information. */
|
||||
function cloneSvg(svg: SVGElement): SVGElement {
|
||||
return svg.cloneNode(true) as SVGElement;
|
||||
}
|
||||
|
||||
/** Returns the cache key to use for an icon namespace and name. */
|
||||
function iconKey(namespace: string, name: string) {
|
||||
return namespace + ':' + name;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import {inject, async, TestBed} from '@angular/core/testing';
|
||||
import {SafeResourceUrl, DomSanitizer} from '@angular/platform-browser';
|
||||
import {XHRBackend} from '@angular/http';
|
||||
import {HttpModule, XHRBackend} from '@angular/http';
|
||||
import {MockBackend} from '@angular/http/testing';
|
||||
import {Component} from '@angular/core';
|
||||
import {MdIconModule} from './index';
|
||||
import {MdIconRegistry} from './icon-registry';
|
||||
import {MdIconNoHttpProviderError} from './icon-errors';
|
||||
import {getFakeSvgHttpResponse} from './fake-svgs';
|
||||
|
||||
|
||||
@@ -36,7 +37,7 @@ describe('MdIcon', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [MdIconModule],
|
||||
imports: [HttpModule, MdIconModule],
|
||||
declarations: [
|
||||
MdIconColorTestApp,
|
||||
MdIconLigatureTestApp,
|
||||
@@ -394,6 +395,37 @@ describe('MdIcon', () => {
|
||||
});
|
||||
|
||||
|
||||
describe('MdIcon without HttpModule', () => {
|
||||
let mdIconRegistry: MdIconRegistry;
|
||||
let sanitizer: DomSanitizer;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [MdIconModule],
|
||||
declarations: [MdIconFromSvgNameTestApp],
|
||||
});
|
||||
|
||||
TestBed.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(inject([MdIconRegistry, DomSanitizer], (mir: MdIconRegistry, ds: DomSanitizer) => {
|
||||
mdIconRegistry = mir;
|
||||
sanitizer = ds;
|
||||
}));
|
||||
|
||||
it('should throw an error when trying to load a remote icon', async() => {
|
||||
expect(() => {
|
||||
mdIconRegistry.addSvgIcon('fido', sanitizer.bypassSecurityTrustResourceUrl('dog.svg'));
|
||||
|
||||
let fixture = TestBed.createComponent(MdIconFromSvgNameTestApp);
|
||||
|
||||
fixture.componentInstance.iconName = 'fido';
|
||||
fixture.detectChanges();
|
||||
}).toThrowError(MdIconNoHttpProviderError);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/** Test components that contain an MdIcon. */
|
||||
@Component({template: `<md-icon>{{iconName}}</md-icon>`})
|
||||
class MdIconLigatureTestApp {
|
||||
|
||||
+2
-24
@@ -9,20 +9,10 @@ import {
|
||||
SimpleChange,
|
||||
ViewEncapsulation,
|
||||
AfterViewChecked,
|
||||
Optional,
|
||||
SkipSelf,
|
||||
} from '@angular/core';
|
||||
import {Http} from '@angular/http';
|
||||
import {DomSanitizer} from '@angular/platform-browser';
|
||||
import {MdError} from '../core';
|
||||
import {MdIconRegistry, MdIconNameNotFoundError} from './icon-registry';
|
||||
import {MdIconRegistry} from './icon-registry';
|
||||
import {MdIconNameNotFoundError, MdIconInvalidNameError} from './icon-errors';
|
||||
|
||||
/** Exception thrown when an invalid icon name is passed to an md-icon component. */
|
||||
export class MdIconInvalidNameError extends MdError {
|
||||
constructor(iconName: string) {
|
||||
super(`Invalid icon name: "${iconName}"`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Component to display an icon. It can be used in the following ways:
|
||||
@@ -250,15 +240,3 @@ export class MdIcon implements OnChanges, OnInit, AfterViewChecked {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function ICON_REGISTRY_PROVIDER_FACTORY(
|
||||
parentRegistry: MdIconRegistry, http: Http, sanitizer: DomSanitizer) {
|
||||
return parentRegistry || new MdIconRegistry(http, sanitizer);
|
||||
}
|
||||
|
||||
export const ICON_REGISTRY_PROVIDER = {
|
||||
// If there is already an MdIconRegistry available, use that. Otherwise, provide a new one.
|
||||
provide: MdIconRegistry,
|
||||
deps: [[new Optional(), new SkipSelf(), MdIconRegistry], Http, DomSanitizer],
|
||||
useFactory: ICON_REGISTRY_PROVIDER_FACTORY,
|
||||
};
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import {NgModule} from '@angular/core';
|
||||
import {HttpModule} from '@angular/http';
|
||||
import {MdCommonModule} from '../core';
|
||||
import {MdIcon, ICON_REGISTRY_PROVIDER} from './icon';
|
||||
import {MdIcon} from './icon';
|
||||
import {ICON_REGISTRY_PROVIDER} from './icon-registry';
|
||||
|
||||
|
||||
@NgModule({
|
||||
imports: [HttpModule, MdCommonModule],
|
||||
imports: [MdCommonModule],
|
||||
exports: [MdIcon, MdCommonModule],
|
||||
declarations: [MdIcon],
|
||||
providers: [ICON_REGISTRY_PROVIDER],
|
||||
@@ -14,4 +14,5 @@ export class MdIconModule {}
|
||||
|
||||
|
||||
export * from './icon';
|
||||
export {MdIconRegistry} from './icon-registry';
|
||||
export * from './icon-errors';
|
||||
export * from './icon-registry';
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
"homepage": "https://github.com/angular/material2#readme",
|
||||
"peerDependencies": {
|
||||
"@angular/core": "^4.0.0",
|
||||
"@angular/common": "^4.0.0",
|
||||
"@angular/http": "^4.0.0"
|
||||
"@angular/common": "^4.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user