问题描述
根据How to remove the URL from the printing page?,这是我需要的CSS:
@media print{
@page{
margin:0;
}
body{
margin:30px;
}
}
但是将CSS与::ng-deep
或ViewEncapsulation.None
放到组件中将无济于事,因为在离开页面时,不会删除页面的CSS。
我添加了Stackblitz,它可以清楚地说明问题。
encapsulation: ViewEncapsulation.None
...
constructor(private renderer: Renderer2) {
this.renderer.addClass(document.body,'special-print');
}
ngOnDestroy() {
this.renderer.removeClass(document.body,'special-print');
}
....
....
....
@media print{
@page{
margin:0;
}
body.special-print{
margin:30px;
}
}
为什么不起作用:
虽然它对<body>
CSS有帮助,但对@page
CSS没有帮助。也许最好将问题概括为“如何添加全局CSS,但是在离开页面时将其删除?”。
解决方法
解决了!通过DomSanitizer.bypassSecurityTrustHtml
这里是StackBlitz。
首先,创建一个新组件来处理工作:
component.ts: (This is all we need. We don't need an HTML or style.css file.)
//Inside your local component,place this HTML
//<app-local-css [style]="'body{background:green !important;}'"></app-local-css>
// OR
//<app-local-css [scriptURL]="'/path/to/file.css'"></app-local-css>
@Component({
selector: "app-local-css",template: '<span style="display:none" [innerHTML]="this.safeString"></span>'
})
export class LocalCSSComponent implements OnInit {
constructor(protected sanitizer: DomSanitizer) {}
@Input() scriptURL?: string;
@Input() style?: string;
safeString: SafeHtml;
ngOnInit() {
if (this.scriptURL) {
let string = '<link rel="stylesheet" type="text/css" href="' + this.scriptURL + '">';
this.safeString = this.sanitizer.bypassSecurityTrustHtml(string);
} else if (this.style) {
let string = '<style type="text/css">' + this.style + "</style>";
this.safeString = this.sanitizer.bypassSecurityTrustHtml(string);
}
}
}
然后像这样使用它:
mySample.component.html:
<app-local-css [style]="'body{background:green !important;}'"></app-local-css>
// OR
<app-local-css [scriptURL]="'/path/to/file.css'"></app-local-css>
这是有效的,因为CSS位于HTML内,因此当组件被销毁时,也是如此。 (由于bypassSecurityTrustHtml
,Angular不会尝试修改它)
Angular正在进行客户端渲染,这是一个坏消息,因为您没有单独的页面。不过,您有几种可能的解决方案:
1。单独的页面
您可以创建包含或不包含Angular的另一个页面,其中包含您需要的CSS并加载该页面。用最简单的方法来实现此目的,另一个页面将具有不同的URL。如果您不喜欢使用其他URL,则可以隐藏页面的内容,并在iframe
中显示另一个页面。无疑,这将是一个棘手的解决方案,但这是一个解决方案。
2。客户端CSS渲染
您可以拥有一个可以控制全局CSS规则并与视图名称匹配的组件,而不是仅加载CSS。您将向属性渲染一个模板值,例如:
`
@media print{
@page{
margin:0;
}
body{
margin:30px;
}
}
`
当您访问需要激活该页面的页面时,只需使用基于模板生成并添加到style
的{{1}} HTML元素初始化属性。离开给定视图后,组件将检测到该事件并head
该元素。如果选择此解决方案,那么最好以更笼统的术语来支持此解决方案,这样一来,如果某些新视图将具有其自定义的全局CSS,那么将来它们很容易集成到您的项目中
3。身体类别
每当要更改样式时,都可以在remove()
中添加一些custom-print
或从其中删除类。这样,您可以将CSS完全添加到HTML一次,并相应地更改规则,例如:
body
这将是一个很好的解决方案,但您的问题是您也有一个body.custom-print {
margin: 30px;
}
规则,但我不确定如何使它依赖于正文类或其他一些HTML属性。如果我是你的话,我将为此做很多实验。
4。 iframe分期
您可以避免在主页上放置该CSS,但是会在@page
中隐藏一个CSS,将其复制到CSS中,然后将其复制并打印出来。
不要改变苹果的整个身体。相反,需要进行一些更改。
-
在应用程序组件中,请为您是否在苹果计算机上保存一个布尔值,并将ngClass用作scss中定义的类。
-
跟踪您在appComponent中的路线,并相应地设置isApple
-
在您的所有html周围添加一个div,以使容器采用完整尺寸
-
添加全局html,主体设置高度为100%,这样您就可以在任何地方看到颜色
-
删除苹果中的身体覆盖
所以, appComponent.ts:
isApple: Boolean;
constructor(router: Router) {
router.events.subscribe(v => {
if (v instanceof NavigationEnd) {
this.isApple = v.url === "/apple";
}
});
}
appComponent.html:
<div [ngClass]="{'red':isApple}" class="container">
<p>
There are two components: Apple and Banana. Switching between them will show
the problem.
</p>
<router-outlet></router-outlet>
</div>
appComponent.scss
.red {
background-color: red;
}
.container {
height: 100%;
}
apple.component.scss(删除主体)
/*Sample "global" CSS,that affects something outside the current component.*/
::ng-deep {
@media print {
@page {
margin: 0;
}
}
}
styles.scss(全局)
html,body {
height: 100%;
}
您可以总共看到at this Stackblitz link
,您可以在组件中添加不同的css文件(例如,app-task.component.ts):
@Component({
selector: 'app-task',templateUrl: './app-task.component.html',styleUrls: ['./app-task.component.scss','./styles2.scss','./styles3.scss']
})
在此示例中,样式文件与组件位于同一文件夹中,但这不是最佳选择:例如,您必须将文件放入资产中。另外,请谨慎使用样式的线,因为您放置的第一个样式(显然)将放置在第二个样式之前。