Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
139 views
in Technique[技术] by (71.8m points)

angular - Expression has changed after it was checked. Previous value: 'model: 1777'. Current value: 'model: 2222'

I have this html code, in this code I used [(ngModel)] for change my value input, and when I change I want to calculate automatic my Total, subtotal and Amound Paid. Maybe this is not good solution because I have some problem.

  1. When I add some data, my all data chnage value, all get the last set value. Like in photo,

    enter code here

Please I need help.

My html code

 <form [formGroup]="addsale" (ngSubmit)="onaddsale()">
      <table align="center" class="table table-bordered table-hover">
        <thead>
          <tr style="color:black;">
            <th>Unit_price</th>
            <th>Quantity</th>
            <th>Description</th>
            <th>Subtotal</th>
            <th>Actions</th>
          </tr>
        </thead>
        <tbody>
          <tr class="group" style="cursor: pointer" *ngFor="let item of products; let i = index">
             <td>
              <input formControlName="Unit_price" id="Unit_price " type="number" class="validate"[(ngModel)]="item.Unit_price">
            </td>
            <td>
              <input formControlName="Quantity" id="Quantity " type="number" class="validate"  [(ngModel)]="item.Quantity"> 
            </td>
            <td>
              <input type="text" formControlName="Description" id="Description" name="Description" [(ngModel)]="item.Description">
            </td>
            <td>
              <input formControlName="Subtotal" id="Subtotal" type="number" class="validate"  [(ngModel)]="item.Subtotal">
            </td>
            <td>
              <button type="button" class="fa" (click)="onDelete(i)">x</button>
            </td>
          </tr>
        </tbody>
      </table>
      <br>
      <br>
      <div class="row">
        <div class="input-field col s2" style="float: right;">
          <label for="total">Total {{total}} ALL</label>
          <input formControlName="total" id="total" type="text" class="validate"   [(ngModel)]="total">
        </div>
        <div class="input-field col s2" style="float: right;">
          <label for="amount_paid">Amount Paid:</label>
          <input formControlName="amount_paid" id="amount_paid" [(ngModel)]="total" type="text" class="validate">
        </div>
        <div class="input-field col s2" style="float: right;">
          <label for="total">Subtotal</label>
          <input formControlName="Subtotal" id="Subtotal" type="text" class="validate"  [(ngModel)]="total">
        </div>
      </div>

      <hr>
      <br>
      <div id="add_homebox_button_container" class="row" style="float: right;">
        <button id="add_client_button" type="submit" class="btn waves-effect waves-light">
          Register
        </button>
      </div>
    </form>

Code ts:

export class AddSaleFormComponent implements OnInit {
  addsale: FormGroup;
  loading: boolean = false;
  client: Client[];
  producttype: ProductType[];
  contrat: Contrat[];
  gpss: GPS[];
  homeboxp: HomeboxP[];
  sensors: Sensors[];
  homebox: Homebox[];
  products: Products[] = [];
  Price: number = 0;
  Total;
  variable: any;
  Quantity: number;
  Unit_price: number;

  selectedClient: Client = new Client('');
  @Input() selectedProduct: Products;

  constructor(
    private router: Router,
    private fb: FormBuilder,
    private ss: SalesService,
    private ps: ProductsService,
    private cs: ClientService,
    private pts: ProducttypeService,
    private css: ContratService,
    private gps: GpsService,
    private hbp: HomeboxpackageService,
    private sensor: SensorsService,
    private hb: HomeboxService

  ) {
    this.addsale = this.fb.group({
      'invoice_number': new FormControl('', [Validators.required, Validators.nullValidator]),
      'invoice_date': new FormControl('', Validators.required),
      'client_id': new FormControl('', Validators.required),
      'amount_paid': new FormControl('', Validators.required),
      'notes': new FormControl('', Validators.required),
      'Subtotal': new FormControl('', Validators.required),
      'products': this.fb.array([]),
      'total': new FormControl('', Validators.required),
      'contactNo': new FormControl('', Validators.required),
      'address': new FormControl('', Validators.required),
      'Unit_price': new FormControl('', Validators.required),
      'Quantity': new FormControl('', Validators.required),
      'Description': new FormControl('', Validators.required),
      'line_num': new FormControl('', Validators.required)
    });
  }

  ngOnInit() {

    this.products = this.ps.getProduct();
    console.log(this.products)

    this.pts.getAllProductType().subscribe(
      producttype => {
        this.producttype = producttype;
      }
    );
  }


  onaddsale() {
    this.loading = true;
    let sale = this.addsale.value
    sale.products = this.products

    let newSale = new Sale(sale);
    console.log(newSale)

    this.ss.saleitemcreate(newSale).subscribe(
      result => {
        if (result === true) {
          Materialize.toast('Sale saved successfully', 4000);
        } else {
          this.loading = false;
        }
      },
      error => {
        this.loading = false;
      }
    );
  }

  get total() {
    let Total = 0;
    for (let p of this.products) {
      Total += p.Unit_price * p.Quantity;
    }
    return Total;
  }
  Subtotal() {
    let subtotal = 0;
    for (let p of this.products) {
      subtotal = p.Unit_price * p.Quantity;
    }
    console.log(subtotal)
    return subtotal;
  }

}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your problem is the FormGroup. As you can see, you've got one FormControl for 'Unit_price'. However, in your template, you've got several rows, and in each row there is an input that points to that same FormControl (via the FormControlName directive). But they all belong to the same FormGroup, and that messes with the form, so all the inputs with the same name refer to the same FormControl, causing the odd behaviour you're suffering. You can't have duplicate controls under the same FormGroup directive.

What you've got to do is define a FormGroup for each row of the table. This way, you'll have an array of FormGroup. In each of them, there will be a FormControl with a unique name, and so your problems will disappear.

This means you've got to make a FormGroup for each product in the products array, and maybe a different FormGroup for the common controls (total, Subtotal...).

Of course, this means that the products array in the FormGroup no longer is necessary.

Another advice is to remove data binding from the 'total' fields, as you won't edit them. You can change [(ngModel)] to just [ngModel] for them.

In fact, though I'm not an expert in reactive forms, I think that, if you're using FormControl and FormGroup, you don't need ngModel at all.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...