1

I'm from a c# c++ background and I'm confused about something that is happening.

Inside the scope of my function I am creating a new object before pushing it onto an 'array'. When I create the new object, it seems to be referencing the same object that was previously added to the array, even though I'm not assigning to the same variable. This is confusing because in c# this code would be creating a new object then adding the new object to the array. How do I get around this in javascript? Even using 'let', which I thought should stay in the scope I defined, does not seem to work

function:

  addPurchaseOrderItem() {
    this.purchaseOrderItems.push(new PurchaseOrder("","","","",1,100,""));
    console.log(this.purchaseOrderItems);
    // this.showNewPurchaseOrderItem = true;
  }

another version that still does not work:

 addPurchaseOrderItem() {
    let temp = new PurchaseOrder("","","","",1,100,"");
    this.purchaseOrderItems.push(temp);
    console.log(this.purchaseOrderItems);
    // this.showNewPurchaseOrderItem = true;
  }

purchase order class:

export class PurchaseOrder {
    public poNumber: string;
    public siteLocation: string;
    public lineItem: string;
    public manufacture: string;
    public partNum: string;
    public qTY: number;
    public acquisitionCost: number;
    public itemDescription: string

    constructor(
        siteLocation: string,
        lineItem: string,
        manufacture: string,
        partNum: string,
        qTY: number,
        acquisitionCost: number,
        itemDescription: string
        )
    {
        this.siteLocation = siteLocation;
        this.lineItem = lineItem;
        this.manufacture = manufacture;
        this.partNum = partNum;
        this.qTY = qTY;
        this.acquisitionCost = acquisitionCost;
        this.itemDescription = itemDescription
    }
}

here is the live example (stackblitz): https://stackblitz.com/edit/angular-rvkjoa

Goku
  • 1,565
  • 1
  • 29
  • 62

2 Answers2

1

Your array is populated correctly. It looks like you have the same id's and Angular always shows the first row everywhere. Your array items are not the same. It can be seen from the following code:

<!-- The above code omitted for the brevity -->
<button (click)="addPurchaseOrderItem()"> Add</button>
<p>purchaseOrderItems {{ purchaseOrderItems | json }} </p>

You should just delete the id attributes because they are always the same in your loop:

<form #form="ngForm" (ngSubmit)="saveAllChangesToDatabase(form)">
    <table style="width:100%; margin: 0 auto;">
    <tr style="text-align: left;">
      <th>QTY</th>
      <th>Acq. Cost$</th>
      <th>Item Description</th>
    </tr>
    <tr *ngFor="let purchaseOrder of purchaseOrderItems">
      <td>
        <input name="qTY" [(ngModel)]="purchaseOrder.qTY" type="text" size="3%"  required>
      </td>
      <td>
        <input name="acquisitionCost" [(ngModel)]="purchaseOrder.acquisitionCost" type="text" size="5%"  required>
      </td>
      <td>
        <input name="itemDescription" [(ngModel)]="purchaseOrder.itemDescription" type="text" size="35%" required>
      </td>
    </tr>
  </table>
  <button style="margin-top: 2em"style="height: 2em; width: 100%; margin-top: .5em" (click)="addPurchaseOrderItem()"> Add</button>

  <p>purchaseOrderItems {{ purchaseOrderItems | json }} </p>

</form>

UPDATE:

Just delete form tag to avoid of disappearing data

<table style="width:100%; margin: 0 auto;">
    <tr style="text-align: left;">
      <th>QTY</th>
      <th>Acq. Cost$</th>
      <th>Item Description</th>
    </tr>
    <tr *ngFor="let purchaseOrder of purchaseOrderItems">
      <td>
        <input name="qTY" [(ngModel)]="purchaseOrder.qTY" type="text" size="3%"  required>
      </td>
      <td>
        <input name="acquisitionCost" [(ngModel)]="purchaseOrder.acquisitionCost" type="text" size="5%"  required>
      </td>
      <td>
        <input name="itemDescription" [(ngModel)]="purchaseOrder.itemDescription" type="text" size="35%" required>
      </td>
    </tr>
  </table>
  <button style="margin-top: 2em"style="height: 2em; width: 100%; margin-top: .5em" (click)="addPurchaseOrderItem()"> Add</button>

  <p>purchaseOrderItems {{ purchaseOrderItems | json }} </p>
StepUp
  • 36,391
  • 15
  • 88
  • 148
  • I made the changes you suggested and updated the StackBlitz, but the UI is still not reflecting it. Got any suggestions? – Goku Sep 03 '19 at 13:43
  • @Goky it works. I've opened your link and edited your data. https://stackblitz.com/edit/angular-rvkjoa . Try to edit your data. – StepUp Sep 03 '19 at 14:09
  • I mean how do I get the changes to stay. after I press add the item description disappears from the table even though the array is updated. – Goku Sep 03 '19 at 18:29
  • Is there a way to get this to work without removing the form? I need the form for validation – Goku Sep 04 '19 at 13:39
  • @Goku Yeah, you can do validation like this: https://stackoverflow.com/questions/51599143/angular-5-dynamic-form-validation-inside-a-table or https://stackoverflow.com/questions/44158712/reactive-form-for-each-table-row and plunker example https://stackblitz.com/edit/angular-vcjjfr?file=src%2Fapp%2Fapp.component.html – StepUp Sep 04 '19 at 14:10
0

Javascript has 3 data types that are passed by reference: Array, Function and Object. Anything else is pass by value. Solution can be found in following post. JavaScript: How to pass object by value?

Longer
  • 21
  • 2
  • but am I not creating a new reference in my example code? – Goku Sep 02 '19 at 19:31
  • Looks like there is nothing wrong with pushing new object into the array. It's working like you expected. i.e. 'creating a new object then adding the new object to the array.' The issue is with your UI code not reflecting new values that's already in the array. If you change the values already in the form and click the add button, then check console log and open the array, you will find that values already in array changed. – Longer Sep 02 '19 at 19:57