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

Commit 0c9e9cb

Browse files
feat(core): add print support with mediaQuery override (#954)
When printing developers can now configure how layouts should render. Default print will use the current layout and current elements shown/visible. By specifying 1..n mediaQuery aliases, developers can specify alternate layouts with alternate breakpoints to be used for printing. Elements can also be shown and hidden for printing-only. > This feature supports totally different print outputs without modifying the current browser layout. Implement PrintHook service to intercept print mediaQuery activation events. * add fxShow.print and fxHide.print support to show/hide elements during printing * suspend activation changes in MediaMarshaller while print-mode is active * trigger MediaObserver to notify subscribers with print mqAlias(es) * use PrintHook to intercept activation changes in MediaMarshaller while print-mode is active * trigger MediaObserver to notify subscribers with print mqAlias(es) * add watermark component to Demo app that is shown only during printing Using the new `printWithBreakpoint` allows developers to specify a breakpoint that should be used to render layouts only during printing. With the configuration below, the breakpoint associated with the **`md`** alias will be used. ```ts FlexLayoutModule.withConfig({ useColumnBasisZero: false, printWithBreakpoints: ['md', 'lt-lg', 'lt-xl', 'gt-sm', 'gt-xs'] }) ``` Shown below is the print layout rendered in floating dialog over the normal layout that is currently using 'lg' breakpoints. ![angular-layout-printing](https://user-images.githubusercontent.com/210413/50407211-2e04ca00-0798-11e9-8f35-b4e9e2fca864.jpg) Fixes #603.
1 parent d57b293 commit 0c9e9cb

32 files changed

+1058
-374
lines changed

docs/documentation/BreakPoints.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ import {BREAKPOINT} from '@angular/flex-layout';
4242
const PRINT_BREAKPOINTS = [{
4343
alias: 'xs.print',
4444
suffix: 'XsPrint',
45-
mediaQuery: 'print and (max-width: 297px)',
45+
mediaQuery: 'screen and (max-width: 297px)',
4646
overlapping: false
4747
}];
4848

@@ -157,4 +157,4 @@ export class CustomShowHideDirective extends ShowHideDirective {
157157
this._cacheInput("showXsPrint", negativeOf(val));
158158
}
159159
}
160-
```
160+
```

docs/documentation/fxHide-API.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ e.g.
2424
2525
### Using Responsive API
2626

27-
When a mediaQuery range activates, the directive instances will be notified. If the current activate mediaQuery range
27+
When a mediaQuery range activates, the directive instances will be notified. If the current activated mediaQuery range
2828
(and its associated alias) are not used, then the static API value is restored as the fallback value.
2929

3030
The *fallback* solution uses a **`largest_range-to-smallest_range`** search algorithm. Consider the following:

docs/documentation/fxShow-API.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ e.g.
2424
2525
### Using Responsive API
2626

27-
When a mediaQuery range activates, the directive instances will be notified. If the current activate mediaQuery range
27+
When a mediaQuery range activates, the directive instances will be notified. If the current activated mediaQuery range
2828
(and its associated alias) are not used, then the static API value is restored as the fallback value.
2929

3030
The *fallback* solution uses a **`largest_range-to-smallest_range`** search algorithm. Consider the following:

src/apps/demo-app/src/app/app.component.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ <h2>Layout Demos: </h2>
1313
</span>
1414
</div>
1515
<div fxLayout="row"
16-
fxLayoutAlign="start center"
1716
fxLayoutGap="20px"
17+
fxHide.print
1818
style="height:40px; min-height:40px;">
1919
<button mat-raised-button color="primary" [routerLink]="['']">
2020
Static
@@ -30,4 +30,8 @@ <h2>Layout Demos: </h2>
3030

3131
<div class="demo-content">
3232
<router-outlet></router-outlet>
33+
<watermark
34+
title="@angular/layout"
35+
message="HTML Layouts w/ Flex and Grid CSS"
36+
fxHide fxShow.print></watermark>
3337
</div>

src/apps/demo-app/src/app/app.module.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,31 @@ import {FlexLayoutModule, BREAKPOINT} from '@angular/flex-layout';
66
import {RoutingModule} from './routing.module';
77
import {AppComponent} from './app.component';
88
import {DemoMaterialModule} from './material.module';
9+
import {WatermarkComponent} from './watermark.component';
910

10-
const PRINT_BREAKPOINTS = [{
11-
alias: 'xs.print',
12-
suffix: 'XsPrint',
13-
mediaQuery: 'print and (max-width: 297px)',
11+
const EXTRA_BREAKPOINT = [{
12+
alias: 'xs.landscape',
13+
suffix: 'XsLandscape',
14+
mediaQuery: 'screen and (orientation: landscape) and (max-width: 559px)',
15+
priority: 1000,
1416
overlapping: false
1517
}];
1618

1719
@NgModule({
1820
declarations: [
19-
AppComponent,
21+
AppComponent, WatermarkComponent
2022
],
2123
imports: [
2224
BrowserModule.withServerTransition({ appId: 'serverApp' }),
2325
BrowserAnimationsModule,
2426
RoutingModule,
2527
DemoMaterialModule,
26-
FlexLayoutModule.withConfig({useColumnBasisZero: false}),
28+
FlexLayoutModule.withConfig({
29+
useColumnBasisZero: false,
30+
printWithBreakpoints: ['md', 'lt-lg', 'lt-xl', 'gt-sm', 'gt-xs']
31+
}),
2732
],
28-
providers: [{provide: BREAKPOINT, useValue: PRINT_BREAKPOINTS, multi: true}],
33+
providers: [{provide: BREAKPOINT, useValue: EXTRA_BREAKPOINT, multi: true}],
2934
bootstrap: [AppComponent]
3035
})
3136
export class AppModule { }

src/apps/demo-app/src/app/responsive/docs-responsive/docs-responsive.component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import {Component} from '@angular/core';
33
@Component({
44
selector: 'demo-docs-responsive',
55
template: `
6-
<demo-responsive-layout-direction class='small-demo'> </demo-responsive-layout-direction>
6+
<demo-responsive-layout-direction class='small-demo' fxHide.print>
7+
</demo-responsive-layout-direction>
78
<demo-responsive-row-column class='small-demo'> </demo-responsive-row-column>
89
<demo-responsive-flex-directive class='small-demo'> </demo-responsive-flex-directive>
910
<demo-responsive-flex-order class='small-demo'> </demo-responsive-flex-order>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
:host {
2+
display: block;
3+
position: absolute;
4+
5+
width: 100vw;
6+
min-height: 100vh;
7+
top: 0;
8+
left: 0;
9+
right: 0;
10+
bottom: 0;
11+
12+
div {
13+
width: 100vw;
14+
min-height: 100vh;
15+
}
16+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import {Component, Input} from '@angular/core';
2+
import {DomSanitizer} from '@angular/platform-browser';
3+
4+
@Component({
5+
selector: 'watermark',
6+
styleUrls: ['watermark.component.scss'],
7+
template: `
8+
<div [style.background]="backgroundImage">
9+
</div>
10+
`,
11+
})
12+
export class WatermarkComponent {
13+
@Input() title = '@angular/layout';
14+
@Input() message = 'Layout with FlexBox + CSS Grid';
15+
16+
constructor(private _sanitizer: DomSanitizer) {
17+
}
18+
19+
/* tslint:disable:max-line-length */
20+
get backgroundImage() {
21+
const rawSVG = `
22+
<svg id="diagonalWatermark"
23+
width="100%" height="100%"
24+
xmlns="http://www.w3.org/2000/svg"
25+
xmlns:xlink="http://www.w3.org/1999/xlink" >
26+
<style type="text/css">
27+
text {
28+
fill: currentColor;
29+
font-family: Avenir, Arial, Helvetica, sans-serif;
30+
opacity: 0.25;
31+
}
32+
</style>
33+
<defs>
34+
<pattern id="titlePattern" patternUnits="userSpaceOnUse" width="350" height="150">
35+
<text y="30" font-size="30" id="title">
36+
${this.title}
37+
</text>
38+
</pattern>
39+
<pattern xlink:href="#titlePattern">
40+
<text y="60" x="0" font-size="16" id="message" width="350" height="150">
41+
${this.message}
42+
</text>
43+
</pattern>
44+
<pattern id="combo" xlink:href="#titlePattern" patternTransform="rotate(-30)">
45+
<use xlink:href="#title"/>
46+
<use xlink:href="#message"/>
47+
</pattern>
48+
</defs>
49+
<rect width="100%" height="100%" fill="url(#combo)"/>
50+
</svg>
51+
`;
52+
const bkgrndImageUrl = `data:image/svg+xml;base64,${window.btoa(rawSVG)}`;
53+
54+
return this._sanitizer.bypassSecurityTrustStyle(`url('${bkgrndImageUrl}') repeat-y`);
55+
}
56+
}

src/apps/demo-app/src/styles.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,18 @@ body {
88
font-size: 16px;
99
line-height: 1.4;
1010
-webkit-font-smoothing: antialiased;
11+
-webkit-print-color-adjust: exact !important;
12+
}
13+
14+
@page {
15+
size: auto; /* auto is the initial value */
16+
margin: 2cm;
17+
}
18+
19+
@media print {
20+
body {
21+
background: white;
22+
}
1123
}
1224

1325
h3 {

src/lib/core/add-alias.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {extendObject} from '../utils/object-extend';
1414
* and suffix (if available).
1515
*/
1616
export function mergeAlias(dest: MediaChange, source: BreakPoint | null): MediaChange {
17-
return extendObject(dest, source ? {
17+
return extendObject(dest || {}, source ? {
1818
mqAlias: source.alias,
1919
suffix: source.suffix
2020
} : {});

0 commit comments

Comments
 (0)