geteds
geteds

Reputation: 79

Two way binding in Angular in more than two fields

So I’ve been playing around with angular and I learned about two-way binding using “ngModel”. I got this idea, but I can’t seem to implement it, would appreciate any help on this:

What I’m trying to do: So I will have an input field, that’ll take ticket prices for “Adult”, and a similar one for “Child”. I have another two input fields that’ll calculate the ticket prices based on the fixed rates. Then I want a third field where the sum of both their calculated prices is printed. I’ve tried this so far, but can't figure out what to do now. Any help would be greatly appreciated, thank you!

here’s the code:

<input type="text" [(ngModel)]="ticket.adult" name="adult">
<input type="text" value="{{ ticket.adult*15 }}">

<input type="text" [(ngModel)]="ticket.child" name="child">
<input type="text" value="{{ ticket.child*5 }}">


<p>Ticket Price:<!--the total price will be displayed here--></p>

P.S- I've declared a ticket object in its component.ts file.

Upvotes: 4

Views: 2298

Answers (2)

Explosion Pills
Explosion Pills

Reputation: 191789

As JBNizet said, for semantic and possibly functional reasons you should avoid using <input> for displaying output. Thus you can rewrite your code like this:

<input type="text" [(ngModel)]="ticket.adult" name="adult">
<p>{{ ticket.adult*15 }}</p>

<input type="text" [(ngModel)]="ticket.child" name="child">
<p>{{ ticket.child*5 }}</p>


<p>Ticket Price: {{ ticket.adult * 15 + ticket.child * 5 }}</p>

However, you probably want to avoid rewriting your adult / child multipliers more than once simply to avoid duplication and also in case they change. My recommended solution in this case would be to use pipes since your calculation is deterministic.

@Pipe({ name: 'price' })
export class PricePipe implements PipeTransform {
  transform(amount, type) {
    let multiplier = 0; // perhaps throw an error or set a sane default
    switch (type) {
      case 'adult':
        multiplier = 15;
      case 'child':
        multiplier = 5;
    }

    return amount * multiplier;
  }
}

Now you could use it like:

<input type="text" [(ngModel)]="ticket.adult" name="adult">
<p>{{ ticket.adult | price:'adult' }}</p>

<input type="text" [(ngModel)]="ticket.child" name="child">
<p>{{ ticket.child | price:'child' }}</p>


<p>Ticket Price: {{ (ticket.adult | price:'adult') + (ticket.child | price:'child') }}</p>

Now you can keep the multipliers in one spot and even add other kinds of multipliers later on if you need to. You could even possibly refactor your code to iterate over 'adult' and 'child' properties to display the prices rather than hard coding the .adult and .child values.

Upvotes: 1

Envil
Envil

Reputation: 2727

Maybe this works:

get sum(): number {
  // calculate your price with your formula here, 
  return this.ticket.adult*15 + this.ticket.child*5;
}

And in your template:

<p>Ticket Price: {{sum}}</p>

In your .ts file, you can access the sum by just calling this.sum

DEMO: https://stackblitz.com/edit/angular-lmjyts?file=src/app/app.component.ts

Upvotes: 2

Related Questions