mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
feat(core): directive to add extra classes to components for m1 compat (#1498)
* feat(core): directive to add extra classes to components for m1 compatibility * fix e2e tests for menu
This commit is contained in:
@@ -15,7 +15,8 @@ describe('icon', () => {
|
||||
|
||||
it('should have the correct class when used', () => {
|
||||
testIcon.getAttribute('class').then((attr: string) => {
|
||||
expect(attr).toEqual('md-24 material-icons');
|
||||
expect(attr).toContain('md-24');
|
||||
expect(attr).toContain('material-icons');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ export class MenuPage {
|
||||
browser.get('/menu');
|
||||
}
|
||||
|
||||
menu() { return element(by.css('.md-menu')); }
|
||||
menu() { return element(by.css('.md-menu-panel')); }
|
||||
|
||||
start() { return element(by.id('start')); }
|
||||
|
||||
@@ -28,11 +28,11 @@ export class MenuPage {
|
||||
|
||||
combinedTrigger() { return element(by.id('combined-t')); }
|
||||
|
||||
beforeMenu() { return element(by.css('.md-menu.before')); }
|
||||
beforeMenu() { return element(by.css('.md-menu-panel.before')); }
|
||||
|
||||
aboveMenu() { return element(by.css('.md-menu.above')); }
|
||||
aboveMenu() { return element(by.css('.md-menu-panel.above')); }
|
||||
|
||||
combinedMenu() { return element(by.css('.md-menu.combined')); }
|
||||
combinedMenu() { return element(by.css('.md-menu-panel.combined')); }
|
||||
|
||||
// TODO(kara): move to common testing utility
|
||||
pressKey(key: any): void {
|
||||
@@ -46,7 +46,7 @@ export class MenuPage {
|
||||
}
|
||||
|
||||
expectMenuPresent(expected: boolean) {
|
||||
return browser.isElementPresent(by.css('.md-menu')).then((isPresent) => {
|
||||
return browser.isElementPresent(by.css('.md-menu-panel')).then(isPresent => {
|
||||
expect(isPresent).toBe(expected);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ describe('menu', () => {
|
||||
it('should mirror classes on host to menu template in overlay', () => {
|
||||
page.trigger().click();
|
||||
page.menu().getAttribute('class').then((classes) => {
|
||||
expect(classes).toEqual('md-menu custom');
|
||||
expect(classes).toEqual('md-menu-panel custom');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import {NgModule, ModuleWithProviders, Directive, Renderer, ElementRef} from '@angular/core';
|
||||
|
||||
|
||||
/** Selector that matches all elements that may have style collisions with material1. */
|
||||
export const ELEMENTS_SELECTOR = `
|
||||
md-card,
|
||||
md-card-actions,
|
||||
md-card-content,
|
||||
md-card-footer,
|
||||
md-card-header,
|
||||
md-card-subtitle,
|
||||
md-card-title,
|
||||
md-card-title-group,
|
||||
md-checkbox,
|
||||
md-dialog-container,
|
||||
md-divider,
|
||||
md-grid-list,
|
||||
md-grid-tile,
|
||||
md-grid-tile-footer,
|
||||
md-grid-tile-header,
|
||||
md-hint,
|
||||
md-icon,
|
||||
md-ink-bar,
|
||||
md-input,
|
||||
md-list,
|
||||
md-list-item,
|
||||
md-menu,
|
||||
md-nav-list,
|
||||
md-placeholder,
|
||||
md-progress-bar,
|
||||
md-progress-circle,
|
||||
md-radio-button,
|
||||
md-radio-group,
|
||||
md-select,
|
||||
md-sidenav,
|
||||
md-slider,
|
||||
md-spinner,
|
||||
md-tab,
|
||||
md-toolbar
|
||||
`;
|
||||
|
||||
/**
|
||||
* Directive to apply to all material2 components that use the same element name as a
|
||||
* component in material2. It does two things:
|
||||
* 1) Adds the css class "md2" to the host element so that material1 can use this class with a
|
||||
* :not() in order to avoid affecting material2 elements.
|
||||
* 2) Adds a css class to the element that is identical to the element's tag. E.g., the element
|
||||
* `<md-card>` would be given a css class `md-card`. This is done so that material2 can style
|
||||
* only these classes instead of defining element rules that would affect material1 components.
|
||||
*/
|
||||
@Directive({
|
||||
selector: ELEMENTS_SELECTOR,
|
||||
})
|
||||
export class StyleCompatibility {
|
||||
constructor(renderer: Renderer, elementRef: ElementRef) {
|
||||
const element = elementRef.nativeElement as Node;
|
||||
renderer.setElementClass(element, 'md2', true);
|
||||
renderer.setElementClass(element, element.nodeName.toLowerCase(), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [StyleCompatibility],
|
||||
exports: [StyleCompatibility],
|
||||
})
|
||||
export class StyleCompatibilityModule {
|
||||
static forRoot(): ModuleWithProviders {
|
||||
return {
|
||||
ngModule: StyleCompatibilityModule,
|
||||
providers: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -79,6 +79,8 @@ export {ComponentType} from './overlay/generic-component-type';
|
||||
// Keybindings
|
||||
export * from './keyboard/keycodes';
|
||||
|
||||
export * from './compatibility/style-compatibility';
|
||||
|
||||
// Animation
|
||||
export * from './animation/animation';
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
$background: map-get($theme, background);
|
||||
$foreground: map-get($theme, foreground);
|
||||
|
||||
.md-menu {
|
||||
.md-menu-panel {
|
||||
background: md-color($background, 'card');
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div class="md-menu" [ngClass]="_classList" (click)="_emitCloseEvent()" (keydown)="_handleKeydown($event)">
|
||||
<div class="md-menu-panel" [ngClass]="_classList"
|
||||
(click)="_emitCloseEvent()" (keydown)="_handleKeydown($event)">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
</template>
|
||||
<div class="md-menu-click-catcher" *ngIf="_showClickCatcher" (click)="_emitCloseEvent()"></div>
|
||||
<div class="md-menu-click-catcher" *ngIf="_showClickCatcher" (click)="_emitCloseEvent()"></div>
|
||||
|
||||
@@ -16,7 +16,7 @@ $md-menu-font-size: 16px !default;
|
||||
$md-menu-side-padding: 16px !default;
|
||||
$md-menu-vertical-padding: 8px !default;
|
||||
|
||||
.md-menu {
|
||||
.md-menu-panel {
|
||||
@include md-elevation(2);
|
||||
min-width: $md-menu-overlay-min-width;
|
||||
max-width: $md-menu-overlay-max-width;
|
||||
|
||||
@@ -18,13 +18,13 @@ describe('MdMenu', () => {
|
||||
it('should open the menu as an idempotent operation', () => {
|
||||
let fixture = TestBed.createComponent(SimpleMenu);
|
||||
fixture.detectChanges();
|
||||
let menu = fixture.debugElement.query(By.css('.md-menu'));
|
||||
let menu = fixture.debugElement.query(By.css('.md-menu-panel'));
|
||||
expect(menu).toBe(null);
|
||||
expect(() => {
|
||||
fixture.componentInstance.trigger.openMenu();
|
||||
fixture.componentInstance.trigger.openMenu();
|
||||
|
||||
menu = fixture.debugElement.query(By.css('.md-menu'));
|
||||
menu = fixture.debugElement.query(By.css('.md-menu-panel'));
|
||||
expect(menu.nativeElement.innerHTML.trim()).toEqual('Content');
|
||||
}).not.toThrowError();
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
PortalModule,
|
||||
OverlayModule,
|
||||
A11yModule,
|
||||
StyleCompatibilityModule,
|
||||
} from './core/index';
|
||||
|
||||
import {MdButtonToggleModule} from './button-toggle/index';
|
||||
@@ -58,6 +59,7 @@ const MATERIAL_MODULES = [
|
||||
PortalModule,
|
||||
RtlModule,
|
||||
A11yModule,
|
||||
StyleCompatibilityModule,
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
@@ -90,6 +92,7 @@ const MATERIAL_MODULES = [
|
||||
MdSnackBarModule.forRoot(),
|
||||
MdTooltipModule.forRoot(),
|
||||
OverlayModule.forRoot(),
|
||||
StyleCompatibilityModule.forRoot(),
|
||||
],
|
||||
exports: MATERIAL_MODULES,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user