我有两个模块,一个是查看项模块,另一个是添加项模块。
我有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中。我是新来的角度。

最佳答案

最简单的方法是通过Services。检查这个stackblitz
为了简单起见,我没有使用SubjectBehaviorSubject
我有两个组件,我们称它们为InputComponentTableComponent
第一个保存输入,第二个显示数据。
我还创建了一个名为DataService的服务。
它包含一个名为data的数组和一个将新行推送到data的方法

@Injectable()
export class DataService {

  data: any[] = [];

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

}

让我们看看InputComponent
如您所见,我注入了DataComponent并创建了两个输入
当用户单击ngModel时,我将此数据推入button数组并清除输入。
@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 = {};
  }
}

dataService.data上,我向用户显示TableComponent,如下所示
dataService.data
@Component({
  selector: 'table-comp',
  templateUrl: './table.component.html'
})
export class TableComponent  {

  constructor(public dataService: DataService) {}
}

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

当存在table.component.html时,上述解决方案不起作用
上面的stackblitz工作得很好,因为我没有改变ChangeDetectionStrategy.OnPushchangeDetection。但是,如果将TableComponentchangeDetection设置为TableComponent,您将看到它不起作用。Check it out
这是因为,现在你告诉ChangeDetectionStrategy.OnPush只听事件,比如Angulars中的任何变化(我们没有)、内部事件等等。如果你不知道Input你应该读一下。它提供了很大的性能改进。
无论如何,让我们重构ChangeDetectionStrategy.OnPushservices以支持component
Our final code
首先,我重构ChangeDetectionStrategy.OnPush以获得DataService
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);
  }
}

现在,我们不再向外界公开BehaviourSubject数组,而是公开一个名为data的可观测对象。而且,当一个新项目通过时,我们会更新我们的内部data$并通过data发布它。这样,将触发一个事件并通知所有订阅者。
让我们看看我们的dataSubject.next
<table border="1">
  <tbody>
    <tr *ngFor="let row of dataService.data$ | async">
      <td>{{row.firstValue}}</td>
      <td>{{row.secondValue}}</td>
    </tr>
  </tbody>
</table>

唯一的区别是,我们不是直接访问TableComponent数组,而是访问dataobservatable并通过dataService.data$管道订阅它。现在,每个人都很快乐,一切都很好。
不带RXJ
有一种方法不需要RxJs,但我认为如果有许多级别的组件的话,这会很麻烦。看看final code
我删除了负责在两个组件之间传递数据的async。相反,现在当输入新输入并单击按钮时,data.service会发出一个事件。
InputComponent通过TableComponent检索data
@Input
@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 = {};
  }
}

InputComponent
@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[];

}

TableComponent
@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];
  }
}

正如你可能已经注意到的,我不做AppComponent。这是因为,当将新数据推送到现有数组时,其对象引用将不会更改。因此,角度变化检测不会触发this.data.push(newModel)并更新表格。
TableComponent使用现有的this.data = [...this.data, newModel]数组并将其扩展到data并添加...。这样,您总是创建一个新实例,并且更改检测将正常工作。

10-06 07:49