src/app/shared/components/viewer/viewer.component.ts
Viewer for tissue samples
OnChanges
changeDetection | ChangeDetectionStrategy.OnPush |
selector | ccf-viewer |
styleUrls | ./viewer.component.scss |
templateUrl | ./viewer.component.html |
Properties |
Inputs |
Outputs |
HostBindings |
constructor(sanitizer: DomSanitizer)
|
||||||
Parameters :
|
url | |
Type : string
|
|
Default value : ''
|
|
closed | |
Type : EventEmitter
|
|
class |
Type : string
|
Default value : 'ccf-viewer'
|
className |
Type : string
|
Default value : 'ccf-viewer'
|
Decorators :
@HostBinding('class')
|
loading |
Default value : true
|
safeUrl |
Type : SafeResourceUrl | null
|
Default value : null
|
Sanitized url NOTE: Never use a getter for this property! It will cause the iframe to reload constantly. |
import {
ChangeDetectionStrategy,
Component,
EventEmitter,
HostBinding,
Input,
OnChanges,
Output,
SimpleChanges,
} from '@angular/core';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
/**
* Viewer for tissue samples
*/
@Component({
selector: 'ccf-viewer',
templateUrl: './viewer.component.html',
styleUrls: ['./viewer.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ViewerComponent implements OnChanges {
@HostBinding('class') className = 'ccf-viewer';
@Input() url = '';
@Output() readonly closed = new EventEmitter<void>();
loading = true;
/**
* Sanitized url
* NOTE: Never use a getter for this property! It will cause the iframe to reload constantly.
*/
safeUrl: SafeResourceUrl | null = null;
constructor(private readonly sanitizer: DomSanitizer) {}
ngOnChanges(changes: SimpleChanges): void {
if ('url' in changes) {
this.updateUrl();
}
}
private updateUrl(): void {
const { sanitizer, url } = this;
this.safeUrl = null;
if (url) {
this.safeUrl = sanitizer.bypassSecurityTrustResourceUrl(url);
this.loading = true;
}
}
}
<div class="toolbar">
<a mat-flat-button class="launch" target="_blank" rel="noopener noreferrer" [href]="safeUrl" [disabled]="!safeUrl">
<mat-icon class="icon">launch</mat-icon>
<span class="text">Open in Portal</span>
</a>
<button mat-flat-button class="close" (click)="closed.emit()">
<mat-icon class="icon">clear</mat-icon>
</button>
</div>
<div class="overlay" *ngIf="loading">
<mat-spinner class="spinner"></mat-spinner>
<span class="text">Loading External Site</span>
</div>
<iframe
*ngIf="safeUrl"
class="frame"
title="Portal Data Viewer"
referrerpolicy="no-referrer"
[attr.src]="safeUrl"
(load)="loading = false"
>
</iframe>
./viewer.component.scss
:host {
display: block;
z-index: 1;
.toolbar {
display: flex;
justify-content: flex-end;
align-items: center;
width: 100%;
height: 1.5rem;
.launch {
margin-right: 3.5rem;
&.mat-button-disabled {
cursor: not-allowed;
}
.icon {
margin-right: 0.25rem;
}
}
.close {
min-width: 0;
padding: 0;
border-radius: 0;
height: 100%;
width: 1.5rem;
.icon {
margin: 0;
}
}
}
.overlay {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: absolute;
top: 1.5rem;
bottom: 0;
left: 0;
right: 0;
.spinner {
margin-bottom: 0.5rem;
}
}
.frame {
width: 100%;
height: 100%;
}
}