Подтвердить что ты не робот

Получить статический 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)

4b9b3361

Ответ 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 и сохранить.