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

问题描述 投票:0回答:2

我最近刚刚从 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
中的
MessagesComponent
在调用时确实会更改为正确的值,但是 DOM 不会更新。

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

感谢您的帮助!

html angular dom
2个回答
4
投票

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

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

...它将每秒通知一次更改

constructor(private ref: ChangeDetectorRef){

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

 }

...如果您只想通知其他人,您需要在需要后使用此行

 this.ref.detectChanges()

0
投票

我将按如下方式重新排列代码。整个想法是 MessageComponent 有一个 Input 属性,用于接收它必须显示的消息,并且 SignupComponent 使用模板绑定语法将错误消息传递给 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() {                                                                                                                                                                                                    
  }  
}

注册组件

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>
© www.soinside.com 2019 - 2024. All rights reserved.