2017-05-21 3 views
0

최근에 Angular 1에서 Angular 4로 이동했으며 구성 요소 속성이 업데이트 될 때 DOM이 업데이트되지 않는 이유를 이해하는 데 약간의 어려움이 있습니다. 나는 수없이 많은 게시물을 검색하고 읽었으며 이에 대한 답변을 찾을 수 없습니다.Angular 2 구성 요소 속성이 변경 될 때 DOM 업데이트

나는 오류 메시지를 표시하는 구성 요소가있는 앱이라고 MessageComponent 있습니다

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

@Component({                            
    selector: 'message',                          
    templateUrl: './message.component.html',                     
    styleUrls: ['./message.component.css']                     
})                               

export class MessageComponent implements OnInit {                   

    messages: Array<string>;                         

    constructor() {                           

    }                               

    ngOnInit() {                            
    this.messages = ['My messages'];                      
    }                               

    /* Takes an array of messages */                       

    showErrors(errors) {                          
    this.messages = errors;                         
    } 
} 

템플릿은 간단하다 :

<div class="message">                          
    <p>Messages go here</p>                         
    <div class="error">                          
    <ul>                             
     <li *ngFor="let message of messages">{{message}}</li>                
    </ul>                             
    </div>                             
</div> 

내가 다른 구성 요소에서 showErrors 메소드를 호출하고 있습니다를 :

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

    import { MessageComponent } from '../message/message.component';               

    @Component({                            
    selector: 'app-signup',                         
    templateUrl: './signup.component.html',                     
    styleUrls: ['./signup.component.css']                      
    })                               
    export class SignupComponent implements OnInit {                   

    email: string;                           
    password: string;                           
    cardNumber: string;                          
    expiryMonth: string;                          
    expiryYear: string;                          
    cvc: string;                            
    plan: string;                            

    constructor(private activatedRoute: ActivatedRoute, private auth: Auth, private message: MessageComponent) { }   

    signupUser() {                           
     // do stuff here, then call back with status                                             
     }, (status: number, response: any) => {                     
     if (status == 200) {                         
      // yay, do success stuff                         
     } else {                            
      console.log('Error', response.error.message);                  
      this.message.showErrors([response.error.message]);                 
     }                              
     });                              
    } 

signupUser() THOD는 signup.component.html의 SignupComponent의 템플릿입니다이 양식에서 호출됩니다

<message></message>                          
<h1>Signup</h1>                           
<form (submit)="signupUser()">                       
    <div class="row">                          
    <div class="small-12 columns">                      
     <label>Email address                        
      <input type="text" [(ngModel)]="email" name="email">               
     </label>                           
    </div>                            
    </div>                             
    <div class="row">                          
    <div class="small-12 columns">                      
     <label>Password                          
     <input type="password" [(ngModel)]="password" name="password">             
     </label>                           
    </div>                            
    </div>                             
    <div class="row">                          
    <div class="small-12 columns">                      
     <label>Card Number                         
      <input type="text" [(ngModel)]="cardNumber" name="card-number" data-stripe="number">       
     </label>                           
    </div>                            
    </div>                             
    <div class="row">                          
    <div class="small-6 columns">                       
     <label>Expiration Date (MM/YY)                      
     <span><input type="text" size="2" [(ngModel)]="expiryMonth" name="expiry-month" placeholder="MM"><input type="text" size="2" [(ngModel)]="expiryYear" name="expiry-year" placeholder="YY"></span>              
     </label>                           
    </div>                            
    <div class="small-6 columns">                       
     <label>CVC                           
     <input type="text" [(ngModel)]="cvc" name="cvc">                 
     </label>                           
    </div>                            
    </div>                             
    <input type="submit" value="Sign Up">                     
</form> 

는 희망 그 요점을 얻을 충분하다. 내가 볼 수있는 것은 MessagesComponent 안에있는 this.messages이 실제로 호출되었을 때 정확한 값으로 변경된다는 것입니다. 그러나 DOM은 업데이트되지 않습니다.

무엇이 여기에 있습니까? Angular가 구성 요소 속성의 변경 사항을 감지하고이를 DOM에 전파하는 방법에 대한 근본적인 오해가있는 것처럼 느껴지지만 실종 된 부분이 전혀 없습니다.

도움 주셔서 감사합니다.

+0

. 우리는 모델을 업데이트하는 호출이 어디서 발생했는지 알아야합니다. 수동으로 변경 감지를 호출하기위한 검색 –

+0

고마워요 @ GünterZöchbauer - 모델을 업데이트하는 호출은 SignupComponent에서 호출됩니다. 바로 근처에 'this.message.showErrors (...)'가 있습니다. 그게 네가 묻고있는거야? 또한,'ApplicationRef'를 주입하고'ref.tick()'을 호출하려고했지만, 수동으로 변경 감지를 시도하는 것과 관련하여 차이점을 보이지는 않습니다. –

+0

예, 'signupUser'는 어디에서 호출 되었습니까? 'NgZone.run' 또는 'ChangeDetectorRef.detectChanges'로 해결할 수 있지만 근본 원인을 수정할 수 있다면 더 좋을 것입니다. –

답변

0

코드를 다음과 같이 재정렬합니다. 전체 아이디어는 MessageComponent에 표시해야하는 메시지를 수신하는 데 사용되는 Input 속성이 있고 SignupComponent가 템플릿 바인딩 sintax를 사용하여 MessageComponent에 오류 메시지를 전달한다는 것입니다.

MessageComponent

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

@Component({                            
    selector: 'message',                          
    templateUrl: './message.component.html',                     
    styleUrls: ['./message.component.css']                     
})                               

export class MessageComponent implements OnInit {                   

    @Input() messages: Array<string>; // Input property                         

    constructor() {                           
    }                               

    ngOnInit() {                                                  
    } 
} 

SignupComponent

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

    @Component({                            
    selector: 'app-signup',                         
    templateUrl: './signup.component.html',                     
    styleUrls: ['./signup.component.css']                      
    })                               
    export class SignupComponent implements OnInit {                   

    email: string;                           
    password: string;                           
    cardNumber: string;                          
    expiryMonth: string;                          
    expiryYear: string;                          
    cvc: string;                            
    plan: string; 

    messages: Array<string>; // property used to pass the messages to the MessageComponent                           

    constructor(private activatedRoute: ActivatedRoute, private auth: Auth) { }   

    signupUser() {                           
     // do stuff here, then call back with status                                             
     }, (status: number, response: any) => {                     
     if (status == 200) {                         
      // yay, do success stuff                         
     } else {                            
      console.log('Error', response.error.message);                  
      this.messages = [response.error.message];                 
     }                              
     });                              
    } 

SignupComponent 템플릿 그것은 통상

<!-- TEMPLATE BINDING --> 
<message [messages]="messages"></message>                          
<h1>Signup</h1>                           
<form (submit)="signupUser()"> 
..... the rest of your code 
</form> 
+0

이것은 나에게 합당한 일이지만 DOM을 업데이트하지 않는 것 같습니다. –

+0

내가 제안 할 수있는 유일한 것은'response.error.message'에서 어떤 종류의 객체를 얻는지를 보는 것이다. 코드는 문자열의 배열을받는 것으로 가정한다. 문자열의 배열이 아닌 간단한 문자열을받는다면 아마도 아무것도 볼 수 없습니다. – Picci

+0

밝혀 졌 ngzone.run()에서 포장하는 경우 작동합니다. 분명히,이 호출의 비동기 성격 문제가 보인다 (나는이 호출에서 Stripe API를 사용하고 있습니다. response.error.message는 해당 호출의 반환 값입니다.)이를 랩핑하면 솔루션이 완벽하게 작동합니다. 다른 곳에서 구현하기가 더 쉽도록 캡슐화하는 것이 좋습니다.하지만 확실히 실행 가능합니다. 해결책! –

관련 문제