【问题标题】:angular 4 - update property in another component without parent child relationship角度 4 - 在没有父子关系的另一个组件中更新属性
【发布时间】:2017-10-01 13:23:52
【问题描述】:

我有 2 个不相关的组件,navbaredit-page

navbar 组件中,我从集合中获取页面标题列表,并使用edit-page 组件编辑页面标题,但因为我总是可以看到来自navbar 组件的所有页面标题,我希望在编辑页面标题后立即更新它。

如何在没有 @input@output 的情况下实现这一目标?据我了解,我应该创建某种共享服务,但我不知道该怎么做?

pages.service.ts

import { Http } from '@angular/http';
import { Injectable } from '@angular/core';
import 'rxjs/add/operator/map';

@Injectable()
export class PagesService {

    constructor(private http: Http) { }

    getPages() {
        return this.http.get('http://localhost:3000/pages')
            .map(res => res.json());
    }

    getEditPage(id) {
        return this.http.get('http://localhost:3000/pages/edit-page/' + id)
            .map(res => res.json());
    }

    postEditPage(value) {
        return this.http.post('http://localhost:3000/pages/edit-page/' + value.id, value)
            .map(res => res.json());
    }

}

导航栏组件

pages: any[];
ngOnInit() {
        this.pagesService.getPages().subscribe(pages => {
            this.pages = pages;
        });
    }

编辑页面组件

editPage({ value, valid }) {
        if (valid) {
            this.pagesService.postEditPage(value).subscribe(res => {
                if (res == "ok") {
                    this.successMsg = true;
                }

            });
        } else {
            console.log('Form is not valid');
        }
    }

所以在edit-page 组件中执行editPage 方法后,我希望navbar 组件中的pages 属性自动更新。

【问题讨论】:

  • 一个组件应该监听一个更新事件。
  • @RomanC 还有更多线索吗?我对 Angular 很陌生。
  • 不用@input和@output也能做到吗?
  • 如果您的父组件告诉孩子该做什么并且孩子应该回应父母已经完成的事情,那么它们是必不可少的。

标签: angular


【解决方案1】:

像这样使用 Observables。

import { BehaviorSubject } from "rxjs/BehaviorSubject";

export class MyService(){
public someProp  = new BehaviorSubject<string(null);

 }
 
 export class ComponentOne implements OnInit{
     constructor(private service:MyService){
    }
    ngOnInit(){
    //this will set the value of someProp
      this.service.someProp.next('some value')
    }
 
 }
 export class ComponentTwo implements OnInit{
    constructor(private service:MyService){
    }
    ngOnInit(){
        //this will get latest value from someProp
        // also will update when it changes
      this.service.someProp.subscribe(res=>{
      console.log('this is the current value',res)
      })
    
    }
 
 }
 

【讨论】:

  • 我正在使用 http.get 从数据库中获取值,它可以与这种方法一起使用吗?我已将当前 pagesService.ts 粘贴到我的问题中。
  • 你只需添加一个 BehaviorSubject 就像我展示的那样,你称之为模式或编辑模式,或者对你有意义。订阅它,它会自动改变。
  • 好的,到了那里。在我的 pages.service.ts 我有这个 public someProp = new BehaviorSubject&lt;string&gt;(null); 。我保留了someProp 这个名字,所以很容易被发现。现在我在 nginit 内的 navbar.component.ts 中设置它,就像 this.pagesService.getPages().subscribe(pages =&gt; { this.pagesService.someProp.next(pages); this.pages = this.pagesService.someProp; }); 这样有效,因为现在要遍历它,我必须使用 pages.value 而不仅仅是 pages,到目前为止一切都很好。但是当我在另一个组件中更新页面标题时如何更新呢?
  • 您可以在我的问题中的edit-page 组件中查看我是如何进行更新的。
  • 你只需调用 someProp.next() 每次你想更新它就可以了 if (res == "ok") { this.successMsg = true;this.service.someProp.next('update ...')。 }
【解决方案2】:

创建一个服务,该服务返回页面并在页面数组更改时使用 EventEmitter 发出事件。将 PagesService 注入您的 NavbarComponentEditPageComponent

在 EditPageComponent 中进行更改并更新 PageService 中的页面并发出 pagesChanged 事件。然后在 NavbarComponent订阅 pagesChanged 事件。

import { EventEmitter } from '@angular/core';
import { pages} from './../shared/pages.model';


export class PageService {

    pagesChanged = new EventEmitter<Pages[]>();

    private pages: Page[] = [
        new Page('PageName1'),
        new Page('PageName2'),
      ];    

      getPages() {
          return this.pages.slice();
      }

      editPage(page: Page) {
        // write you logic to edit the page or pages array.
        // Emit the pagesChanged event.
        this.pagesChanged.emit(this.pages.slice());
      }
}

并像这样订阅 NavabarComponent 中的 pagesChanged 事件。

import { Page} from './../shared/pages.model';
import { PagesService } from './pages.service';
import { Component, OnInit } from '@angular/core';


@Component({
  selector: 'app-navbar',
  templateUrl: './navbar.component.html',
  styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {
  pages: Page[];

  constructor(private pageService: PagesService) { }

  ngOnInit() {
    this.pages= this.pageService.getPages();
    this.pageService.pagesChanged
      .subscribe(
        (pages: Page[]) => {
          this.pages= pages;
        } 
      )
  }

}

希望这能解决您的问题。

【讨论】:

  • 我不明白,你看我是如何在导航栏中获取页面的,我如何将它移到服务中?我之前已经尝试过将其移至服务,但不能。
  • 我刚刚添加了 pages.service.ts 代码,所以也许有帮助
猜你喜欢
  • 1970-01-01
  • 2021-03-25
  • 2021-12-07
  • 2021-07-21
  • 2022-01-24
  • 1970-01-01
  • 1970-01-01
  • 2018-06-17
  • 2019-01-19
相关资源
最近更新 更多