Skip to content
This repository was archived by the owner on Jan 6, 2025. It is now read-only.

fix: apply correct RTL margins #527

Merged
merged 1 commit into from
Feb 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/demo-app/app/docs-layout/_module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {Component} from '@angular/core';
<demo-flex-attribute-values class="small-demo"></demo-flex-attribute-values>
<demo-flex-offset-values class="small-demo"></demo-flex-offset-values>
<demo-flex-align-self class="small-demo"></demo-flex-align-self>
<demo-layout-row-direction class="small-demo"></demo-layout-row-direction>
`
})
export class DemosLayoutAPI {
Expand All @@ -26,6 +27,7 @@ import {DemoFlexRowFillWrap} from './flexRowFillWrap.demo';
import {DemoFlexAttributeValues} from './flexOtherValues.demo';
import {DemoFlexOffsetValues} from './flexOffetValues.demo';
import {DemoFlexAlignSelf} from './FlexAlignSelf.demo';
import {DemoLayoutRowDirection} from './layoutRowWithDirection.demo';

@NgModule({
declarations: [
Expand All @@ -37,7 +39,8 @@ import {DemoFlexAlignSelf} from './FlexAlignSelf.demo';
DemoFlexRowFillWrap,
DemoFlexAttributeValues,
DemoFlexOffsetValues,
DemoFlexAlignSelf
DemoFlexAlignSelf,
DemoLayoutRowDirection,
],
imports: [
SharedModule,
Expand Down
42 changes: 42 additions & 0 deletions src/demo-app/app/docs-layout/layoutRowWithDirection.demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {Component} from '@angular/core';

@Component({
moduleId: module.id,
selector: 'demo-layout-row-direction',
template: `
<mat-card class="card-demo">
<mat-card-title>Direction support for RTL</mat-card-title>
<mat-card-subtitle>
Simple row using layout gap and flex offset to demonstrate changes
in layout direction between rtl and ltr.
</mat-card-subtitle>
<mat-card-content fxLayout="column" fxLayoutGap="8px">
<div>
<button (click)="toggleDirection()" mat-raised-button>
Toggle direction
</button>
</div>
<div class="containerX">
<div fxLayout="row" class="colored box" fxLayoutGap="20px"
[dir]="direction" fxFlex>
<div fxFlexOffset="20px">item 1</div>
<div>item 2</div>
<div>item 3</div>
</div>
</div>
</mat-card-content>
<mat-card-footer>
<div class="hint">
&lt;div dir="{{ direction }}" fxLayoutGap="20px"&gt;
</div>
</mat-card-footer>
</mat-card>
`
})
export class DemoLayoutRowDirection {
direction = 'ltr';

toggleDirection() {
this.direction = this.direction === 'ltr' ? 'rtl' : 'ltr';
}
}
44 changes: 43 additions & 1 deletion src/lib/api/flexbox/flex-offset.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {Component} from '@angular/core';
import {CommonModule} from '@angular/common';
import {ComponentFixture, TestBed} from '@angular/core/testing';

import {DIR_DOCUMENT} from '../../bidi/directionality';
import {DEFAULT_BREAKPOINTS_PROVIDER} from '../../media-query/breakpoints/break-points-provider';
import {BreakPointRegistry} from '../../media-query/breakpoints/break-point-registry';
import {MockMatchMedia} from '../../media-query/mock/mock-match-media';
Expand All @@ -27,20 +28,23 @@ import {
describe('flex directive', () => {
let fixture: ComponentFixture<any>;
let expectDOMFrom = makeExpectDOMFrom(() => TestFlexComponent);
let fakeDocument: {body: {dir?: string}, documentElement: {dir?: string}};
let componentWithTemplate = (template: string) => {
fixture = makeCreateTestComponent(() => TestFlexComponent)(template);
};

beforeEach(() => {
jasmine.addMatchers(customMatchers);
fakeDocument = {body: {}, documentElement: {}};

// Configure testbed to prepare services
TestBed.configureTestingModule({
imports: [CommonModule, FlexLayoutModule],
declarations: [TestFlexComponent],
providers: [
BreakPointRegistry, DEFAULT_BREAKPOINTS_PROVIDER,
{provide: MatchMedia, useClass: MockMatchMedia}
{provide: MatchMedia, useClass: MockMatchMedia},
{provide: DIR_DOCUMENT, useValue: fakeDocument}
]
});
});
Expand Down Expand Up @@ -134,6 +138,44 @@ describe('flex directive', () => {
});
});

it('should set margin-right for rtl layouts on document body', () => {
fakeDocument.body.dir = 'rtl';
componentWithTemplate(`
<div fxLayout='row' class='test'>
<div fxFlex='30px' fxFlexOffset='17px'> </div>
</div>
`);
fixture.detectChanges();

let element = queryFor(fixture, '[fxFlex]')[0].nativeElement;
expect(element).toHaveStyle({'margin-right': '17px'});
});

it('should set margin-right for rtl layouts on documentElement', () => {
fakeDocument.documentElement.dir = 'rtl';
componentWithTemplate(`
<div fxLayout='row' class='test'>
<div fxFlex='30px' fxFlexOffset='17px'> </div>
</div>
`);
fixture.detectChanges();

let element = queryFor(fixture, '[fxFlex]')[0].nativeElement;
expect(element).toHaveStyle({'margin-right': '17px'});
});

it('should set margin-left for ltr layouts', () => {
componentWithTemplate(`
<div fxLayout='row' class='test'>
<div fxFlex='30px' fxFlexOffset='17px'> </div>
</div>
`);
fixture.detectChanges();

let element = queryFor(fixture, '[fxFlex]')[0].nativeElement;
expect(element).toHaveStyle({'margin-left': '17px'});
});

});

});
Expand Down
15 changes: 13 additions & 2 deletions src/lib/api/flexbox/flex-offset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
import {Subscription} from 'rxjs/Subscription';

import {BaseFxDirective} from '../core/base';
import {Directionality} from '../../bidi/directionality';
import {MediaChange} from '../../media-query/media-change';
import {MediaMonitor} from '../../media-query/media-monitor';
import {LayoutDirective} from './layout';
Expand All @@ -39,6 +40,7 @@ import {isFlowHorizontal} from '../../utils/layout-validator';
[fxFlexOffset.gt-xs], [fxFlexOffset.gt-sm], [fxFlexOffset.gt-md], [fxFlexOffset.gt-lg]
`})
export class FlexOffsetDirective extends BaseFxDirective implements OnInit, OnChanges, OnDestroy {
private _directionWatcher: Subscription;

/* tslint:disable */
@Input('fxFlexOffset') set offset(val) { this._cacheInput('offset', val); }
Expand All @@ -63,8 +65,11 @@ export class FlexOffsetDirective extends BaseFxDirective implements OnInit, OnCh
elRef: ElementRef,
renderer: Renderer2,
@Optional() @SkipSelf() protected _container: LayoutDirective,
@Inject(PLATFORM_ID) platformId: Object) {
@Inject(PLATFORM_ID) platformId: Object,
private _directionality: Directionality) {
super(monitor, elRef, renderer, platformId);
this._directionWatcher =
this._directionality.change.subscribe(this._updateWithValue.bind(this));


this.watchParentFlow();
Expand All @@ -91,6 +96,9 @@ export class FlexOffsetDirective extends BaseFxDirective implements OnInit, OnCh
if (this._layoutWatcher) {
this._layoutWatcher.unsubscribe();
}
if (this._directionWatcher) {
this._directionWatcher.unsubscribe();
}
}

/**
Expand Down Expand Up @@ -162,8 +170,11 @@ export class FlexOffsetDirective extends BaseFxDirective implements OnInit, OnCh
offset = offset + '%';
}

const horizontalLayoutKey =
this._directionality.value === 'rtl' ? 'margin-right' : 'margin-left';
// The flex-direction of this element's flex container. Defaults to 'row'.
let layout = this._getFlowDirection(this.parentElement, true);
return isFlowHorizontal(layout) ? {'margin-left': `${offset}`} : {'margin-top': `${offset}`};
return isFlowHorizontal(layout) ? {[horizontalLayoutKey]: `${offset}`} :
{'margin-top': `${offset}`};
}
}
23 changes: 22 additions & 1 deletion src/lib/api/flexbox/layout-gap.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {Component, OnInit} from '@angular/core';
import {CommonModule} from '@angular/common';
import {TestBed, ComponentFixture, async} from '@angular/core/testing';

import {DIR_DOCUMENT} from '../../bidi/directionality';
import {DEFAULT_BREAKPOINTS_PROVIDER} from '../../media-query/breakpoints/break-points-provider';
import {BreakPointRegistry} from '../../media-query/breakpoints/break-point-registry';
import {MockMatchMedia} from '../../media-query/mock/mock-match-media';
Expand All @@ -26,17 +27,20 @@ describe('layout-gap directive', () => {
let fixture: ComponentFixture<any>;
let createTestComponent = makeCreateTestComponent(() => TestLayoutGapComponent);
let expectDomForQuery = makeExpectDOMForQuery(() => TestLayoutGapComponent);
let fakeDocument: {body: {dir?: string}, documentElement: {dir?: string}};

beforeEach(() => {
jasmine.addMatchers(customMatchers);
fakeDocument = {body: {}, documentElement: {}};

// Configure testbed to prepare services
TestBed.configureTestingModule({
imports: [CommonModule, FlexLayoutModule],
declarations: [TestLayoutGapComponent],
providers: [
BreakPointRegistry, DEFAULT_BREAKPOINTS_PROVIDER,
{provide: MatchMedia, useClass: MockMatchMedia}
{provide: MatchMedia, useClass: MockMatchMedia},
{provide: DIR_DOCUMENT, useValue: fakeDocument}
]
});
});
Expand Down Expand Up @@ -287,6 +291,23 @@ describe('layout-gap directive', () => {

});

describe('rtl support', () => {
it('uses margin-left when document body has rtl dir', () => {
fakeDocument.body.dir = 'rtl';
verifyCorrectMargin('row', 'margin-left');
});

it('uses margin-left when documentElement has rtl dir', () => {
fakeDocument.documentElement.dir = 'rtl';
verifyCorrectMargin('row', 'margin-left');
});

it('still uses margin-bottom in column layout when body has rtl dir', () => {
fakeDocument.body.dir = 'rtl';
verifyCorrectMargin('column', 'margin-bottom');
});
});

});


Expand Down
12 changes: 10 additions & 2 deletions src/lib/api/flexbox/layout-gap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {Subscription} from 'rxjs/Subscription';

import {BaseFxDirective} from '../core/base';
import {LayoutDirective} from './layout';
import {Directionality} from '../../bidi/directionality';
import {MediaChange} from '../../media-query/media-change';
import {MediaMonitor} from '../../media-query/media-monitor';
import {LAYOUT_VALUES} from '../../utils/layout-validator';
Expand All @@ -45,6 +46,7 @@ export class LayoutGapDirective extends BaseFxDirective implements AfterContentI
protected _layout = 'row'; // default flex-direction
protected _layoutWatcher: Subscription;
protected _observer: MutationObserver;
private _directionWatcher: Subscription;

/* tslint:disable */
@Input('fxLayoutGap') set gap(val) { this._cacheInput('gap', val); }
Expand All @@ -70,12 +72,15 @@ export class LayoutGapDirective extends BaseFxDirective implements AfterContentI
renderer: Renderer2,
@Optional() @Self() container: LayoutDirective,
private _zone: NgZone,
@Inject(PLATFORM_ID) platformId: Object) {
@Inject(PLATFORM_ID) platformId: Object,
private _directionality: Directionality) {
super(monitor, elRef, renderer, platformId);

if (container) { // Subscribe to layout direction changes
this._layoutWatcher = container.layout$.subscribe(this._onLayoutChange.bind(this));
}
this._directionWatcher =
this._directionality.change.subscribe(this._updateWithValue.bind(this));
}

// *********************************************
Expand Down Expand Up @@ -108,6 +113,9 @@ export class LayoutGapDirective extends BaseFxDirective implements AfterContentI
if (this._observer) {
this._observer.disconnect();
}
if (this._directionWatcher) {
this._directionWatcher.unsubscribe();
}
}

// *********************************************
Expand Down Expand Up @@ -196,7 +204,7 @@ export class LayoutGapDirective extends BaseFxDirective implements AfterContentI
case 'row' :
case 'row-reverse':
default :
key = 'margin-right';
key = this._directionality.value === 'rtl' ? 'margin-left' : 'margin-right';
break;
}
margins[key] = value;
Expand Down
23 changes: 23 additions & 0 deletions src/lib/bidi/bidi-module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {NgModule} from '@angular/core';
import {DOCUMENT} from '@angular/common';
import {Dir} from './dir';
import {DIR_DOCUMENT, Directionality} from './directionality';


@NgModule({
exports: [Dir],
declarations: [Dir],
providers: [
{provide: DIR_DOCUMENT, useExisting: DOCUMENT},
Directionality,
]
})
export class BidiModule { }
39 changes: 39 additions & 0 deletions src/lib/bidi/bidi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
The `bidi` package provides a common system for components to get and respond to change in the
application's LTR/RTL layout direction. This directory was copied straight from
https://github.com/angular/material2/blob/master/src/cdk/bidi/

### Directionality

When including the CDK's `BidiModule`, components can inject `Directionality` to get the current
text direction (RTL or LTR);

#### Example
```ts
@Component({ ... })
export class MyWidget implements OnDestroy {

/** Whether the widget is in RTL mode or not. */
private isRtl: boolean;

/** Subscription to the Directionality change EventEmitter. */
private _dirChangeSubscription = Subscription.EMPTY;

constructor(dir: Directionality) {
this.isRtl = dir.value === 'rtl';

_dirChangeSubscription = dir.change.subscribe(() => {
this.flipDirection();
});
}

ngOnDestroy() {
this._dirChangeSubscription.unsubscribe();
}
}
```

### The `Dir` directive
The `BidiModule` also includes a directive that matches any elements with a `dir` attribute. This
directive has the same API as Directionality and provides itself _as_ `Directionality`. By doing
this, any component that injects `Directionality` will get the closest ancestor layout direction
context.
Loading