user3473535
user3473535

Reputation: 31

Angular 4 - How to calculate price based on change in quantity and option

Requirement
There are a list of items in the shopping cart. Each item has option, quantity, price. Need to calculate the price based on change in quantity and option of a item.

Research I had added [(ngModel)] as below, so as to use 2 way data-binding, however, no idea why the page simply keeps on loading and than crashes without any error. When i remove the ngModel attribute the page loads successfully.

<span class="price col-1 pull-right" >{{ orderType*price}}</span>
<div class="qty" style="margin:0;">
     <span class="spinner">
        <span class="sub">-</span>
        <input type="number" id="qty" name="qty" min="1" max="100" 
               value="1" class="qty-spinner" [(ngModel)]="quantity" />
        <span class="add">+</span>
     </span>
 </div>
 <div class="type">
     <label class="radio inline" *ngFor="let option of item.options; let k = index"> 
     <input id="{{'toggle-half-'+item.id+'-'+j}}" type="radio" 
            name="{{'option-toggle-'+item.id+'-'+j}}" [value]="option.value" 
            [checked]='k===0' [(ngModel)]="orderType" />
     <span>{{option.title}} </span> 
     </label>
 </div>

TypeScript Code

quantity:number;
orderType:number;
price:number;

constructor() {
    this.quantity = 1;
    this.price = 0;
}

Controls used
1) Number Control input of type number for quantity.
2) Radio Control for Options [Half/Full]
3) span element for printing calculated price.

Expected Output
Price which is currently set to 0 should get updated when we change the quantity or the option.
Eg. Value set for option [Half] = 10
Eg. Value set for option [Full] = 20

Please advise how can i implement this, is the above logic and implmentation correct ?

Thanks in advance

Upvotes: 2

Views: 3587

Answers (4)

user3473535
user3473535

Reputation: 31

the issue is resolved now. The code snippet in the description was implemented between a div tag which had a *ngFor directive, that iterated through the list of items.

Issue
For dividing the list of items into 2 columns "div.col-md-6", i had implemented a a function that returned me an array of 2 arrays each containing set of items, so as to iterate through each array and display the items in each column.

Could not find the issue, why there was an issue only when i implemented the ngModel tag, which should have not been the case. However, i removed that splitting function and everything worked fine for me.

Thanks to all for your efforts and help.

Upvotes: 0

Nuru Salihu
Nuru Salihu

Reputation: 4928

Not sure why it crashed but if i were you. The constructor

constructor() {
    this.quantity = 1;
    this.price = 0;
}

I will use ngInit instead since its a two way binding.

     import { OnInit } from '@angular/core';

        export class myClas implements OnInit {

        ngOnInit() {
            this.quantity = 1;
            this.price = 0;
        }

    }

Secondly, you have value in your radio button and input type number. Are you sure they return value of type number ? If i were you i will use or try string first and cast it to my desired number type afterward. Or use a pipe. Wrong type conversion can be expensive sometimes . So can you try

quantity:string;
orderType:string;
price:string;

first and do your number conversion afterward ?

Upvotes: 0

stealththeninja
stealththeninja

Reputation: 3791

Edit: Reviewing the documentation sample shared in jkris' answer, value makes sense for radio inputs. I still suspect checked creates an update loop when combined with [(ngModel)].


I notice you're binding checked in addition to the NgModel binding. If you remove it, does it keep the correct behavior and prevent crashing?

<input type="number" class="qty-spinner" min="1" max="100" 
       name="quantity" [(ngModel)]="quantity" />


<input type="radio" 
       [value]="option.value" name="option" [(ngModel)]="option" />

Otherwise, another option is to use [checked] and (click)(or similar) bindings in place of NgModel.

Upvotes: 0

jkris
jkris

Reputation: 6541

The variable option is already in use in the ngFor directive. See line:

<label class="radio inline" *ngFor="let option of item.options; let k = index">

Use a different variable instead for the ngModel, example:

<input id="{{'toggle-half-'+item.id+'-'+j}}"  
       type="radio" 
       name="{{'option-toggle-'+item.id+'-'+j}}" 
       [value]="option.value"
       [(ngModel)]="selectedOption" />

Look at the examples in the documentation;

EDIT

Also you have you're binding the checked attribute while imposing a ngModel. Instead of doing that, simply init the ngModel with the value you want, in your case,

selectedOption = item.options[0].value

Upvotes: 0

Related Questions