parametros - ¿Cómo paso datos a componentes enrutados angulares?
pasar datos entre componentes angular 5 (11)
Angular 7.2.0 introdujo una nueva forma de pasar los datos al navegar entre componentes enrutados:
<a routerLink = "/link"
[queryParams] = "{parameterName: objectToPass| json }">
sample Link
</a>
O:
@Component({
template: `<a (click)="navigateWithState()">Go</a>`,
})
export class AppComponent {
constructor(public router: Router) {}
navigateWithState() {
this.router.navigateByUrl(''/123'', { state: { hello: ''world'' } });
}
}
Para leer el estado, puede acceder a la propiedad
window.history.state
después de que la navegación haya finalizado:
@Component({
selector: ''my-app'',
template: `
<a routerLink="/details" [state]="{ hello: ''world'' }">Go</a>`,
})
export class AppComponent {}
En una de las plantillas de mis rutas de Angular 2 ( FirstComponent ) tengo un botón
first.component.html
<div class="button" click="routeWithData()">Pass data and route</div>
Mi objetivo es lograr:
Haga clic en el botón -> diríjase a otro componente mientras conserva los datos y sin usar el otro componente como directiva.
Esto es lo que probé ...
1er ENFOQUE
En la misma vista, estoy almacenando la recopilación de los mismos datos en función de la interacción del usuario.
first.component.ts
export class FirstComponent {
constructor(private _router: Router) { }
property1: number;
property2: string;
property3: TypeXY; // this a class, not a primitive type
// here some class methods set the properties above
// DOM events
routeWithData(){
// here route
}
}
Normalmente me dirigiría a SecondComponent por
this._router.navigate([''SecondComponent'']);
eventualmente pasando los datos por
this._router.navigate([''SecondComponent'', {p1: this.property1, p2: property2 }]);
mientras que la definición del enlace con parámetros sería
@RouteConfig([
// ...
{ path: ''/SecondComponent/:p1:p2'', name: ''SecondComponent'', component: SecondComponent}
)]
El problema con este enfoque es que supongo que no puedo pasar datos complejos (por ejemplo, un objeto como propiedad3) en la URL;
2º ENFOQUE
Una alternativa sería incluir SecondComponent como directiva en FirstComponent.
<SecondComponent [p3]="property3"></SecondComponent>
Sin embargo, quiero enrutar a ese componente, ¡no incluirlo!
3er ENFOQUE
La solución más viable que veo aquí sería usar un Servicio (por ejemplo, FirstComponentService) para
- almacenar los datos (_firstComponentService.storeData ()) en routeWithData () en FirstComponent
- recuperar los datos (_firstComponentService.retrieveData ()) en ngOnInit () en SecondComponent
Si bien este enfoque parece perfectamente viable, me pregunto si esta es la forma más fácil / elegante de lograr el objetivo.
En general, me gustaría saber si me faltan otros enfoques potenciales para pasar los datos entre componentes, particularmente con la menor cantidad de código posible
Creo que dado que no tenemos el tipo de cosa $ rootScope en angular 2 como en angular 1.x. Podemos usar el servicio / clase angular 2 mientras que en ngOnDestroy pase los datos al servicio y, después del enrutamiento, tomemos los datos del servicio en la función ngOnInit :
Aquí estoy usando DataService para compartir el objeto héroe:
import { Hero } from ''./hero'';
export class DataService {
public hero: Hero;
}
Pase el objeto del primer componente de la página:
ngOnDestroy() {
this.dataService.hero = this.hero;
}
Tomar objeto del componente de la segunda página:
ngOnInit() {
this.hero = this.dataService.hero;
}
Aquí hay un ejemplo: plunker
El tercer enfoque es la forma más común de compartir datos entre componentes. puede inyectar el servicio del elemento que desea usar en un componente relacionado.
goToPage(pageNum) {
this.router.navigate([''/product-list''], { queryParams: { serviceId: serviceId} });
}
Este otro enfoque no es bueno para este problema.
Creo que el mejor enfoque es
Query-Parameter
by
Router
angular que tiene 2 vías:
Pasando el parámetro de consulta directamente
Con este código puede navegar a
url
por
params
en su código html:
import { Injectable } from ''@angular/core'';
import { Predicate } from ''../interfaces''
import * as _ from ''lodash'';
@Injectable()
export class ItemsService {
constructor() { }
removeItemFromArray<T>(array: Array<T>, item: any) {
_.remove(array, function (current) {
//console.log(current);
return JSON.stringify(current) === JSON.stringify(item);
});
}
removeItems<T>(array: Array<T>, predicate: Predicate<T>) {
_.remove(array, predicate);
}
setItem<T>(array: Array<T>, predicate: Predicate<T>, item: T) {
var _oldItem = _.find(array, predicate);
if(_oldItem){
var index = _.indexOf(array, _oldItem);
array.splice(index, 1, item);
} else {
array.push(item);
}
}
addItemToStart<T>(array: Array<T>, item: any) {
array.splice(0, 0, item);
}
getPropertyValues<T, R>(array: Array<T>, property : string) : R
{
var result = _.map(array, property);
return <R><any>result;
}
getSerialized<T>(arg: any): T {
return <T>JSON.parse(JSON.stringify(arg));
}
}
export interface Predicate<T> {
(item: T): boolean
}
Pasar parámetro de consulta por
Router
Tienes que inyectar el enrutador dentro de tu
constructor
como:
export class AdminUserListComponent {
users : User[];
constructor( private router : Router) { }
modifyUser(i) {
let navigationExtras: NavigationExtras = {
queryParams: {
"user": JSON.stringify(this.users[i])
}
};
this.router.navigate(["admin/user/edit"], navigationExtras);
}
}
Ahora use eso como:
export class AdminUserEditComponent {
userWithRole: UserWithRole;
constructor( private route: ActivatedRoute) {}
ngOnInit(): void {
super.ngOnInit();
this.route.queryParams.subscribe(params => {
this.userWithRole.user = JSON.parse(params["user"]);
});
}
}
Ahora, si desea leer desde el
Router
en otro
Component
, debe usar
ActivatedRoute
como:
<a [routerLink]="[''customer-service'']" [queryParams]="{ serviceId: 99 }"></a>
y
subscribe
que:
constructor(private router:Router){
}
Pase usando JSON
export class PageComponent implements OnInit {
state$: Observable<object>;
constructor(public activatedRoute: ActivatedRoute) {}
ngOnInit() {
this.state$ = this.activatedRoute.paramMap
.pipe(map(() => window.history.state))
}
}
Solución con ActiveRoute (si desea pasar un objeto por ruta, use JSON.stringfy / JSON.parse):
Prepare el objeto antes de enviarlo:
constructor(private activateRouter:ActivatedRouter){
}
Reciba su objeto en el componente de destino:
ngOnInit() {
this.sub = this.route
.queryParams
.subscribe(params => {
// Defaults to 0 if no query param provided.
this.page = +params[''serviceId''] || 0;
});
}
Una persona súper inteligente (tmburnell) que no soy yo sugiere reescribir los datos de la ruta:
let route = this.router.config.find(r => r.path === ''/path'');
route.data = { entity: ''entity'' };
this.router.navigateByUrl(''/path'');
Como se ve here en los comentarios.
Espero que alguien encuentre esto útil
di que tienes
- component1.ts
- componente1.html
y desea pasar datos a component2.ts .
-
en component1.ts es una variable con datos que dicen
//component1.ts item={name:"Nelson", bankAccount:"1 million dollars"} //component1.html //the line routerLink="/meter-readings/{{item.meterReadingId}}" has nothing to //do with this , replace that with the url you are navigating to <a mat-button [queryParams]="{ params: item | json}" routerLink="/meter-readings/{{item.meterReadingId}}" routerLinkActive="router-link-active"> View </a> //component2.ts import { ActivatedRoute} from "@angular/router"; import ''rxjs/add/operator/filter''; /*class name etc and class boiler plate */ data:any //will hold our final object that we passed constructor( private route: ActivatedRoute, ) {} ngOnInit() { this.route.queryParams .filter(params => params.reading) .subscribe(params => { console.log(params); // DATA WILL BE A JSON STRING- WE PARSE TO GET BACK OUR //OBJECT this.data = JSON.parse(params.item) ; console.log(this.data,''PASSED DATA''); //Gives {name:"Nelson", bankAccount:"1 //million dollars"} }); }
use un servicio compartido para almacenar datos con un índice personalizado. luego envíe ese índice personalizado con queryParam. Este enfoque es más flexible .
// component-a : typeScript :
constructor( private DataCollector: DataCollectorService ) {}
ngOnInit() {
this.DataCollector[''someDataIndex''] = data;
}
// component-a : html :
<a routerLink="/target-page"
[queryParams]="{index: ''someDataIndex''}"></a>
.
// component-b : typeScript :
public data;
constructor( private DataCollector: DataCollectorService ) {}
ngOnInit() {
this.route.queryParams.subscribe(
(queryParams: Params) => {
this.data = this.DataCollector[queryParams[''index'']];
}
);
}
actualización 4.0.0
Ver documentos angulares para más detalles https://angular.io/guide/router#fetch-data-before-navigating
original
Usar un servicio es el camino a seguir. En los parámetros de ruta, solo debe pasar los datos que desea que se reflejen en la barra de URL del navegador.
Ver también https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service
El enrutador enviado con RC.4 reintroduce
data
constructor(private route: ActivatedRoute) {}
const routes: RouterConfig = [
{path: '''', redirectTo: ''/heroes'', pathMatch : ''full''},
{path : ''heroes'', component : HeroDetailComponent, data : {some_data : ''some value''}}
];
class HeroDetailComponent {
ngOnInit() {
this.sub = this.route
.data
.subscribe(v => console.log(v));
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}
Vea también el Plunker en https://github.com/angular/angular/issues/9757#issuecomment-229847781
<div class="button" click="routeWithData()">Pass data and route</div>
bueno, la forma más fácil de hacerlo en angular 6 u otras versiones, espero es simplemente definir su ruta con la cantidad de datos que desea pasar
{path: ''detailView/:id'', component: DetailedViewComponent}
Como puede ver en mi definición de rutas, agregué el
/:id
para soportar los datos que quiero pasar al componente a través de la navegación del enrutador.
Por lo tanto, su código se verá así
<a class="btn btn-white-view" [routerLink]="[ ''/detailView'',list.id]">view</a>
para leer la
id
en el componente, simplemente importe
ActivatedRoute
como
import { ActivatedRoute } from ''@angular/router''
y en el
ngOnInit
es donde recuperas los datos
ngOnInit() {
this.sub = this.route.params.subscribe(params => {
this.id = params[''id''];
});
console.log(this.id);
}
Puedes leer más en este artículo https://www.tektutorialshub.com/angular-passing-parameters-to-route/