将数据从兄弟组件传递到另一个Angular 2

时间:2017-06-20 23:08:48

标签: angular typescript

我试图自学Angular 2(嗯..实际上是Angular 4,但谷歌的编号方案有点时髦)。无论如何,到目前为止,我已经能够通过angular.io中的示例以及在stackoverflow上回答的问题找出如何使一切正常工作。然而,这个让我很难过。

所以这就是我的问题,我正在尝试构建一个搜索页面,可以使用两个不同的组件,一个搜索栏和一个结果页面来筛选大量的JSON数据文件(如果有&#39)更好的方法是做到这一点,我的所有耳朵都是。我已经获得搜索栏来收集数据,并将数据通过路由器传递到结果页面,它实际上会进行查询和过滤,但我无法获得结果页面从查询字符串中读取数据。以下是相关文件。

搜索-bar.component.ts

import { Component } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'search-bar',
  templateUrl: './search-bar.component.html',
  styleUrls: ['./search-bar.component.css']
})
export class SearchbarComponent {

    langSelect: string = 'english'; // Default search language

    searchTerm: string;

    constructor(private router: Router) {}

    searchForTerm() {
        let data: string = this.searchTerm + '_' + this.langSelect
        this.router.navigate(['/results', {searchData: data}]);
    }
}

搜索-results.component.ts

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';

import { WordEntry } from '../../shared/models/word-entry';
import { DataRetrievalService } from '../../shared/services/data-retrieval.service';

@Component({
    templateUrl: './search-results.component.html',
    styleUrls: ['./search-results.component.css']
})
export class SearchResultsComponent implements OnInit {
    searchData: string; // Two parameters separated by '_'. search term is on the left and the language on the right


    constructor(private dataSvc: DataRetrievalService, private route: ActivatedRoute) {}

    ngOnInit() {
        console.log('starting!');

       this.route.params.subscribe((params: Params) => {
           this.searchData = params['searchData'];
           console.log(this.searchData);
       });
    }
}

----------- ------------编辑

search.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule, Routes } from '@angular/router';
import { FormsModule } from '@angular/forms';

import { SearchbarComponent } from './searchBar/search-bar.component';
import { SearchComponent } from './searchComponent/search.component';
import { SearchResultsComponent } from './searchResults/search-results.component';
import { DataRetrievalService } from '../shared/services/data-retrieval.service';

const SearchRoutes: Routes = [
    {
        path: 'search',
        component: SearchComponent,
        children: [
            { path: 'results', component: SearchResultsComponent }
        ]
    }
];

@NgModule({
    imports: [
        CommonModule,
        FormsModule,
        RouterModule.forChild(SearchRoutes)
    ],
    exports: [
        RouterModule,
        SearchbarComponent
    ],
    declarations: [
        SearchComponent,
        SearchbarComponent,
        SearchResultsComponent
    ],
    providers: [
        DataRetrievalService
    ]
})
export class SearchModule {}

这两个文件是搜索模块中的兄弟组件,每个组件都在各自的文件夹中。

我的问题是ngOnInit()看起来并不像它一样被调用,因为没有任何东西被打印到控制台,而且searchData类变量中没有任何内容。

关于我做错的任何想法?提前感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

我不是100%确定我做了什么的因果关系,而是将SearchbarComponent和SearchResultsComponent提取到主app模块中,而不是在搜索模块中,然后更改它以便数据被持久化到视图转换之间的服务,我让它工作。

我认为服务[最初​​]发生的事情是SearchbarComponent正在与app模块服务实例交谈(因为它目前是导航栏的一部分),而SearchResultsComponent正在与搜索模块服务交谈实例

以下是一些相关文件:

<强> app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule, JsonpModule } from '@angular/http';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './start/app.component';
import { HomeComponent } from './home/home.component';
import { ErrorComponent} from './error/error.component';
import { NavComponent } from './shared/navbar/navbar.component';
import { AppRoutingModule } from './shared/app.routing';
import { SearchbarComponent } from './searchBar/search-bar.component';
import { SearchResultsComponent } from './searchResults/search-results.component';

import { WordEntry } from './shared/models/word-entry';
import { LexiconComponent } from './lexicon/lexicon.component';
import { DataRetrievalService } from './shared/services/data-retrieval.service';
import { TruncatePipe } from './shared/pipes/trunc.pipe';

@NgModule({
    imports: [
        BrowserModule,
        FormsModule,
        AppRoutingModule,
        HttpModule,
        JsonpModule
    ],
    exports: [
        TruncatePipe
    ],
    declarations: [
        AppComponent,
        NavComponent,
        HomeComponent,
        ErrorComponent,
        LexiconComponent,
        TruncatePipe,
        SearchbarComponent,
        SearchResultsComponent
    ],
    providers: [
        DataRetrievalService
    ],
    bootstrap: [ AppComponent ]
})
export class AppModule {}

<强> search.service.ts

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/Rx';
import { Observable } from 'rxjs/Observable';


@Injectable()
export class SearchService {

    private _searchData = new BehaviorSubject<string>(''); // Initialize with emtpy string

    setSearchData(data: string) {
        // Fire the update event with the new data
        this._searchData.next(data);
    }

    getSearchData(): Observable<string>  {
        return this._searchData.asObservable();
    }
}

搜索-bar.component.ts

import { Component } from '@angular/core';
import { Router } from '@angular/router';

import { DataRetrievalService } from '../shared/services/data-retrieval.service';

@Component({
    selector: 'search-bar',
    templateUrl: './search-bar.component.html',
    styleUrls: ['./search-bar.component.css']
})
export class SearchbarComponent {

    langSelect: string = 'english'; // Default search language

    searchTerm: string;

    constructor(private router: Router, private searchSvc: SearchService) {}

    searchForTerm() {
        let data: string = this.searchTerm + '_' + this.langSelect

        // Update the service
        this.searchSvc.setSearchData(data);

        // No need to change routes if you're already on that page, even if it's a no op.
        if (this.router.url != '/search') {
            this.router.navigate(['/search']);
        }
    }
}

搜索-results.component.ts

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';

import { WordEntry } from '../shared/models/word-entry';
import { DataRetrievalService } from '../shared/services/data-retrieval.service';

@Component({
    templateUrl: './search-results.component.html',
    styleUrls: ['./search-results.component.css']
})
export class SearchResultsComponent {
    searchData: string; // Two parameters separated by '_'. search term is on the left and the language on the right

    constructor(private dataSvc: DataRetrievalService, private searchSvc: SearchService) {
        // This should trigger anytime the searchbar is submitted
        this.searchSvc.getSearchData().subscribe(searchData => {

            // Don't even bother searching for an empty string
            if (searchData != '') {
                let parts = searchData.split('_', 2);

                // Clear the searchResults, otherwise it just appends to the list with each search
                this.searchResults = [];

                this.searchForWord(parts[0], parts[1]);
            }
        });
    }
}

搜索-result.component.html

<nav-bar></nav-bar>

{{searchData}}

我希望这有助于某些人下线。