Wie füge ich Document in Service ein?

74

Ich habe eine Angular 2-Anwendung. Um das DocumentObjekt in Tests zu verspotten , möchte ich es wie folgt in den Dienst einfügen:

import { Document } from '??' 

@Injectable()
export class MyService {
  constructor(document: Document) {}
}

Der TitleDienst von Angular verwendet die interne getDOM()Methode .

Gibt es eine einfache Möglichkeit, das Documentin den Dienst einzuspeisen? Wie soll ich im providersArray darauf verweisen ?

RJo
quelle
Ich wollte das positiv bewerten, habe mich dann aber dagegen entschieden ... aber danke, dass du diese Frage gestellt hast :)
Joel Balmer

Antworten:

134

Dies wird seit einiger Zeit von Angular unterstützt.

Sie können die DOCUMENTvom @angular/commonPaket bereitgestellte Konstante verwenden .

Beschreibung der DOCUMENTKonstante (aus der API-Dokumentation entnommen ):

Ein DI-Token, das den Haupt-Rendering-Kontext darstellt. In einem Browser ist dies das DOM-Dokument.

Ein Beispiel ist wie folgt:

my-service.service.ts:

import { Inject, Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/common';

@Injectable()
export class MyService {
  constructor(@Inject(DOCUMENT) private document: Document) {}
}

my-service.service.spec.ts

import { provide } from '@angular/core';
import { DOCUMENT } from '@angular/common';

import { MyService } from './my-service';

class MockDocument {}

describe('MyService', () => {
  beforeEachProviders(() => ([
    provide(DOCUMENT, { useClass: MockDocument }),
    MyService
  ]));

  ...
});
Günter Zöchbauer
quelle
1
Und in der realen Implementierung sollten wir die tatsächliche Dokumentinstanz bereitstellen, z. B. declare const document: Document;und dannbootstrap(provide(Document, { useValue: document }));
RJo
3
@ GünterZöchbauer es sieht so aus, als wäre DOKUMENT veraltet . Irgendeine Idee, wie man das macht, wenn es weg ist? Wie würde ich beispielsweise das Favicon dynamisch einstellen?
Adamdport
11
@adamdport - {DOCUMENT} aus '@ angle / common' importieren; anstelle von '@
angle
1
Diese Antwort ist verwirrend (es scheint überall zu sein - wo ist Bootstrap (vorausgesetzt, es soll aufgerufen werden?). Ist es veraltet? Gibt es eine äquivalente Antwort, die tatsächlich zeigt, was wohin gehen soll? Beachten Sie, dass ich Sie müssen sich über nichts lustig machen
Dave Nottage
4
Als Typ können Sie HTMLDocumentanstelle von any:@Inject(DOCUMENT) private document: HTMLDocument
Edwin
33

Ich kann die Frage von adamdport nicht direkt kommentieren (noch nicht 50 Wiederholungspunkte), aber hier ist es wie in den eckigen Dokumenten angegeben.

Blockquote @ GünterZöchbauer es sieht so aus, als wäre DOKUMENT veraltet. Irgendeine Idee, wie man das macht, wenn es weg ist? Wie würde ich beispielsweise das Favicon dynamisch einstellen?

Anstatt wie folgt aus dem Plattformbrowser zu importieren:

import { DOCUMENT } from '@angular/platform-browser';

Importieren Sie es aus eckigen gemeinsamen:

import {DOCUMENT} from '@angular/common';
Ruud Voost
quelle
9

zusätzlich zu @ Günter Zöchbauers Antwort.

Angular definiert DOKUMENT als InjectionToken

export const DOCUMENT = new InjectionToken<Document>('DocumentToken');

dom_tokens.ts

Und fügen Sie es mit Dokument in browser.ts ein

{provide: DOCUMENT, useFactory: _document, deps: []}


export function _document(): any {
  return document;
}

Wenn wir es verwenden, müssen wir es daher nur injizieren @Inject(DOCUMENT)

oder verwenden Sie den Token direkt in deps:[DOCUMENT]

Maxisam
quelle
Dies funktioniert in AOT (Produktion), wenn Sie das eigentliche Dokument benötigen. Es verhindert, dass "ERROR in Error beim statischen Auflösen von Symbolwerten aufgetreten ist"
Marcel van der Drift
Funktioniert nicht für mich in AOT, zumindest für Angular 6. Ich erhalte die Fehlermeldung "Kann nicht alle Parameter für ... auflösen". Siehe auch: stackoverflow.com/questions/50920734/…
Dave Nottage
Wird dies korrekt behoben, wenn die eckige App in einem Nicht-Browser gerendert wird?
The.Wolfgang.Grimmer
-2
import { Inject, Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/common';

@Injectable()
export class MyService {
  constructor(@Inject(DOCUMENT) private document) {}
}

Es ist das ": Dokument", das das Problem verursacht.

Ein besorgter Linux-Bürger
quelle