или же

ой 4.Github источник

У меня есть меню, которое заполняется веб-сервисом. Веб-сервис находится в taskService, но сейчас не нужен.

ngOnInit() {
    this.getTasks();
    }
    getTasks(): void {
        this.taskService.getTasks()
            .subscribe(Tasks => this.tasks = Tasks);
    } 

Когда вы нажимаете на задачу, она загружает страницу, другой компонент, с формой, готовой для обновления данных. Он также сделан веб-сервисом и работает нормально.Проблема в том, что после обновления задачи она не отражается в меню задач

Я импортирую это:

import { Component, OnInit, ChangeDetectorRef } from '@angular/core';

и добавив это в конструктор:

private cdRef: ChangeDetectorRef

И это мой лучший подход к функции deteChanges (),после обновления данных с помощью функции save ()

  this.taskService.updateTask(task, id)
          .subscribe(
              this.Ref.detach();
              setInterval(() => {
                this.Ref.detectChanges();
              }, 5000);
      );

Это HTML-код из меню для печати задач:

   <li *ngFor="let task of tasks" class="d-inline-block col-md-12">
        <a routerLink="/task/{{task.id}}" > {{task.title}}</a>
        <!-- <span class="close big"></span> -->
        <button class="close big" title="delete task"
        (click)="delete(task)">x</button>
    </li>

И это форма, которая обновляет задачу

<form (ngSubmit)="save(taskName.value, taskBody.value)" #taskForm="ngForm" class="example-form">
  <mat-form-field class="example-full-width">
    <label>Task Name</label>
    <input matInput [(ngModel)]="task.name" #taskName name="name">
  </mat-form-field>

  <mat-form-field class="example-full-width">
    <textarea matInput [(ngModel)]="task.body" #taskBody name="body"></textarea>

  </mat-form-field>
  <button type="submit" class="btn btn-success" >Save</button>
</form>

Оба находятся в разных компонентах.

Я пытался следовать этомуруководство, но я застрял, я не знаю, как использовать ChangeDetectorRef.

 ValRob20 дек. 2017 г., 20:46
@BunyaminCoskuner нет, ничего такого, я должен сделать это вручную, потому что они находятся в разных компонентах. Смотри вот полныйпроект:
 ValRob20 дек. 2017 г., 20:40
сделано @BunyaminCoskuner
 Bunyamin Coskuner20 дек. 2017 г., 20:35
Можете ли вы опубликовать свой HTML-файл тоже?
 Bunyamin Coskuner20 дек. 2017 г., 20:45
Я пытаюсь понять, почему вам нужно вызватьchangeDetection вручную. Angular должен поднять его при обновленииtasks, Вы устанавливаетеchangeDetectionStrategy в вашейComponent декларация?
 bazzells20 дек. 2017 г., 20:46
Вы подтвердили, чтоthis.tasks в вашей подписке обратный вызов переопределяется с обновленными данными из формы отправки?

Ответы на вопрос(2)

changeDetection потому что вы не просите об этом. Ни одна из переменных экземпляра в вашемViewTaskComponent обновляются внутри вашегоsave метод.

В вашем коде послеupdateTask() заканчивается, он возвращается кsave() в вашейViewTaskComponent, Но нет ссылки наthis.task в обратном вызове подписки наthis.taskService.updateTask().

посколькуupdateTask использует запрос PATCH, я предполагаю, что вы не получаете весьTask Возврат Так что вы не сможете просто сказатьthis.task = valuePassedToSubscribeCallback.

Вместо этого вы можете вызватьthis.viewTask() в этом подписаться обратный вызов и получить все обновленноеTask объект.

Например:

this.taskService.updateTask(task, id)
    .subscribe(
        // new line here to fetch the updated Task object
        this.viewTask()
    );

Примечание: я бы поддержал предложение @Bunyamin Coskuner об использованииBehaviorSubjectх (или даже стандартSubject). Если вы готовы к рефакторингу, это чистый способ управления состоянием в ваших сервисах.

 ValRob20 дек. 2017 г., 22:02
Я не знаю, как войти, но я получил ошибкуStaticInjectorError[NavigationComponent]: NullInjectorError: No provider for NavigationComponent!
 ValRob20 дек. 2017 г., 22:18
сделано, но это не работает. Я ничего не получаю послеsave() функция. :(
 bazzells20 дек. 2017 г., 22:34
Вы имеете в видуNavigationComponent не обновляется? Для того, чтобы это работало, я бы порекомендовал реализоватьSubject или жеBehaviorSubject.
 bazzells20 дек. 2017 г., 22:08
Это вызвано тем, что в строке 32 view-task.component.ts вы инициализировали свойNavigationComponent приватная переменная в вашем классе. Вам не нужно, хотя. Есть ли причина, по которой у вас это есть? Попробуйте хотя бы закомментировать его и посмотреть, работает ли он.
Решение Вопроса

view-task.component обновляет ваши задачи, ноnavigation.component не уведомлен об этой транзакции. думаюBehaviorSubject может быть, просто вещь для вас.

Вы можете прочитать больше об этомВот

Я предполагаю, что у вас будет один массивtasks во всем приложении, и вы бы отображали их наnavigation составная часть.

Task.service.ts

export class TaskService {
     // behaviorSubject needs an initial value.
     private tasks: BehaviorSubject = new BehaviorSubject([]);
     private taskList: Task[];

     getTasks() {
         if (!this.taskList || this.taskList.length === 0) {
             this.initializeTasks();
         }

         return this.tasks.asObservable();
     }

     initializeTasks() {
          this.http.get('api/tasks')
              .subscribe(tasks => {
                   // next method will notify all of the subscribers
                   this.tasks.next(tasks);
              }, error => {
                   // proper error handling here
              });
     }

     updateTasks(task: Task) {
          this.http.post('api/updateTask')
              .subscribe(resp => {
                   // update your tasks array
                   this.tasks = ...
                   // and call next method of your behaviorSubject with updated list
                   this.tasks.next(this.tasks);
              }, error => {
                   // proper error handling here    
              });
     }
}

Navigation.component.ts

 export class NavigationComponent implements OnInit{
      tasks: Task[];
      constructor(private taskService: TaskService) {}

      ngOnInit() {
          // this method will be called every time behaviorSubject
          // emits a next value.
          this.taskService.getTasks()
              .subscribe(tasks => this.tasks = tasks);
      }
 }

Просмотр-task.component.ts

 export class ViewTaskComponent {
     constructor(private taskService: TaskService) {}

     updateTask(task: Task) {
         this.taskService.updateTask(task);
     }
 }

Я не пробовал этот код сам. Тем не менее, я реализовал нечто подобное в моем приложении раньше. Поэтому, когда вы попробуете это и у вас возникнут проблемы, дайте мне знать.

 ValRob21 дек. 2017 г., 12:01
Хорошо, спасибо, это работает, но с парой вещей по-другому:service.ts , вид-task.ts иnavitation.ts.
 Bunyamin Coskuner21 дек. 2017 г., 13:11
Я рад, что это работает, только одна заключительная нота. Вам не нужно возвращатьсяSubscriptionнаверное никто с этим ничего не сделает
 Bunyamin Coskuner21 дек. 2017 г., 10:56
Вы определяете свой тип возврата какObservable<Task[]>, но вы подписываетесь на запрос http. Если вы хотите вернуть Observable, вы не можете подписаться на него. Если вы просто хотите получить данные и присвоить их какому-либо атрибуту, вы должны подписаться на них, но не можете определить свой тип возврата какObservable, Вы должны сделать одно или другое.
 ValRob21 дек. 2017 г., 10:51
У меня есть запрос http, который дает проблему:initializeTasks(): Observable<Task[]> { const url =$ {this.mainUrl} / задачи; const returnGets = this.http.get<Task[]>(url) .subscribe (tasks => { this.tasks.next(tasks); }); return returnGets } Сказал, что тип'подписка' нельзя назначить типу'observable<Task>', Свойство'_isScalar' отсутствует в подписке
 ValRob21 дек. 2017 г., 12:01
Это моеupdatetask() в настоящее время:updateTask (task: Task, id){ const url = ${this.mainUrl}/node/${id}; return this.http.patch(url, task, httpHaljson) .subscribe(resp => { this.initializeTasks() }); }

Ваш ответ на вопрос