File
Implements
Metadata
selector |
body-text-expandable |
styleUrls |
./body-text-expandable.component.scss |
templateUrl |
./body-text-expandable.component.html |
Index
Properties
|
|
Methods
|
|
Inputs
|
|
HostBindings
|
|
Methods
Public
parseRTF
|
parseRTF(bodyTextList)
|
|
Parameters :
Name |
Optional |
bodyTextList |
No
|
|
bodyTextAccordion
|
Type : NgbAccordion
|
Decorators :
@ViewChild('expandable')
|
|
bodyTextId
|
Default value : this.idGenerator.getId()
|
|
import { Component, Input, OnInit, HostBinding } from '@angular/core';
import { UtilService } from 'src/app/core/services/util-service/util.service';
import { IdGeneratorService } from 'src/app/core/services/id-generator.service';
import { NgbAccordion } from '@ng-bootstrap/ng-bootstrap';
import { ViewChild } from '@angular/core';
import { ExpandService } from 'src/app/core/services/expand-service/expand.service';
interface ExpandableBodyTextData {
title: any;
id: string;
bodyText: any;
}
@Component({
selector: 'body-text-expandable',
templateUrl: './body-text-expandable.component.html',
styleUrls: ['./body-text-expandable.component.scss']
})
export class BodyTextExpandableComponent implements OnInit {
@Input() entity;
bodyTexts: ExpandableBodyTextData[] = [];
firstBody; // First body text which should be non-collapsable
bodyTextId = this.idGenerator.getId();
@HostBinding('class') get class() { return 'col-md-8 space-between'; }
@ViewChild('expandable') bodyTextAccordion: NgbAccordion;
constructor(
private util: UtilService,
private idGenerator: IdGeneratorService,
private expandService: ExpandService
) {}
ngOnInit(): void {
const bodyTextList = this.util.extract(this.entity, 'EmbeddedBodytext');
this.bodyTexts = this.parseRTF(bodyTextList);
this.expandService.expandObs.subscribe(id => {
this.bodyTextAccordion.expand(id);
const accordion = document.querySelector(`#${id}`);
// Wait for accordion to open.
setTimeout(() => {
accordion.scrollIntoView({ behavior: 'smooth' });
}, 1);
});
}
// Parse RTF field and extract title value
public parseRTF(bodyTextList) {
bodyTextList = bodyTextList.map((bodyText, index) => {
const rtf = this.util.extract(bodyText, 'BodyText') || '';
const parser = new DOMParser();
const doc = parser.parseFromString(rtf, 'text/html');
const paragraphTitle = doc.documentElement.querySelector('.expandable-text-title');
const title = paragraphTitle ? paragraphTitle.textContent : '';
const bodyElement = doc.documentElement.querySelector('body');
// Generate id
const bodyId = `body-${this.idGenerator.getId()}`;
// Remove title from all bodyTexts except the first
if (index !== 0 && paragraphTitle) {
paragraphTitle.parentNode.removeChild(paragraphTitle);
}
// Hide first bodyText if class name found
if (index === 0 && doc.documentElement.querySelector('.hidden-paragraph')) {
return undefined;
}
return {
title: title,
id: bodyId,
bodyText: bodyElement.innerHTML,
} as ExpandableBodyTextData;
});
return bodyTextList;
}
}
<div class="mt-4 mb-4 body-text-expanded" [id]="'expandable-' + bodyTextId">
<rich-text-field *ngIf="bodyTexts[0]" [body]="bodyTexts[0].bodyText"></rich-text-field>
<ngb-accordion #expandable="ngbAccordion" [closeOthers]="true" [destroyOnHide]="false">
<ng-container *ngFor="let bodyText of bodyTexts; let first=first">
<ngb-panel *ngIf="!first" [id]="bodyText.id">
<ng-template ngbPanelHeader>
<button ngbPanelToggle>
<span>{{bodyText.title}}</span>
<span class="open" *ngIf="!expandable.isExpanded(bodyText.id)">+</span>
<span class="closed" *ngIf="expandable.isExpanded(bodyText.id)">×</span>
</button>
</ng-template>
<ng-template ngbPanelContent>
<rich-text-field [body]="bodyText.bodyText"></rich-text-field>
</ng-template>
</ngb-panel>
</ng-container>
</ngb-accordion>
<div *ngIf="entity.Footnote?.length > 0" class="footer">
<ol>
<li class="d-flex" *ngFor="let footnote of entity.Footnote; let i=index">
<span class="mr-1"><sup>{{i+1}})</sup></span>
<rich-text-field [body]="footnote"></rich-text-field>
</li>
</ol>
</div>
</div>
@import "src/app/styles/helpers";
.body-text-expanded {
::ng-deep .card {
border: none;
.card-header {
border: none;
background-color: transparent;
border-bottom: 1px solid $light-slate;
padding: 0;
margin-bottom: 0;
button {
border: none;
background-color: transparent;
display: flex;
justify-content: space-between;
width: 100%;
line-height: 3.13;
color: $blue;
&:focus {
outline: none;
}
}
}
.card-body {
padding-right: 0;
padding-left: 0;
}
}
.footer {
border-top: 1px solid $slate;
padding-top: calc-rem(20);
margin-top: calc-rem(20);
@include font-size(12);
ol {
padding-left: 0;
list-style: none;
}
}
}
Legend
Html element with directive