Angular 4: Вид не обновляется после смены модели? - PullRequest
0 голосов
/ 27 июня 2018

У меня есть два component в моем приложении, то есть: HeaderComponent & TestComponent. В HeaderComponent есть имя метода setUserData () . Я называю это setUserDate () из метода TestComponent ansSubmit(), который находится в файле test.component.ts.

Теперь setUserDate() вызывает и значение приходит в setUserDate() метод.

Проблема в том, что при setUserDate() вызове я устанавливаю значение счета в this.userData.score , И this.userData.score значение является обязательным в представлении (HTML), но значение из Метод TestComponent ansSubmit () не собирается обновлять представление , но значение присутствует в файле ts (я печатаю в консоли).

Вот код:

test.component.ts:

import { HeaderComponent } from '../../components/header/header.component';
@Component({
  selector: 'test-page',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.css'],
  providers: [HeaderComponent]
})

export class TestComponent implements OnInit {
  private userData: any = {};

  constructor(private _router: Router, private headerComponent: HeaderComponent) { }

  ansSubmit() {
    const logged_in_user = new LocalStorage(environment.localStorageKeys.ADMIN);
    this.userData = logged_in_user.value;
    this.userData['score'] = parseInt(this.userData.score) + 54321 

    this.headerComponent.getUserData(this.userData['score']); // Calling HeaderComponent's method  value is 54321.
  }
}

test.component.html:

 <div class="col-2">
     <button (click)="ansSubmit()" >
          <div>Submit Answer</div>
      </button>
</div>

header.component.ts:

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


@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css'],

})

export class HeaderComponent implements OnInit {
    public userData : any = {
      score:2000,
   };

  getUserData(score) { // score= 54321  ( value is coming )  
       this.userData.score = score ;
       console.log(this.userData.score);  // in this.userData.score = 54321  ( Value is assigning )
     } 
  }
}

header.component.html:

<span class="topbar-details">
            Scrore : {{userData.score }}  // actual problem is here, Its not updating value. Its only showing 2000.
</span>

Пожалуйста, предложите мне, как решить эту проблему. Заранее спасибо.

Ответы [ 5 ]

0 голосов
/ 10 июля 2018

Я полагаю, что причина, по которой вы боретесь, заключается в том, что у вас, кажется, есть родственные компоненты, пытающиеся манипулировать данными, в которых ни один из них не является истинным владельцем данных. Angular пытается принудительно установить однонаправленный поток данных , который просто означает передачу данных от родителя к потомку, а не от потомка к родителю. Самый простой способ решить вашу проблему - это иметь родительский компонент, который «владеет» userData, а дочерние компоненты связываются с данными для их отображения и генерируют события для манипулирования ими.

Используя ваш сценарий в качестве примера:

app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  public userData: any = {
    score: 2000
};

 updateScore(score: number): void {
   this.userData.score += score;
 }
}

app.component.html

<app-header [score]="userData.score"></app-header>
<app-test (onScoreChange)="updateScore($event)"></app-test>

header.component.ts

import {Component, OnInit, Input} из '@ angular / core';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
  @Input('score') score: number;

  constructor() { }

  ngOnInit() {
  }

}

header.component.html

<span class="topbar-details">
  Scrore : {{score}}
</span>

test.component.ts

import {Component, OnInit, Output, EventEmitter} из '@ angular / core';

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.css']
})
export class TestComponent implements OnInit {
  @Output('onScoreChange') onScoreChange = new EventEmitter<number>();

  constructor() { }

  ngOnInit() {
  }

  ansSubmit() {
    this.onScoreChange.emit(54321);
  }
}

test.component.html

<div class="col-2">
  <button (click)="ansSubmit()" >
    <div>Submit Answer</div>
  </button>
</div>

Примечание: Что касается загрузки пользовательской информации из локального хранилища, я бы использовал службу для ее обработки. Где и как загружаются пользовательские данные, на самом деле не касается компонентов, которые отображают данные и управляют ими. Перемещение этой логики в службу с надлежащим интерфейсом (вероятно, возвращающую наблюдаемые, если данные могут когда-либо поступить из удаленного местоположения) позволит вам беспрепятственно поменять службу на основе локального хранилища на службу на основе HTTP, чтобы принудительно передать все оценки к / с сервера без изменения строки кода в вашем компоненте. Это также позволит вам поменяться в фиктивной службе для тестирования, поэтому для прохождения теста не нужно заполнять локальное хранилище (т. Е. Ваши тесты должны знать меньше о реализации вашего компонента для прохождения, поэтому они будут не быть таким хрупким при изменениях реализации)

0 голосов
/ 03 июля 2018

Попробуйте реализовать OnChanges для HeaderComponent

export class MyComponent implements OnInit, OnChanges {
 ngOnChanges(changes: SimpleChanges): void {
   // do your action
 }
}

Я предлагаю вам использовать угловой сервис или @Output, а также отправлять события в корень и прослушивать их в заголовке. Пожалуйста, ознакомьтесь с основными типами реактивности, представленными угловыми значениями. Слушатель OnChanges предназначен для прослушивания изменений, сделанных вне угла (например, в библиотеке). Вы должны использовать это только в крайнем случае!

0 голосов
/ 27 июня 2018

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

Данные компонента:

@Output() userDataEvent = new EventEmitter<any>();
----
getUserData(score?){
      this.score=score?score:this.userData.score;     
      console.log("getUserData called :"+this.score);  
      this.userDataEvent.emit(this.score);
 }

Дисплей Компонента:

<your-component (userDataEvent)='setUserData($event)'></your-component>

А затем, setUserData - это функция, которая знакомит вас с данными из вашего другого компонента

0 голосов
/ 29 июня 2018

Вы добавляете HeaderComponent в качестве провайдера, поэтому он, вероятно, создает новый экземпляр компонента. Если у вас есть существующий HeaderComponent, вам необходимо получить доступ к этому экземпляру, поэтому использование службы будет полезно для сохранения ссылки на экземпляр компонента.

Лучше всего перенести счет в службу и использовать субъект для обновления его значения. Ознакомьтесь с их документацией: https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service. Действительно, любые стратегии, перечисленные в этой документации, должны быть полезны для вашей ситуации.

0 голосов
/ 27 июня 2018

Я думаю, что проблема в том, что существует несколько HeaderComponent больше, чем один. Возможно, это вызвано вашей инъекцией, которая

constructor(private _router: Router, private headerComponent: HeaderComponent) { }.

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

header.component.ts

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


@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css'],

})

export class HeaderComponent implements OnInit {
    static count:number = 0;
    public id:number = 0;
    public userData : any = {
      score:2000,
    };

    constructor(){
      HeaderComponent.count++;
      this.id = HeaderComponent.count
    }

    getUserData(score) { // score= 54321  ( value is coming )  
       this.userData.score = score ;
       console.log(`${this._id} : ${this.userData.score}`);  // in this.userData.score = 54321  ( Value is assigning )
    } 
  }
}

header.component.html

<span>id : {{id}}</span>
<span class="topbar-details">
   Scrore : {{userData.score }}  // actual problem is here, Its not updating value. Its only showing 2000.
</span>

Если id в представлении и id в консоли отличаются, это означает, что вы обновляете не экземпляр HeaderComponent в представлении, а другой экземпляр HeaderComponent, который печатает журнал в консоли.

Пожалуйста, попробуйте это и скажите мне результаты. Спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...