角注入值也会更改原始值(“角材料对话框”)

时间:2019-02-01 20:33:11

标签: angular typescript angular-material

我创建了一个弹出式表单来编辑表中的值,但是,一旦我开始修改表单中的数据,即使在打开对话框的情况下,键入的内容也会立即更改表中的原始数据。

这是我的主要组成部分:

import { Version } from './../models/Version';
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { AuthService } from '../services/auth.service';
import { ProjectsService } from '../services/projects.service';
import { ClientsService } from '../services/clients.service';
import { VersionsService } from '../services/versions.service';
import { Project } from '../models/Project';
import { EditprojectComponent } from './edit-project/editproject.component';
import {
  MatDialog,
  MatDialogRef,
  MAT_DIALOG_DATA,
  PageEvent,
  MatTableDataSource,
  MatPaginator
} from '@angular/material';
import { Client } from '../models/Client';

interface UIEntries {
  ProjectName: string;
  Client: string;
  Version: string;
  SOW: string;
  PM: string;
}

@Component({
  selector: 'app-projects',
  templateUrl: './projects.component.html',
  styleUrls: ['./projects.component.css']
})
export class ProjectsComponent implements OnInit {
  entries: UIEntries = {
    ProjectName: '',
    Client: '',
    Version: '',
    SOW: '',
    PM: ''
  };

  projects: Project[] = [];
  project: Project = new Project();
  loadingProjects: Boolean = true;
  clients: Client[];
  versions: Version[];

  length;
  pageSize = 5;
  pageSizeOptions: number[] = [5, 10, 25, 100];

  // MatPaginator Output
  pageEvent: PageEvent;
  dataSource;
  displayedColumns: string[] = ['Name', 'Client', 'SOW', 'PM', 'Version'];

  @ViewChild(MatPaginator) paginator: MatPaginator;

  setPageSizeOptions(setPageSizeOptionsInput: string) {
    this.pageSizeOptions = setPageSizeOptionsInput.split(',').map(str => +str);
  }

  constructor(
    private _auth: AuthService,
    private _clients: ClientsService,
    private _versions: VersionsService,
    private _projects: ProjectsService,
    public dialog: MatDialog
  ) {
    this._projects.getProjects().subscribe(res => {
      res.forEach(apiProject => {
        const tempProject = new Project();
        tempProject.populateProject(
          apiProject.Name,
          apiProject.ClientId,
          apiProject.VersionId,
          apiProject.Sow,
          apiProject.Pm,
          apiProject.CreatedBy
        );
        tempProject.ID = apiProject.Id;
        tempProject.Client = apiProject.Client;
        tempProject.Version = apiProject.Version;
        tempProject.Assignments = apiProject.Assignment;
        this.projects.push(tempProject);
      });
      this.length = this.projects.length;
      this.dataSource = new MatTableDataSource<Project>(this.projects);
      console.log(this.projects);
      this.dataSource.paginator = this.paginator;
      this.loadingProjects = false;
    });
  }

  ngOnInit(): void {
    this._clients.getClients().subscribe(res => {
      this.clients = res;
    });
    this._versions.getProjectVersions().subscribe(res => {
      this.versions = res;
    });
  }

  deleteProject(project: Project) {
    this._projects.deleteProject(project.ID).subscribe(res => {
      this.projects = [];
      this._projects.getProjects().subscribe(response => {
        response.forEach(apiProject => {
          const tempProject = new Project();
          tempProject.populateProject(
            apiProject.name,
            apiProject.clientId,
            apiProject.versionId,
            apiProject.sow,
            apiProject.pm,
            apiProject.createdBy
          );
          tempProject.ID = apiProject.id;
          this.projects.push(tempProject);
        });
        this.loadingProjects = false;
      });
    });
  }

  addProject() {
    this.project.Name = this.entries.ProjectName;
    this.project.VersionID = this.entries.Version;
    this.project.ClientID = this.entries.Client;
    this.project.SOW = this.entries.SOW;
    this.project.PM = this.entries.PM;
    this.project.CreatedBy = this._auth.user.UserID;
    this._projects.insertProject(this.project).subscribe(
      res => {
        this.projects.push(res);
      },
      err => console.log(err)
    );
  }

  editProject(project: Project) {
    const dialogRef = this.dialog.open(EditprojectComponent, {
      width: '400px',
      height: '450px',
      data: { project: project, clients: this.clients, versions: this.versions }
    });
  }
}
<div class="mainBody">
  <div class="leftBody">
    <h3>Add new project</h3>
    <div class="addproject-container mat-elevation-z1">
      <form (ngSubmit)="addProject()" class="form-container">
        <mat-form-field>
          <input
            [(ngModel)]="entries.ProjectName"
            name="ProjectName"
            matInput
            required
            placeholder="Project Name"/>
        </mat-form-field>
        <mat-form-field>
          <mat-select
            [(ngModel)]="entries.Client"
            required
            name="Client"
            placeholder="Client">
            <mat-option
              *ngFor="let client of clients; let i = index"
              [value]="client.Name">{{client.Name}}</mat-option>
          </mat-select>
        </mat-form-field>
        <mat-form-field>
          <mat-select
            [(ngModel)]="entries.Version"
            name="Version"
            required
            placeholder="Version">
            <mat-option
              *ngFor="let version of versions; let i = index"
              [value]="version.Description"
              >{{version.Description}}</mat-option>
          </mat-select>
        </mat-form-field>
        <mat-form-field>
          <input
            [(ngModel)]="entries.SOW"
            matInput
            name="SOW"
            required
            placeholder="SOW"
          />
        </mat-form-field>
        <mat-form-field>
          <input
            [(ngModel)]="entries.PM"
            matInput
            name="PM"
            required
            placeholder="PM"
          />
        </mat-form-field>
        <div class="button-container">
          <button mat-raised-button>Add Project</button>
        </div>
      </form>
    </div>
  </div>

  <div class="rightBody">
    <h3>Existing Projects</h3>
    <mat-spinner *ngIf="loadingProjects"></mat-spinner>
    <div class="listproject-container">
      <div *ngIf="!loadingProjects"  class="listproject-scrollcontainer mat-elevation-z1">
        <table  mat-table [dataSource]="dataSource">
          <ng-container matColumnDef="Name">
            <th mat-header-cell *matHeaderCellDef>Name</th>
            <td mat-cell *matCellDef="let element; let i = index;">
              <button mat-button (click)="editProject(projects[i])">{{element.Name}}</button></td>
          </ng-container>
          <ng-container matColumnDef="Client">
            <th mat-header-cell *matHeaderCellDef>Client</th>
            <td mat-cell *matCellDef="let element">
              {{element.Client.Name}}
            </td>
          </ng-container>
          <ng-container matColumnDef="SOW">
            <th mat-header-cell *matHeaderCellDef>SOW</th>
            <td mat-cell *matCellDef="let element">{{element.SOW}}</td>
          </ng-container>
          <ng-container matColumnDef="PM">
            <th mat-header-cell *matHeaderCellDef>PM</th>
            <td mat-cell *matCellDef="let element">{{element.PM}}</td>
          </ng-container>
          <ng-container matColumnDef="Version">
            <th mat-header-cell *matHeaderCellDef>Version</th>
            <td mat-cell *matCellDef="let element">{{element.Version.Description}}</td>
          </ng-container>
          <tr
            mat-header-row
            *matHeaderRowDef="displayedColumns; sticky: true"
          ></tr>
          <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
        </table>
      </div>
      <mat-paginator #paginatorPlaceholder
        [length]="length"
        [pageSize]="pageSize"
        [pageSizeOptions]="pageSizeOptions"
        (page)="pageEvent = $event"
      >
      </mat-paginator>
    </div>
  </div>
</div>

这是Dialog PopUp组件:

import { Component, OnInit, Inject } from '@angular/core';
import { Project } from 'src/app/models/Project';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';

@Component({
  selector: 'app-editproject',
  templateUrl: './editproject.component.html',
  styleUrls: ['./editproject.component.css']
})
export class EditprojectComponent implements OnInit {

  popupProject: Project = new Project();
  clients: any;
  versions: any;

  constructor(
    public dialogRef: MatDialogRef<{EditprojectComponent: any}>,
    @Inject(MAT_DIALOG_DATA) public data: any) {
    this.popupProject = data.project;
    this.clients = data.clients;
    this.versions = data.versions;
    console.log(this.popupProject);
  }

  onNoClick(): void {
    this.dialogRef.close();
  }

  ngOnInit() {
  }

  submitEdit() {

  }
}
<div  mat-dialog-content>
<form (ngSubmit)="submitEdit()" class="form-container">
  <mat-form-field>
    <input [(ngModel)]="popupProject.Name" name="ProjectName" matInput required placeholder="Project Name">
  </mat-form-field>
  <mat-form-field>
    <mat-select [(ngModel)]="popupProject.Client.Name" required name="Client" placeholder="Client">
      <mat-option *ngFor="let client of clients; let i=index" [value]="client.Name">{{client.Name}}</mat-option>
    </mat-select>
  </mat-form-field>
  <mat-form-field>
    <mat-select [(ngModel)]="popupProject.Version.Description" name="Version" required placeholder="Version">
      <mat-option *ngFor="let version of versions; let i=index" [value]="version.Description">{{version.Description}}</mat-option>
    </mat-select>
  </mat-form-field>
  <mat-form-field>
    <input [(ngModel)]="popupProject.SOW" matInput name="SOW" required placeholder="SOW">
  </mat-form-field>
  <mat-form-field>
    <input [(ngModel)]="popupProject.PM" matInput name="PM" required placeholder="PM">
  </mat-form-field>
  <div class="button-container">
    <button mat-raised-button [mat-dialog-close]="popupProject" cdkFocusInitial>Save</button>
  </div>
</form>
</div>

我想实现的是,如果表值存在,则在弹出窗口中将其作为副本保存,并且仅在按下保存按钮后才保存它。

1 个答案:

答案 0 :(得分:1)

当您将对象作为数据传递给对话框时,对话框将可以访问和修改这些对象。您已将表中使用的项目对象传递给对话框,并且对话框的所有字段均已绑定到该对象,因此对这些字段所做的更改将作用于原始项目对象。你应该通过该项目的副本:

editProject(project: Project) {
  const dialogRef = this.dialog.open(EditprojectComponent, {
    width: '400px',
    height: '450px',
    data: { 
      project: {
        Name: project.Name,
        Client: project.Client,
        ...
      }, 
      clients: this.clients, 
      versions: this.versions 
    }
  });
}

您可能需要更彻底,并且可能需要对对象进行深层复制。仅传递对话框中需要的对象成员的值而不是整个项目对象会更简单,也可能更安全。这可能也容易得多。

然后,当然,当对话框是“拯救”,您将需要更新原有的项目对象与数据从您dialogRef.afterClosed()处理程序的对话框(你还没有表现出)传回。