首页 文章

如何将数据传递给Angular路由组件?

提问于
浏览
125

在我的一个Angular 2路线模板( FirstComponent )中,我有一个按钮

first.component.html

<div class="button" click="routeWithData()">Pass data and route</div>

我的 goal 是为了实现:

按钮单击 - >路由到另一个组件,同时保留数据,而不使用其他组件作为指令 .

这就是我试过的......

1ST APPROACH

在同一视图中,我存储基于用户交互收集相同的数据 .

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
    }
}

通常我会路由到 SecondComponent

this._router.navigate(['SecondComponent']);

最终传递数据

this._router.navigate(['SecondComponent', {p1: this.property1, p2: property2 }]);

而带参数的链接的定义是

@RouteConfig([
      // ...
      { path: '/SecondComponent/:p1:p2', name: 'SecondComponent', component: SecondComponent} 
)]

这种方法的问题是我猜 I can't pass complex data (例如 object like property3)in-url;

2ND APPROACH

另一种方法是在FirstComponent中将SecondComponent包含为 directive .

<SecondComponent [p3]="property3"></SecondComponent>

但是我想 route 到那个组件,不包括它!

3RD APPROACH

我在这里看到的最可行的解决方案是使用 Service (例如FirstComponentService)

  • store FirstComponent中routeWithData()上的数据(_firstComponentService.storeData())
    159 retrieve SecondComponent 中的数据(_firstComponentService.retrieveData()) SecondComponent

虽然这种方法似乎完全可行,但我想知道这是否是实现目标的最简单/最优雅的方式 .

一般来说,我'd like to know whether I' m缺少其他 potential approaches 来传递组件之间的数据,特别是 with the less possible amount of code

7 回答

  • 93

    第三种方法是在组件之间共享数据的最常用方法 . 您可以注入要在相关组件中使用的项目服务 .

    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
    }
    
  • 43
    `<div class="button" click="routeWithData()">Pass data and route</div>`
    

    以角度6或其他版本执行此操作的最简单方法我希望只需使用您要传递的数据量来定义路径

    `{path: 'detailView/:id', component: DetailedViewComponent}`
    

    正如你从我的路线定义中看到的那样,我已经添加了 /:id 来支持我想通过路由器导航传递给组件的数据 . 因为你的代码看起来像

    `<a class="btn btn-white-view" [routerLink]="[ '/detailView',list.id]">view</a>`
    

    为了读取组件上的 id ,只需导入 ActivatedRoute 就好了

    `import { ActivatedRoute } from '@angular/router'`
    

    并在 ngOnInit 上检索数据

    `ngOnInit() {
           this.sub = this.route.params.subscribe(params => {
            this.id = params['id'];
            });
            console.log(this.id);
          }`
    

    你可以在这篇文章中阅读更多https://www.tektutorialshub.com/angular-passing-parameters-to-route/

  • 5

    我想因为我们在角度2中没有像角度1.x那样的东西 . 我们可以使用angular 2共享服务/类,而在 ngOnDestroy 传递数据到服务,并在路由后从 ngOnInit 函数中获取服务中的数据:

    Here I am using DataService to share hero object:

    import { Hero } from './hero';
    export class DataService {
      public hero: Hero;
    }
    

    Pass object from first page component:

    ngOnDestroy() {
        this.dataService.hero = this.hero; 
     }
    

    Take object from second page component:

    ngOnInit() {
        this.hero = this.dataService.hero; 
     }
    

    这是一个例子:plunker

  • 0

    update 4.0.0

    有关详细信息,请参阅Angular文档https://angular.io/guide/router#fetch-data-before-navigating

    original

    使用服务是可行的方法 . 在路径参数中,您应该只传递要在浏览器URL栏中反映的数据 .

    另见https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service

    RC.4附带的路由器重新引入 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();
      }
    }
    

    另请参阅https://github.com/angular/angular/issues/9757#issuecomment-229847781的Plunker

  • 2

    使用ActiveRoute的解决方案(如果您希望按路由传递对象 - 使用JSON.stringfy / JSON.parse):

    发送前准备对象:

    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);
      }
    
    }
    

    在目标组件中接收您的对象:

    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"]);
          });
      }
    
    }
    
  • 3

    Angular 6.1.5

    路由模块{路径:'用户视图',组件:UserViewComponent,数据:{some_data:'some value'}}


    组件从'@ angular / router'导入;

    @零件({
    选择器:'app-user-view',
    templateUrl:' . / user-view.component.html',
    styleUrls:[' . / user-view.component.css']
    })
    导出类UserViewComponent实现OnInit {

    构造函数(private activatedRoute:ActivatedRoute){}

    ngOnInit(){
    this.activatedRoute.data.subscribe(data => {
    的console.log(数据)
    })
    }
    }


    My project NgModule

    从'@ angular / core'导入;从'@ angular / platform-browser'导入;从'./app.component'导入;从'./user-view/user-view.component'导入;从'./app.routing'导入; @NgModule({declarations:[AppComponent,UserViewComponent],import:[BrowserModule,routing] bootstrap:[AppComponent]})export class AppModule {}


    Routing Module

    从'@ angular / router'导入{Routes,RouterModule};从'./user-view/user-view.component'导入;

    const appRoutes:Routes = [
    {path:'user-view',component:UserViewComponent,canActivate:[AuthGuard],data:{some_data:'some value'}}];

    export const routing = RouterModule.forRoot(appRoutes);

    routerLink in Html

    <a [routerLink]="['/user-view']"[queryParams]="{some_data:'I'm a data'}"> </a>

  • 2

    使用JSON传递

    <a routerLink = "/link"
       [queryParams] = "{parameterName: objectToPass| json }">
             sample Link                   
      </a>
    

相关问题