2017-05-21 86 views
0

就在最近,從1角到移動角度4,並且有一點的一個艱難的時間理解爲什麼當一個組件的屬性被更新的DOM沒有更新。我搜索並閱讀了無數帖子,並且找不到任何似乎回答此問題的內容。更新DOM當角2組件屬性更改

我有了顯示錯誤消息的組件的應用程序,叫做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]);                 
     }                              
     });                              
    } 

The signupUser() me的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

The我只能建議在'response.error.message'中看看你收到了什麼樣的對象,代碼假設你接收到一個字符串數組,如果你接收到一個簡單的字符串(而不是一串字符串),你會可能沒有看到任何東西 – Picci

+0

事實證明,如果我將它包裝在ngzone.run()中,這樣做會起作用。顯然,這似乎是調用的異步性問題(我在此調用中使用Stripe API, response.error.message是來自該調用的返回值)當我將其包裝在其中時,您的解決方案完美地工作,我仍然希望封裝好一點,以便更容易在別處實現,但它當然是可行的解! –