Angular 2组件属性更改时更新DOM

时间:2017-05-21 19:18:01

标签: angular

刚刚从Angular 1迁移到Angular 4,并且在更新组件属性时理解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()方法,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>  

希望这足以获得要点。我能够观察到this.messages DOES中的MessagesComponent确实在被调用时会更改为正确的值,但DOM不会更新。

我在这里缺少什么?我觉得我对Angular如何检测组件属性的变化并将其传播到DOM有一些基本的误解,但我不知道它是什么我错过了。

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

今天我遇到了这个问题,我这样解决了:

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

......它会每隔一秒通知一次更改

constructor(private ref: ChangeDetectorRef){

     setInterval(() => {
       this.ref.detectChanges()
     }, 1000);

 }

...如果你只想通知那些,你需要在需要之后使用这一行

 this.ref.detectChanges()

答案 1 :(得分: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>