从组件推送后,阵列更改未反映

时间:2018-03-24 14:31:31

标签: angular

在angular中,我尝试创建一个示例服务来传递一个数组,该数组将被所有组件共同使用,然后一个组件向该数组添加新元素。但是,在推送它之后,新元素不会在app.component.html中呈现。我对角度有点新意。请帮忙。 app.component.html是:

<div class="container">
  <div class="row">
    <div class="col-xs-12 col-md-8 col-md-offset-2">
      <app-new-account></app-new-account>
      <hr>
      <app-account
        *ngFor="let acc of myAccounts; let i = index"
        [account]="acc"
        [id]="i"></app-account>
    </div>
  </div>
</div>

app.component.ts是:

import { Component, OnInit } from '@angular/core';
import { AccountsService } from './accounts.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [AccountsService]
})
export class AppComponent implements OnInit {
  myAccounts: {name: string, status: string}[] = [];

  constructor(private accountsService: AccountsService) {}

  ngOnInit() {
    this.myAccounts = this.accountsService.accounts;
  }

}

服务(accounts.service.ts)是:

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

@Injectable()
export class AccountsService {
	accounts = [
    {
      name: 'Master Account',
      status: 'active'
    },
    {
      name: 'Testaccount',
      status: 'inactive'
    },
    {
      name: 'Hidden Account',
      status: 'unknown'
    }
  ];

  addAccount(acctName: string, acctStatus: string) {
  	console.log("inside add accnt");
  	this.accounts.push({name: acctName, status: acctStatus});
  	console.log(this.accounts);
  }

  updateStatus(id: number, status: string) {
	this.accounts[id].status = status;
  }

}

子组件account.component.html是:

<div class="row">
  <div class="col-xs-12 col-md-8 col-md-offset-2">
    <h5>{{ account.name }}</h5>
    <hr>
    <p>This account is {{ account.status }}</p>
    <button class="btn btn-default" (click)="onSetTo('active')">Set to 'active'</button>
    <button class="btn btn-default" (click)="onSetTo('inactive')">Set to 'inactive'</button>
    <button class="btn btn-default" (click)="onSetTo('unknown')">Set to 'unknown'</button>
  </div>
</div>

子组件account.component.ts是:

import { Component, Input } from '@angular/core';
import { LoggingService } from '../logging.service';
import { AccountsService } from '../accounts.service';

@Component({
  selector: 'app-account',
  templateUrl: './account.component.html',
  styleUrls: ['./account.component.css'],
  providers: [LoggingService]
})
export class AccountComponent {
  @Input() account: {name: string, status: string};
  @Input() id: number;

  constructor(private loggingService: LoggingService, private accountsService: AccountsService) {}

  onSetTo(status: string) {
    this.accountsService.updateStatus(this.id, status);
    this.loggingService.logStatusChange(this.account.status);
  }
}

子组件new-account.component.html是:

<div class="row">
  <div class="col-xs-12 col-md-8 col-md-offset-2">
    <div class="form-group">
      <label>Account Name</label>
      <input
        type="text"
        class="form-control"
        #accountName>
    </div>
    <div class="form-group">
      <select class="form-control" #status>
        <option value="active">Active</option>
        <option value="inactive">Inactive</option>
        <option value="hidden">Hidden</option>
      </select>
    </div>
    <button
      class="btn btn-primary"
      (click)="onCreateAccount(accountName.value, status.value)">
      Add Account
    </button>
  </div>
</div>

子组件new-account.component.ts是:

import { Component } from '@angular/core';
import { LoggingService } from '../logging.service';
import { AccountsService } from '../accounts.service';

@Component({
  selector: 'app-new-account',
  templateUrl: './new-account.component.html',
  styleUrls: ['./new-account.component.css'],
  providers: [LoggingService]
})
export class NewAccountComponent {

  constructor(private loggingService: LoggingService, private accountsService: AccountsService) {}

  onCreateAccount(accountName: string, accountStatus: string) {
    this.accountsService.addAccount(accountName, accountStatus);
    this.loggingService.logStatusChange(accountStatus);
  }
}

2 个答案:

答案 0 :(得分:0)

这是一个变化检测问题。您必须更改对数组的引用以触发更改检测。

在服务档案中:

#:kivy 1.10.0
#:import FadeTransition kivy.uix.screenmanager.FadeTransition

<RootScreen>:
    transition: FadeTransition()
    IntroScreen:
        name: 'intro'
    NameScreen:
        name: 'data'

<IntroScreen>:
    AnchorLayout:
        Image:
            source: 'kivyLogo.png' # 'yCFD2.png'
            size_hint: 1,1
        Button:
            background_color: [63, 191, 63, 0.0]
            text: ''
            on_press: root.manager.current = 'data'

<NameScreen>:
    canvas.before:
        Rectangle:
            pos: self.pos
            size: self.size
            source: 'kivymd_logo.png'  # 'X6TF0.png'
    FloatLayout:
        TextInput:
            id: ChildName
            size_hint:.2, .2
            pos_hint:{'x': 0.7, 'y': 0.4}
            text: "Введи имя"
            focus: True
            multiline: False
        TextInput:
            id: ChildAge
            size_hint:.2, .2
            pos_hint:{'x': 0.7, 'y': 0.6}
            text: "Введи возраст"
            focus: True
            multiline: False
        Button:
            size_hint:.2, .2
            pos_hint:{'x': 0.7, 'y': 0.8}
            background_color: [63, 191, 63, 0.3]
            text: 'Добавить в базу'
            on_press: root.PrintData(ChildName.text, ChildAge.text)

在组件文件中:

addAccount(acctName: string, acctStatus: string) {
  this.accounts = [...this.accounts, {name: acctName, status: acctStatus}]
}

updateStatus(id: number, status: string) {
  this.accounts = this.accounts.map((acc, i) => i === id ? { ...acc, status } : acc))
}

你应该习惯于使用不可变数据(总是返回新副本,而不是改变原始值),否则你最终会得到带有角度变化检测的奇怪错误日志。

良好的经验法则是: 如果您的console.log显示正确的值,但模板未更新,则表明存在更改检测问题。

答案 1 :(得分:0)

只要您不使用OnPush更改检测策略,它就应该按照您的描述运行。我将你的代码复制到stackblitz中,我觉得它的工作原理是:

https://stackblitz.com/edit/angular-3dxw8d

周末愉快