Получить статический html/css снимок компонента
Вкратце: Как получить сгенерированный CSS моего компонента в виде строки?
- > Я хочу получить снимок моего компонента. То есть, как выглядит этот вид. Только то, что вы видите, когда вы щелкаете правой кнопкой → проверяете. Html и css для рендеринга компонента независимо от любого Javascript.
Мотивация: используйте этот снимок для последующего экспорта в формате PDF. Я могу создать PDF файлы по-серверу, но поскольку Angular имеет аккуратный механизм шаблонов, почему бы не использовать его для этого? Комментарии приветствуются.
Мне удалось получить html-код моментального снимка из моего banana
-компонента следующим образом:
// banana component file
@Component( {
selector: 'banana',
template: `<div id="report">some text</div>`,
styles: [ '#report { font-weight:bold; }' ]
})
export class BananaComponent {
constructor(public elementRef: ElementRef) { }
}
// parent component file
@Component(...)
export class App {
@ViewChild(BananaComponent) myBanana;
private getSnapshot() {
let bananaSnapshotHtml = this.myBanana.elementRef.nativeElement.outerHTML;
let bananaSnapshotCss = // ?? TODO
}
}
Например, переменная snapshotHtml
выглядит следующим образом:
<banana _ngcontent-c2="" _nghost-c4="" ng-reflect-render="true"><!--bindings={
"ng-reflect-ng-if": "true"
}--><div _ngcontent-c4="" id="report">
some text
</div></banana>
Но я понятия не имею, как получить соответствующий bananaSnapshotCss
. Согласно Firefox, Angular каким-то образом помещает этот inline:
#report[_ngcontent-c4] {
font-weight: bold;
}
Есть ли способ получить это ^ как-то программно? Я хочу, чтобы моя переменная bananaSnapshotCss
была выше. Или мой подход не так?
Сейчас я вручную копирую содержимое своих css файлов в bananaSnapshotCss
и, таким образом, это часть моего кода TS. Это уродливый и повторяющийся код и игнорирует вложенные стили дочерних компонентов.
Смотрите живой пример здесь, включая текущее обходное решение (app/app.ts
с TODO
)
Ответы
Ответ 1
Вот решение, которое я мог бы придумать.
@Component(...)
export class App {
@ViewChild(BananaComponent) myBanana;
private getSnapshot() {
let bananaSnapshotHtml = this.myBanana.elementRef.nativeElement.outerHTML;
// new:
let bananaSnapshotCss = [].slice.call(document.styleSheets)
.map(sheet => [].slice.call(sheet.rules))
.filter(sheet => !sheet.disabled)
.reduce((all_rules, rules) => all_rules.concat(rules), [])
.reduce((style, rule) => `${style}\n${rule.cssText}`, "");
}
}
Что это значит, просто конкатенировать все styleSheets
документа. Это также будет содержать CSS для других компонентов. Они могут быть отфильтрованы, но это действительно не нужно.
Вот обновленный плункер, если кому-то интересно. http://embed.plnkr.co/0BlyVihLcoDOLqzwqmNm/
Со всем этим компонент, наконец, может быть экспортирован в виде полного html файла.
Ответ 2
Вы можете применить метод getComputedStyle()
к elementRef.nativeElement
(подробнее об этом здесь).
В вашем примере это означало бы:
// banana component file
@Component( {
selector: 'banana',
template: `<div id="report">some text</div>`,
styles: [ '#report { font-weight:bold; }' ]
})
export class BananaComponent {
constructor(public elementRef: ElementRef) { }
}
// parent component file
@Component(...)
export class App {
@ViewChild(BananaComponent) myBanana;
private getSnapshot() {
let bananaSnapshotHtml = this.myBanana.elementRef.nativeElement.outerHTML;
let bananaSnapshotCss = getComputedStyle(this.myBanana.elementRef.nativeElement);
}
}
Ответ 3
Если вы можете создавать PDF файлы на стороне клиента, я бы предложил использовать медиа-запрос CSS: @media print { ... }
Основная причина заключается в том, что DOM не отражает состояние приложения. Только повторная передача экспортированной DOM несовместима. Больше вашего компонента CSS будет недостаточно для воспроизведения всех стилей (агент, страница, компоновка компонентов и т.д.).
Большинство инструментов, которые имеют веб-рендеринг на стороне сервера (PDF, изображения,...), используют PhantomJS для генерации "моментальный снимок".
В случае Angular вы также можете взглянуть на Angular Universal, которые предлагают рендеринг на стороне сервера.
Ответ 4
В селекторе @Component
добавьте класс, используя host: {'class':'reports'}
. Затем в вашем css вы можете устанавливать стили, используя класс отчетов. Надеюсь, это поможет вам.
Ответ 5
Используйте document.documentElement.innerHTML, чтобы получить всю DOM с встроенным css и сохранить.