【问题标题】:Why doesn't my Angular page refresh when using an EventEmitter?为什么我的 Angular 页面在使用 EventEmitter 时不刷新?
【发布时间】:2018-10-15 02:49:01
【问题描述】:

当我的 EventEmitter 发出事件时,我的 Angular SPA 不会刷新。

这是我在子组件中的EventEmitter

import { Component, OnInit, Output, EventEmitter } from '@angular/core';
import { Todo } from '../todo';

@Component({
  selector: 'app-add-todo',
  templateUrl: './add-todo.component.html',
  styleUrls: ['./add-todo.component.css']
})
export class AddTodoComponent implements OnInit {
  newTodo: Todo = new Todo();

  @Output() addTodoEvent: EventEmitter<Todo> = new EventEmitter();

  constructor() { }

  addTodo() {
    this.addTodoEvent.emit(this.newTodo);
    console.log('event emitted');
    this.newTodo = new Todo();
    console.log('new todo created');
  }

  ngOnInit() {
  }

}

这是使用它的模板:

<div class="container">
  <app-add-todo (addTodoEvent)='onAddTodo($event)'></app-add-todo>
   // other template stuff
</div>

这是onAddTodo的声明:

  onAddTodo(todo: Todo) {
    console.log('onAddTodo called');
    this.todoDataService.addTodo(todo);
  }

基本上,应用程序可以工作,但我必须在进行任何更改后按 F5 来刷新页面。

需要注意的一点是,这曾经在我使用数组作为数据源时起作用,但是当我转到 json-server 和 Observables 时,页面停止刷新。

我很乐意提供任何可能需要的进一步信息。

更新:

这里是addTodo

  addTodo(todo: Todo): void {
    this.aHttpService.post<Todo>(`http://localhost:3000/todos`, todo).subscribe(
      val => {
        console.log('POST call successful value returned in body', val);
      },
      response => {
        console.log('POST call in error', response);
      },
      () => {
        console.log('The POST observable is now completed.');
      }
    );
  }

列出待办事项的完整代码如下:

import { Component, OnInit } from '@angular/core';
import { Todo } from '../todo';
import { TodoDataService } from '../todo-data.service';
import { Observable } from 'rxjs/Observable';

@Component({
  selector: 'app-todo-list',
  templateUrl: './todo-list.component.html',
  styleUrls: ['./todo-list.component.css']
})
export class TodoListComponent implements OnInit {
  constructor(private todoDataService: TodoDataService) {}

  completetodos: Observable<Array<Todo>>;
  incompletetodos: Observable<Array<Todo>>;

  onAddTodo(todo: Todo) {
    console.log('onAddTodo called');
    this.todoDataService.addTodo(todo);
  }

  toggleTodoComplete(todo) {
    this.todoDataService.toggleTodoComplete(todo);
  }

  removeTodo(todo) {
    this.todoDataService.deleteTodoById(todo.id);
  }

  editTodo(todo: Todo) {
    todo.editMode = true;
  }

  updateTodo(todo: Todo, editInput) {
    todo.title = editInput.value;
    todo.editMode = false;
    this.todoDataService.updateTodoById(todo.id, todo);
  }

  allTasks(): Observable<Array<Todo>> {
    return this.todoDataService.getAllTodos();
  }

  completedTodos(): Observable<Array<Todo>> {
    return this.todoDataService.completedTodos();
  }

  incompletedToDos(): Observable<Array<Todo>> {
    return this.todoDataService.incompletedTodos();
  }

  ngOnInit() {
    this.completetodos = this.completedTodos();
    this.incompletetodos = this.incompletedToDos();
  }
}

【问题讨论】:

  • addTodo 正在执行 Http 调用?
  • @AlexanderStaroselsky -- 添加了我的addToDo 电话。
  • 用这样的零碎的sn-ps代码和明显的拼写错误有点难以弄清楚(你有一个名为'addTodoEvent'的EventEmitter,但调用了'add.emit')。一个完整的运行示例,也许在 stackblitz.com 上会有很大帮助。
  • 您需要澄清您希望在 post() 之后在屏幕上更新的内容。您是在发布成功后将新的 Todo 推送到数组中,还是在视图中显示任何内容?
  • @NickHodges 你能把你的代码贴在列出待办事项的地方吗?

标签: angular typescript eventemitter


【解决方案1】:

成功保存待办事项后,您必须更新可观察对象

 onAddTodo(todo: Todo) {
this.todoDataService.addTodo(todo).subscribe(
      val => {
         // here you have to update the observables //incompletetodos.next(newTodo)
      },
      response => {
        console.log('POST call in error', response);
      },
      () => {
        console.log('The POST observable is now completed.');
      }
    );
}

这里也不需要订阅

 addTodo(todo: Todo): void {
    return this.aHttpService.post<Todo>(`http://localhost:3000/todos`, todo);
  }

我认为 push 不适用于 observables ,您可以参考下面的链接将新项目附加到不完整的待办事项 observable 数组中

How can I append items to Observable

如果您使用 BehaviorSubject(另一种类型的 observable)而不是 Observable ,则可以轻松添加新项目。类似下面的东西

incompletetodos: BehaviorSubject<Array<Todo>> = BehaviorSubject.empty<Array<Todo>>();

//你可以像下面这样推送一个新项目

 incompletetodos.next(newTodo)

【讨论】:

    【解决方案2】:

    你的服务应该像这样返回 observable:

     addTodo(todo: Todo): void {
        return this.aHttpService.post<Todo>(`http://localhost:3000/todos`, todo);
     }
    

    并在组件中像这样使用它:

     onAddTodo(todo: Todo) {
        this.todoDataService.addTodo(todo).subscribe(val => {
           this.incompletetodos.push(val);
        });;
     }
    

    (我把代码最小化了)


    参考:https://angular.io/tutorial/toh-pt6#add-a-new-hero

    src/app/heroes/heroes.component.ts(添加)

    add(name: string): void {
      name = name.trim();
      if (!name) { return; }
      this.heroService.addHero({ name } as Hero)
        .subscribe(hero => {
          this.heroes.push(hero);
        });
    }
    

    src/app/hero.service.ts (addHero)

    /** POST: add a new hero to the server */
    addHero (hero: Hero): Observable<Hero> {
      return this.http.post<Hero>(this.heroesUrl, hero, httpOptions).pipe(
        tap((hero: Hero) => this.log(`added hero w/ id=${hero.id}`)),
        catchError(this.handleError<Hero>('addHero'))
      );
    }
    

    为什么我的 Angular 页面在使用 EventEmitter 时没有刷新?

    你可能会这样想,我们正在使用 Angular 构建一个不会导致任何全页刷新的单页应用程序,我们只是更新了网站的一部分。

    基本上,应用程序可以工作,但我必须按 F5 来刷新 进行任何更改后的页面。

    因为每当您按下 F5 时,您的 Angular 应用程序都会重新初始化,这会触发这个生命周期钩子:

    ngOnInit() {
        this.completetodos = this.completedTodos();
        this.incompletetodos = this.incompletedToDos();
    }
    

    因此,您的应用程序反映了数据库的最新数据。

    需要注意的一点是,当我使用数组时,这曾经可以工作 作为数据源,但是当我去 json-server 和 Observables 时, 页面停止刷新

    事实上,当您使用数组作为数据源时,我们的应用程序根本不会刷新。这就是所谓的数据绑定,我们在 UI 上看到的数据绑定到 Angular 应用程序持有的数据(在客户端,在客户端的内存中)。

    在与服务器通信时,当我们对服务器的数据库进行一些更改时,我们必须根据服务器的响应来更新客户端的数据。在这种情况下,我们将在您的 Todo 应用中这样做。

    【讨论】:

      猜你喜欢
      • 2021-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-25
      • 1970-01-01
      相关资源
      最近更新 更多