【问题标题】:View only updates on page reload?仅查看页面重新加载时的更新?
【发布时间】:2019-01-30 15:59:39
【问题描述】:

所以,我正在开发一个非常简单的 MEAN stack CRUD 应用程序,它允许用户添加、编辑、删除帖子并将它们显示在同一页面上。我目前没有使用路由,并且有两个组件,

1) 后期制作 2) 帖子列表

我正在使用一项服务将数据从创建后传递到帖子列表。

据我了解,post-list 组件是在应用加载时初始化的,这显然是调用了post-list 的ngOnInit(),并从服务器获取数据。

我希望在创建后组件中单击“保存”按钮时更新帖子列表中的“帖子”数组,这显然会更新帖子列表组件的视图,而不是更新它当页面重新加载并再次调用 ngOnInit() 时。

我只是不知道如何在不重新加载页面的情况下获取更新的数据。谢谢

服务:

post.service.ts

import { Post } from './posts.interface';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { map } from 'rxjs/operators';

@Injectable({
providedIn: 'root'
})

export class PostsService {

  uri = 'http://localhost:3000/api/posts';

  constructor(private http: HttpClient) {}

  getPosts(): Observable<Post[]> {
  return this.http.get<Post[]>(`${this.uri}`);
  }

  addPost(post: Post): Observable<Post> {
  return this.http.post<Post>(`${this.uri}`, post);
  }

post-create.component.html

<mat-card>
  <form>
    <mat-form-field>
     <input matInput type="text" name="title" minlength="3"
     [(ngModel)]="post.title" placeholder="Post Title">
    </mat-form-field>

   <mat-form-field>
    <textarea matInput rows="4" name="content" 
    [(ngModel)]="post.content"
    placeholder="Post Content">
    </textarea>
   </mat-form-field>

   <button mat-raised-button color="primary" class="save-btn" 
   (click)="onAddPost()">Save Post</button>
 </form>
</mat-card>

post-create.component.ts

import { Component, OnInit } from '@angular/core';
import { Post } from '../posts.interface';
import { PostsService } from '../posts.service';

@Component({
selector: 'app-posts-create',
templateUrl: './posts-create.component.html',
styleUrls: ['./posts-create.component.css']
})

export class PostsCreateComponent implements OnInit {

post: Post = {} as Post;

constructor(public postsService: PostsService) { }

ngOnInit() {
}

  onAddPost() {
  this.postsService.addPost(this.post).subscribe(post => {
  this.post = post;
  });
 }
}

posts-list.component.html

<mat-accordion multi="true">
  <mat-expansion-panel *ngFor="let post of posts">

    <mat-expansion-panel-header>{{post.title}}
    </mat-expansion-panel-header>
    <p>{{post.content}}</p>

  <mat-action-row>
   <button mat-button color="primary">EDIT</button>
   <button mat-button color="warn">DELETE</button>
  </mat-action-row>

 </mat-expansion-panel>
</mat-accordion>

posts-list.component.ts

import { Component, OnInit } from '@angular/core';
import { Post } from '../posts.interface';
import { PostsService } from '../posts.service';

@Component({
selector: 'app-posts-list',
templateUrl: './posts-list.component.html',
styleUrls: ['./posts-list.component.css']
})

export class PostsListComponent implements OnInit {

  posts: Post[];

  constructor(public postsService: PostsService) {}

  ngOnInit() {
  this.getAllPosts();
  }

  getAllPosts() {
  this.postsService.getPosts().subscribe((posts: Post[]) => {
    this.posts = posts;
    console.log(this.posts);
  });
 }
}

【问题讨论】:

    标签: angular rxjs observable


    【解决方案1】:

    您需要comunicate between both parent and child components,一种方法是使用eventemitter 和@Output 装饰器:

    首先,编辑您的子组件 post-create.component.ts 以添加 EventEmitter 以向您的父组件发出事件:

    import { Component, OnInit, EventEmitter, Output } from '@angular/core';
    ...
    
    export class PostsCreateComponent implements OnInit {
    
    @Output() emitNewPost = new EventEmitter();    
    ...
    
    onAddPost() {
      this.postsService.addPost(this.post).subscribe(post => {
        this.post = post;
        // Here we emit the event with your new post
        this.emitNewPost.emit(this.post);
      });
     }
    

    然后在父组件htmlposts-list.component.html中绑定html,注意我们使用emitNewPost,因为我们的属性是由@Output装饰器定义的:

        ...
          <mat-expansion-panel *ngFor="let post of posts" (emitNewPost)='addNewPost($event)'>
        ...
    

    最后,在你的父母 ts 文件 posts-list.component.ts 中添加方法,现在每次添加新帖子时都会触发 addNewPost:

    public addNewPost(post) {
      this.posts.push(post);
    }
    

    【讨论】:

    • 我读过输入和输出。我将如何处理服务?我已经阅读了“主题”并阅读了文档,但我对如何在我的代码中实现它感到困惑。
    • 如果您想从您的服务中执行此操作,您可以使用 BehaviorSubject,它始终保存最后一个值,但 subject 没有。但由于您订阅了您的组件,因此我会特别使用 EventEmitter 来处理这个用例,我看不出将它保留在服务中的好处。
    • 明白。顺便说一句,您给定的解决方案不起作用。还是要刷新页面才能更新视图。
    最近更新 更多