如何在应用程序中将ng模型值用作全局值?

时间:2018-08-20 09:04:58

标签: angular html5

我有两个模块,一个是“查看项目”模块,另一个是“添加项目”模块。

我有app.view.component.tsapp.add.component.cs,但是现在如何使用[(ng-model)]值作为全局值

这是add.component.html

<table style="width:100%;">
    <tr height="25">
        <td align="right" width="45%">
            <div class="label-man">
                <span>* Item ID</span>
            </div>
        </td>
        <!-- <td><input type="text" style="width:300px" id="itemIDVal"></td> -->
        <td>
            <input type="text" style="width:300px" name="itemId" id="FstTex" [(ngModel)]=" itemId">
        </td>
    </tr>
    <tr height="25">
        <td align="right">
            <div class="label-man">
                <span>Item Description</span>
            </div>
        </td>
        <td>
            <input type="text" style="width:300px" id="itemDescriptionVal" [(ngModel)]=" itemDesc">
        </td>
    </tr>
    <tr height="25">
        <td align="right">
            <div class="label-man">
                <span>* Item Classification</span>
            </div>
        </td>
        <td>
            <input type="text" style="width:300px" id="classificationVal" [(ngModel)]=" Classification">
        </td>
    </tr>
    <tr height="25">
        <td align="right">
            <div class="label-man">
                <span>* Item Sub-Classification</span>
            </div>
        </td>
        <td>
            <input type="text" style="width:300px" id="subClassificationVal" [(ngModel)]=" subClassification" />
        </td>
    </tr>
    <tr>
        <td class="buttons">
            <a href="#">
                <span>Save</span>
            </a>
        </td>
        <td></td>
    </tr>
</table>
<table style="width:100%; table-layout: fixed;" class="newtbl">
    <thead>
        <tr height="25">
            <th width="25%">Item ID</th>
            <th width="25%">Item Description</th>
            <th width="25%">Item classification</th>
            <th>Item Sub-Classification</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>{{inputItem.itemId}}</td>
            <td>{{inputItem.itemDesc}}</td>
            <td>{{inputItem.Classification}}</td>
            <td>{{inputItem.subClassification}}</td>
        </tr>

    </tbody>
</table>

这是view.componet.html

<table style="width:100%;">
    <thead>
        <tr>
            <td>
                <input type="text" placeholder="Please Enter Item ID" [(ngModel)]="itemId" />
            </td>
            <td>
                <input type="text" placeholder="Please Enter Item Description" [(ngModel)]="itemDesc" />
            </td>
            <td>
                <input type="text" placeholder=" Please Enter Classification" [(ngModel)]="Classification" />
            </td>
            <td>
                <input type="text" placeholder="Please Enter Sub-Class" [(ngModel)]="subClassification" />
            </td>
        </tr>
        <tr height="25">
            <th width="25%">Item ID</th>
            <th width="25%">Item Description</th>
            <th width="25%">Item Classification</th>
            <th>Item Sub-Classification
                <span class="buttons">
                    <a>
                        <span>Add Record</span>
                    </a>
                </span>
            </th>
        </tr>
        <tr>
            <td>{{itemId}}</td>
            <td>{{itemDesc}}</td>
            <td>{{Classification}}</td>
            <td>{{subClassification}}</td>
        </tr>
    </thead>
</table>

这种情况是当我在add.component.html中输入值时,这些值直接作为行追加到view.component.html中。我是Angular的新手。

1 个答案:

答案 0 :(得分:1)

最简单的方法是通过Services。选中此stackblitz

为简单起见,我没有使用SubjectBehaviorSubject

我有两个组成部分,我们将它们称为InputComponentTableComponent

第一个保留输入,第二个显示数据。

我也创建了一个名为DataService的服务。

它包含一个名为data的数组和一种将新行推送到data

的方法
@Injectable()
export class DataService {

  data: any[] = [];

  push(row) {
    this.data.push(row);
  }

}

我们来看看InputComponent 如您所见,我注入了DataComponent并使用ngModel s创建了两个输入

当用户单击button时,我会将这些数据推入dataService.data数组中并清除输入。

@Component({
  selector: 'input-comp',
  template: `
    <div>Enter first column: <input [(ngModel)]="model.firstValue" /></div>
    <div>Enter second column: <input [(ngModel)]="model.secondValue" /></div>
    <button (click)="onBtnClick()">Click me</button>
  `
})
export class InputComponent  {
  model = {};

  constructor(private dataService: DataService) {}

  onBtnClick() {
    this.dataService.push(this.model);
    this.model = {};
  }
}

TableComponent上,我向用户显示dataService.data如下

table.component.ts

@Component({
  selector: 'table-comp',
  templateUrl: './table.component.html'
})
export class TableComponent  {

  constructor(public dataService: DataService) {}
}

table.component.html

<table border="1">
  <tbody>
    <tr *ngFor="let row of dataService.data">
      <td>{{row.firstValue}}</td>
      <td>{{row.secondValue}}</td>
    </tr>
  </tbody>
</table>

存在ChangeDetectionStrategy.OnPush时,以上解决方案无效

由于我没有更改changeDetection中的TableComponent,所以上面的堆叠闪耀效果很好。但是,如果将changeDetection中的TableComponent设置为ChangeDetectionStrategy.OnPush,则会发现它不起作用。 Check it out

这是因为,现在您告诉Angular仅听事件,例如Input中的任何变化(我们没有任何变化),内部事件等。如果您没有了解ChangeDetectionStrategy.OnPush,您应该阅读一下。它提供了很大的性能改进。

无论如何,让我们重构servicecomponent来支持ChangeDetectionStrategy.OnPush

Our final code

首先,我将DataService重构为一个BehaviourSubject

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

@Injectable()
export class DataService {

  private data: any[] = [];

  private dataSubject: BehaviorSubject<any[]> = new BehaviorSubject(this.data);
  public readonly data$ = this.dataSubject.asObservable();
  push(row) {
    this.data.push(row);
    this.dataSubject.next(this.data);
  }
}

现在,我们没有向外界公开data数组,而是公开了一个名为data$的Observable。并且,当有新项目通过时,我们将更新内部data并通过dataSubject.next发布。这样,将触发事件并通知所有订户。

让我们看看我们的TableComponent

<table border="1">
  <tbody>
    <tr *ngFor="let row of dataService.data$ | async">
      <td>{{row.firstValue}}</td>
      <td>{{row.secondValue}}</td>
    </tr>
  </tbody>
</table>

唯一的区别是,我们直接访问data并通过dataService.data$管道对其进行订阅,而不是直接访问async数组。现在,每个人都很高兴,一切都很好。

没有RxJ

有一种没有RxJ的方法,但是我认为如果组件的级别很多,这将很麻烦。看看final code

我删除了data.service,后者负责两个组件之间的数据传递。相反,现在InputComponent会在输入新输入并单击按钮时发出事件。

TableComponent通过data检索@Input

InputComponent

@Component({
  selector: 'input-comp',
  template: `

  <div>Enter first column: <input [(ngModel)]="model.firstValue" /></div>
  <div>Enter second column: <input [(ngModel)]="model.secondValue" /></div>
  <button (click)="onBtnClick()">Click me</button>
  `
})
export class InputComponent  {
  model = {};

  @Output() modelChange: EventEmitter<any> = new EventEmitter();

  constructor() {}

  onBtnClick() {
    this.modelChange.emit(this.model);
    this.model = {};
  }
}

TableComponent

@Component({
  selector: 'table-comp',
  template:`
    <table border="1">
      <tbody>
        <tr *ngFor="let row of data">
          <td>{{row.firstValue}}</td>
          <td>{{row.secondValue}}</td>
        </tr>
      </tbody>
    </table>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class TableComponent  {

  @Input() data: any[];

}

AppComponent

@Component({
  selector: 'my-app',
  template: `
    <input-comp (modelChange)="onModelChange($event)"></input-comp>
    <table-comp [data]="data"></table-comp>
  `,
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';

  data = [];

  onModelChange(newModel) {
    this.data = [...this.data, newModel];
  }
}

您可能已经注意到,我没有this.data.push(newModel)。这是因为,当您将新数据推送到现有数组时,其对象引用不会更改。因此,角度变化检测将不会为TableComponent触发并更新表格。

this.data = [...this.data, newModel]获取现有的data数组,并与...进行扩展,然后添加newModel。这样,您总是可以创建一个新实例,更改检测就可以正常工作。