Eu tenho dois projetos Angular usando estas versões:
- 9.0.0-next.6
- 8.1.0
Na versão 9, usei isso para fornecer e injetar o window
objeto:
@NgModule({
providers: [
{
provide: Window,
useValue: window
},
]
})
export class TestComponent implements OnInit {
constructor(@Inject(Window) private window: Window)
}
O que funciona bem.
A adoção dessa abordagem para a versão 8 gerou avisos e erros durante a compilação:
Aviso: Não é possível resolver todos os parâmetros do TestComponent…
Eu o resolvi usando aspas simples, assim:
@NgModule({
providers: [
{
provide: 'Window',
useValue: window
},
]
})
export class TestComponent implements OnInit {
constructor(@Inject('Window') private window: Window)
}
Qual é a diferença entre as duas versões?
Qual é a diferença nos angulares 8 e 9 que causa isso?
Respostas:
Para que seu aplicativo funcione com a renderização no lado do servidor, sugiro que você não apenas use a janela por meio de token, mas também crie esse token de maneira amigável ao SSR, sem fazer nenhuma referência
window
. Angular possui umDOCUMENT
token interno para acessardocument
. Aqui está o que eu criei para meus projetos usaremwindow
através de tokens:fonte
Considerando a
ValueProvider
interface:A
provide
propriedade é do tipoany
. Isso significa que qualquer objeto (incluindo oWindow
construtor) pode entrar nele. O objeto realmente não importa, apenas a referência importa para identificar qual provedor deve ser usado para injetar um parâmetro em um construtor.Não deve ser considerado uma boa prática usar o
Window
construtor nativo como um token de injeção. Ele falha no tempo de compilação porqueWindow
existe no tempo de execução em um ambiente de navegador, também existe como um TypeScript,declare
mas o compilador Angular 8 não pode fazer análise de código estático para correlacionar os parâmetrosWindow
nos provedores eWindow
nos construtores, uma vez que a atribuição deWindow
é feita pelo navegador, não pelo código. Não sei por que funciona no Angular 9, no entanto ...Você deve criar seu próprio token de injeção que representa o provedor de dependência. Esse token de injeção deve ser:
'Window'
)InjectionToken
. Por exemploexport const window = new InjectionToken<Window>('window');
Além disso, o código angular deve ser independente de plataforma (deve ser executável em um navegador e também em um servidor Node.js.), portanto, seria melhor usar uma fábrica que retorne
window
ouundefined
/ enull
, em seguida, manipule oundefined
/null
case nos componentes.fonte