variable pasar parametros globales entre comunicacion componentes change javascript angular

javascript - parametros - Cómo pasar parámetros procesados desde el backend al método bootstrap angular2



pasar parametros entre componentes angular 2 (4)

¿Hay alguna manera de pasar los argumentos representados en el backend al método angular2 bootstrap? Quiero establecer el encabezado http para todas las solicitudes utilizando BaseRequestOptions con el valor proporcionado desde el back-end. Mi archivo main.ts tiene este aspecto:

import { bootstrap } from ''@angular/platform-browser-dynamic''; import { AppComponent } from "./app.component.ts"; bootstrap(AppComponent);

Encontré cómo pasar estos argumentos al componente raíz ( https://stackoverflow.com/a/35553650/3455681 ), pero lo necesito cuando estoy activando el método bootstrap ... ¿Alguna idea?

editar:

Contenido de webpack.config.js:

module.exports = { entry: { app: "./Scripts/app/main.ts" }, output: { filename: "./Scripts/build/[name].js" }, resolve: { extensions: ["", ".ts", ".js"] }, module: { loaders: [ { test: //.ts$/, loader: ''ts-loader'' } ] } };


En la versión final de Angular2, el proveedor APP_INITIALIZER se puede utilizar para lograr lo que desea.

Escribí un Gist con un ejemplo completo: https://gist.github.com/fernandohu/122e88c3bcd210bbe41c608c36306db9

El ejemplo esencial es leer desde archivos JSON, pero se puede cambiar fácilmente para leer desde un punto final REST.

Lo que necesitas es básicamente:

a) Configure APP_INITIALIZER en su archivo de módulo existente:

import { APP_INITIALIZER } from ''@angular/core''; import { BackendRequestClass } from ''./backend.request''; import { HttpModule } from ''@angular/http''; ... @NgModule({ imports: [ ... HttpModule ], ... providers: [ ... ... BackendRequestClass, { provide: APP_INITIALIZER, useFactory: (config: BackendRequestClass) => () => config.load(), deps: [BackendRequestClass], multi: true } ], ... });

Estas líneas llamarán al método load () de la clase BackendRequestClass antes de que se inicie su aplicación.

Asegúrese de establecer "HttpModule" en la sección "importaciones" si desea realizar llamadas http al backend utilizando la biblioteca integrada angular2.

b) Cree una clase y nombre el archivo "backend.request.ts":

import { Inject, Injectable } from ''@angular/core''; import { Http } from ''@angular/http''; import { Observable } from ''rxjs/Rx''; @Injectable() export class BackendRequestClass { private result: Object = null; constructor(private http: Http) { } public getResult() { return this.result; } public load() { return new Promise((resolve, reject) => { this.http.get(''http://address/of/your/backend/endpoint'').map( res => res.json() ).catch((error: any):any => { reject(false); return Observable.throw(error.json().error || ''Server error''); }).subscribe( (callResult) => { this.result = callResult; resolve(true); }); }); } }

c) Para leer el contenido de la llamada al backend, solo necesita inyectar el BackendRequestClass en cualquier clase de su elección y llamar a getResult (). Ejemplo:

import { BackendRequestClass } from ''./backend.request''; export class AnyClass { constructor(private backendRequest: BackendRequestClass) { // note that BackendRequestClass is injected into a private property of AnyClass } anyMethod() { this.backendRequest.getResult(); // This should return the data you want } }

Avísame si esto resuelve tu problema.


En lugar de tener su punto de entrada llamando a bootstrap, puede crear y exportar una función que haga el trabajo:

export function doBootstrap(data: any) { platformBrowserDynamic([{provide: Params, useValue: new Params(data)}]) .bootstrapModule(AppModule) .catch(err => console.error(err)); }

También puede colocar esta función en el objeto global, dependiendo de su configuración (webpack / SystemJS). También es compatible con AOT.

Esto tiene el beneficio adicional de retrasar el arranque, cuando tiene sentido. Por ejemplo, cuando recupera estos datos de usuario como una llamada AJAX después de que el usuario complete un formulario. Simplemente llame a la función bootstrap exportada con estos datos.


La única forma de hacerlo es proporcionar estos valores al definir sus proveedores:

bootstrap(AppComponent, [ provide(RequestOptions, { useFactory: () => { return new CustomRequestOptions(/* parameters here */); }); ]);

Luego puede usar estos parámetros en su clase CustomRequestOptions :

export class AppRequestOptions extends BaseRequestOptions { constructor(parameters) { this.parameters = parameters; } }

Si obtiene estos parámetros de una solicitud AJAX, debe arrancar de forma asíncrona de esta manera:

var appProviders = [ HTTP_PROVIDERS ] var app = platform(BROWSER_PROVIDERS) .application([BROWSER_APP_PROVIDERS, appProviders]); var http = app.injector.get(Http); http.get(''http://.../some path'').flatMap((parameters) => { return app.bootstrap(appComponentType, [ provide(RequestOptions, { useFactory: () => { return new CustomRequestOptions(/* parameters here */); }}) ]); }).toPromise();

Ver esta pregunta:

Editar

Como tiene sus datos en el HTML, puede usar lo siguiente.

Puede importar una función y llamarla con parámetros.

Aquí hay una muestra del módulo principal que inicia su aplicación:

import {bootstrap} from ''...''; import {provide} from ''...''; import {AppComponent} from ''...''; export function main(params) { bootstrap(AppComponent, [ provide(RequestOptions, { useFactory: () => { return new CustomRequestOptions(params); }); ]); }

Luego puede importarlo desde su página principal HTML de esta manera:

<script> var params = {"token": "@User.Token", "xxx": "@User.Yyy"}; System.import(''app/main'').then((module) => { module.main(params); }); </script>

Consulte esta pregunta: Pase valores constantes a angular desde _layout.cshtml .


actualización2

Ejemplo de Plunker

actualizar AoT

Para trabajar con AoT, el cierre de la fábrica debe retirarse

function loadContext(context: ContextService) { return () => context.load(); } @NgModule({ ... providers: [ ..., ContextService, { provide: APP_INITIALIZER, useFactory: loadContext, deps: [ContextService], multi: true } ],

Ver también https://github.com/angular/angular/issues/11262

actualizar un ejemplo final RC.6 y 2.0.0

function configServiceFactory (config: ConfigService) { return () => config.load(); } @NgModule({ declarations: [AppComponent], imports: [BrowserModule, routes, FormsModule, HttpModule], providers: [AuthService, Title, appRoutingProviders, ConfigService, { provide: APP_INITIALIZER, useFactory: configServiceFactory deps: [ConfigService], multi: true } ], bootstrap: [AppComponent] }) export class AppModule { }

Si no hay necesidad de esperar a que se complete la inicialización, también se puede usar el constructor de `class AppModule {}:

class AppModule { constructor(/*inject required dependencies */) {...} }

pista (dependencia cíclica)

Por ejemplo, inyectar el enrutador puede causar dependencias cíclicas. Para evitarlo, inyecte el Injector y obtenga la dependencia por

this.myDep = injector.get(MyDependency);

en lugar de inyectar MyDependency directamente como:

@Injectable() export class ConfigService { private router:Router; constructor(/*private router:Router*/ injector:Injector) { setTimeout(() => this.router = injector.get(Router)); } }

actualizar

Esto debería funcionar igual en RC.5 pero en su lugar agrega el proveedor a los providers: [...] del módulo raíz en lugar de bootstrap(...)

(No me he probado todavía).

actualizar

Aquí se explica un enfoque interesante para hacerlo completamente dentro de Angular https://github.com/angular/angular/issues/9047#issuecomment-224075188

Puede usar APP_INITIALIZER que ejecutará una función cuando se inicializa la aplicación y retrasará lo que proporciona si la función devuelve una promesa. Esto significa que la aplicación se puede inicializar sin tanta latencia y también puede usar los servicios existentes y las características del marco.

Como ejemplo, suponga que tiene una solución multi-tenanted donde la información del sitio se basa en el nombre de dominio desde el que se sirve. Puede ser [nombre] .letterpress.com o un dominio personalizado que coincida con el nombre de host completo. Podemos ocultar el hecho de que esto está detrás de una promesa usando APP_INITIALIZER .

En bootstrap:

{provide: APP_INITIALIZER, useFactory: (sites:SitesService) => () => sites.load(), deps:[SitesService, HTTP_PROVIDERS], multi: true}),

sites.service.ts:

@Injectable() export class SitesService { public current:Site; constructor(private http:Http, private config:Config) { } load():Promise<Site> { var url:string; var pos = location.hostname.lastIndexOf(this.config.rootDomain); var url = (pos === -1) ? this.config.apiEndpoint + ''/sites?host='' + location.hostname : this.config.apiEndpoint + ''/sites/'' + location.hostname.substr(0, pos); var promise = this.http.get(url).map(res => res.json()).toPromise(); promise.then(site => this.current = site); return promise; }

NOTA: config es solo una clase de configuración personalizada. rootDomain sería ''.letterpress.com'' para este ejemplo y permitiría cosas como aptaincodeman.letterpress.com .

Cualquier componente y otros servicios ahora pueden inyectar el Site en ellos y usar la propiedad .current que será un objeto poblado concreto sin necesidad de esperar ninguna promesa dentro de la aplicación.

Este enfoque parecía reducir la latencia de inicio, que de otra manera era bastante notable si estaba esperando que se cargara el paquete angular grande y luego otra solicitud http antes de que comenzara el arranque.

original

Puede pasarlo usando la inyección de dependencia de Angulares:

var headers = ... // get the headers from the server bootstrap(AppComponent, [{provide: ''headers'', useValue: headers})]);

class SomeComponentOrService { constructor(@Inject(''headers'') private headers) {} }

o proporcionar BaseRequestOptions preparadas directamente como

class MyRequestOptions extends BaseRequestOptions { constructor (private headers) { super(); } } var values = ... // get the headers from the server var headers = new MyRequestOptions(values); bootstrap(AppComponent, [{provide: BaseRequestOptions, useValue: headers})]);