mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
chore: remove dom projection service (#3656)
Gets rid of the `DomProjection` service which isn't being used anymore. Fixes #3649.
This commit is contained in:
committed by
Jeremy Elbourn
parent
2dbf87c7a5
commit
5c1474d610
@@ -38,7 +38,6 @@ import {SnackBarDemo} from './snack-bar/snack-bar-demo';
|
||||
import {PortalDemo, ScienceJoke} from './portal/portal-demo';
|
||||
import {MenuDemo} from './menu/menu-demo';
|
||||
import {TabsDemo, SunnyTabContent, RainyTabContent, FoggyTabContent} from './tabs/tabs-demo';
|
||||
import {ProjectionDemo, ProjectionTestComponent} from './projection/projection-demo';
|
||||
import {PlatformDemo} from './platform/platform-demo';
|
||||
import {AutocompleteDemo} from './autocomplete/autocomplete-demo';
|
||||
import {InputDemo} from './input/input-demo';
|
||||
@@ -81,8 +80,6 @@ import {StyleDemo} from './style/style-demo';
|
||||
PortalDemo,
|
||||
ProgressBarDemo,
|
||||
ProgressSpinnerDemo,
|
||||
ProjectionDemo,
|
||||
ProjectionTestComponent,
|
||||
RadioDemo,
|
||||
RippleDemo,
|
||||
RotiniPanel,
|
||||
|
||||
@@ -36,7 +36,6 @@ export class DemoApp {
|
||||
{name: 'Live Announcer', route: 'live-announcer'},
|
||||
{name: 'Overlay', route: 'overlay'},
|
||||
{name: 'Portal', route: 'portal'},
|
||||
{name: 'Projection', route: 'projection'},
|
||||
{name: 'Progress Bar', route: 'progress-bar'},
|
||||
{name: 'Progress Spinner', route: 'progress-spinner'},
|
||||
{name: 'Radio', route: 'radio'},
|
||||
|
||||
@@ -27,7 +27,6 @@ import {RippleDemo} from '../ripple/ripple-demo';
|
||||
import {DialogDemo} from '../dialog/dialog-demo';
|
||||
import {TooltipDemo} from '../tooltip/tooltip-demo';
|
||||
import {SnackBarDemo} from '../snack-bar/snack-bar-demo';
|
||||
import {ProjectionDemo} from '../projection/projection-demo';
|
||||
import {TABS_DEMO_ROUTES} from '../tabs/routes';
|
||||
import {PlatformDemo} from '../platform/platform-demo';
|
||||
import {AutocompleteDemo} from '../autocomplete/autocomplete-demo';
|
||||
@@ -48,7 +47,6 @@ export const DEMO_APP_ROUTES: Routes = [
|
||||
{path: 'progress-spinner', component: ProgressSpinnerDemo},
|
||||
{path: 'progress-bar', component: ProgressBarDemo},
|
||||
{path: 'portal', component: PortalDemo},
|
||||
{path: 'projection', component: ProjectionDemo},
|
||||
{path: 'overlay', component: OverlayDemo},
|
||||
{path: 'checkbox', component: CheckboxDemo},
|
||||
{path: 'input', component: InputDemo},
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
import {Component, ViewChild, ElementRef, OnInit, Input} from '@angular/core';
|
||||
import {DomProjectionHost, DomProjection} from '@angular/material';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: '[projection-test]',
|
||||
template: `
|
||||
<div class="demo-outer {{cssClass}}">
|
||||
Before
|
||||
<cdk-dom-projection-host><ng-content></ng-content></cdk-dom-projection-host>
|
||||
After
|
||||
</div>
|
||||
`,
|
||||
styles: [`
|
||||
.demo-outer {
|
||||
background-color: #663399;
|
||||
}
|
||||
`]
|
||||
})
|
||||
export class ProjectionTestComponent implements OnInit {
|
||||
@ViewChild(DomProjectionHost) _host: DomProjectionHost;
|
||||
@Input('class') cssClass: any;
|
||||
|
||||
constructor(private _projection: DomProjection, private _ref: ElementRef) {}
|
||||
|
||||
ngOnInit() {
|
||||
this._projection.project(this._ref, this._host);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'projection-app',
|
||||
template: `
|
||||
<div projection-test class="demo-inner">
|
||||
<div class="content">Content: {{binding}}</div>
|
||||
</div>
|
||||
<br/>
|
||||
<input projection-test [(ngModel)]="binding" [class]="binding" [ngClass]="{'blue': true}">
|
||||
<input [(ngModel)]="binding" class="my-class" [ngClass]="{'blue': true}">
|
||||
`,
|
||||
styles: [`
|
||||
.demo-inner {
|
||||
background-color: #DAA520;
|
||||
}
|
||||
`]
|
||||
})
|
||||
export class ProjectionDemo {
|
||||
binding: string = 'abc';
|
||||
}
|
||||
@@ -33,9 +33,6 @@ export {
|
||||
} from './portal/portal-directives';
|
||||
export {DomPortalHost} from './portal/dom-portal-host';
|
||||
|
||||
// Projection
|
||||
export * from './projection/projection';
|
||||
|
||||
// Platform
|
||||
export * from './platform/index';
|
||||
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
import {TestBed, async} from '@angular/core/testing';
|
||||
import {
|
||||
NgModule,
|
||||
Component,
|
||||
ViewChild,
|
||||
ElementRef,
|
||||
} from '@angular/core';
|
||||
import {ProjectionModule, DomProjection, DomProjectionHost} from './projection';
|
||||
|
||||
|
||||
describe('Projection', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ProjectionModule.forRoot(), ProjectionTestModule],
|
||||
});
|
||||
|
||||
TestBed.compileComponents();
|
||||
}));
|
||||
|
||||
it('should project properly', async(() => {
|
||||
const fixture = TestBed.createComponent(ProjectionTestApp);
|
||||
const appEl: HTMLDivElement = fixture.nativeElement;
|
||||
const outerDivEl = appEl.querySelector('.outer');
|
||||
const innerDivEl = appEl.querySelector('.inner');
|
||||
|
||||
// Expect the reverse of the tests down there.
|
||||
expect(appEl.querySelector('cdk-dom-projection-host')).not.toBeNull();
|
||||
expect(outerDivEl.querySelector('.inner')).not.toBe(innerDivEl);
|
||||
|
||||
const innerHtml = appEl.innerHTML;
|
||||
|
||||
// Trigger OnInit (and thus the projection).
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(appEl.innerHTML).not.toEqual(innerHtml);
|
||||
|
||||
// Assert `<cdk-dom-projection-host>` is not in the DOM anymore.
|
||||
expect(appEl.querySelector('cdk-dom-projection-host')).toBeNull();
|
||||
|
||||
// Assert the outerDiv contains the innerDiv.
|
||||
expect(outerDivEl.querySelector('.inner')).toBe(innerDivEl);
|
||||
|
||||
// Assert the innerDiv contains the content.
|
||||
expect(innerDivEl.querySelector('.content')).not.toBeNull();
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
/** Test-bed component that contains a projection. */
|
||||
@Component({
|
||||
selector: '[projection-test]',
|
||||
template: `
|
||||
<div class="outer">
|
||||
<cdk-dom-projection-host><ng-content></ng-content></cdk-dom-projection-host>
|
||||
</div>
|
||||
`,
|
||||
})
|
||||
class ProjectionTestComponent {
|
||||
@ViewChild(DomProjectionHost) _host: DomProjectionHost;
|
||||
|
||||
constructor(private _projection: DomProjection, private _ref: ElementRef) {}
|
||||
ngOnInit() { this._projection.project(this._ref, this._host); }
|
||||
}
|
||||
|
||||
|
||||
/** Test-bed component that contains a portal host and a couple of template portals. */
|
||||
@Component({
|
||||
selector: 'projection-app',
|
||||
template: `
|
||||
<div projection-test class="inner">
|
||||
<div class="content"></div>
|
||||
</div>
|
||||
`,
|
||||
})
|
||||
class ProjectionTestApp {
|
||||
}
|
||||
|
||||
|
||||
|
||||
const TEST_COMPONENTS = [ProjectionTestApp, ProjectionTestComponent];
|
||||
@NgModule({
|
||||
imports: [ProjectionModule],
|
||||
exports: TEST_COMPONENTS,
|
||||
declarations: TEST_COMPONENTS,
|
||||
entryComponents: TEST_COMPONENTS,
|
||||
})
|
||||
class ProjectionTestModule { }
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
import {Injectable, Directive, ModuleWithProviders, NgModule, ElementRef} from '@angular/core';
|
||||
|
||||
|
||||
// "Polyfill" for `Node.replaceWith()`.
|
||||
// cf. https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/replaceWith
|
||||
function _replaceWith(toReplaceEl: HTMLElement, otherEl: HTMLElement) {
|
||||
toReplaceEl.parentElement.replaceChild(otherEl, toReplaceEl);
|
||||
}
|
||||
|
||||
/** @docs-private */
|
||||
@Directive({
|
||||
selector: 'cdk-dom-projection-host'
|
||||
})
|
||||
export class DomProjectionHost {
|
||||
constructor(public ref: ElementRef) {}
|
||||
}
|
||||
|
||||
|
||||
/** @docs-private */
|
||||
@Injectable()
|
||||
export class DomProjection {
|
||||
/**
|
||||
* Project an element into a host element.
|
||||
* Replace a host element by another element. This also replaces the children of the element
|
||||
* by the children of the host.
|
||||
*
|
||||
* It should be used like this:
|
||||
*
|
||||
* ```
|
||||
* @Component({
|
||||
* template: `<div>
|
||||
* <cdk-dom-projection-host>
|
||||
* <div>other</div>
|
||||
* <ng-content></ng-content>
|
||||
* </cdk-dom-projection-host>
|
||||
* </div>`
|
||||
* })
|
||||
* class Cmpt {
|
||||
* constructor(private _projector: DomProjection, private _el: ElementRef) {}
|
||||
* ngOnInit() { this._projector.project(this._el, this._projector); }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* This component will move the content of the element it's applied to in the outer div. Because
|
||||
* `project()` also move the children of the host inside the projected element, the element will
|
||||
* contain the `<div>other</div>` HTML as well as its own children.
|
||||
*
|
||||
* Note: without `<ng-content></ng-content>` the projection will project an empty element.
|
||||
*
|
||||
* @param ref ElementRef to be projected.
|
||||
* @param host Projection host into which to project the `ElementRef`.
|
||||
*/
|
||||
project(ref: ElementRef, host: DomProjectionHost): void {
|
||||
const projectedEl = ref.nativeElement;
|
||||
const hostEl = host.ref.nativeElement;
|
||||
const childNodes = projectedEl.childNodes;
|
||||
let child = childNodes[0];
|
||||
|
||||
// We hoist all of the projected element's children out into the projected elements position
|
||||
// because we *only* want to move the projected element and not its children.
|
||||
_replaceWith(projectedEl, child);
|
||||
let l = childNodes.length;
|
||||
while (l--) {
|
||||
child.parentNode.insertBefore(childNodes[0], child.nextSibling);
|
||||
child = child.nextSibling; // nextSibling is now the childNodes[0].
|
||||
}
|
||||
|
||||
// Insert all host children under the projectedEl, then replace host by component.
|
||||
l = hostEl.childNodes.length;
|
||||
while (l--) {
|
||||
projectedEl.appendChild(hostEl.childNodes[0]);
|
||||
}
|
||||
_replaceWith(hostEl, projectedEl);
|
||||
|
||||
// At this point the host is replaced by the component. Nothing else to be done.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @docs-private */
|
||||
@NgModule({
|
||||
exports: [DomProjectionHost],
|
||||
declarations: [DomProjectionHost],
|
||||
providers: [DomProjection],
|
||||
})
|
||||
export class ProjectionModule {
|
||||
/** @deprecated */
|
||||
static forRoot(): ModuleWithProviders {
|
||||
return {
|
||||
ngModule: ProjectionModule,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
PortalModule,
|
||||
OverlayModule,
|
||||
A11yModule,
|
||||
ProjectionModule,
|
||||
CompatibilityModule,
|
||||
} from './core/index';
|
||||
|
||||
@@ -68,7 +67,6 @@ const MATERIAL_MODULES = [
|
||||
StyleModule,
|
||||
A11yModule,
|
||||
PlatformModule,
|
||||
ProjectionModule,
|
||||
CompatibilityModule,
|
||||
ObserveContentModule
|
||||
];
|
||||
@@ -91,7 +89,6 @@ const MATERIAL_MODULES = [
|
||||
MdTabsModule.forRoot(),
|
||||
MdToolbarModule.forRoot(),
|
||||
PortalModule.forRoot(),
|
||||
ProjectionModule.forRoot(),
|
||||
RtlModule.forRoot(),
|
||||
ObserveContentModule.forRoot(),
|
||||
|
||||
|
||||
Reference in New Issue
Block a user