Ways to dynamically change values within a single Angular component when making multiple selections using mat-select

Imagine you're developing a cutting-edge pizza ordering application complete with a MenuComponent that showcases all the delicious menu items offered by the restaurant.

Each item is presented as a unique card displaying all the essential information. To enhance user experience, you've included the option to customize items with various toppings.

The challenge arises when you need to dynamically update the base price of an item upon selecting additional toppings.

Take a look at the structure of my menu.component.html:

    <div fxFlex *ngFor="let category of categories">
        <h3>{{category.name}}</h3>
            <div *ngFor="let item of items">
                <mat-card *ngIf="item.category == category.name" class="itemcard">

                    <mat-card-header>

                        <mat-card-title>{{item.name}}</mat-card-title>
                        <mat-card-subtitle>{{item.category}}</mat-card-subtitle>
                        <span class="flex-spacer"></span>
                        <div>$ {{item.price_large}}</div>
                    </mat-card-header>
                    <mat-card-content>
                        <mat-form-field>
                            <mat-label>Extra Toppings</mat-label>
                            <mat-select multiple>
                                <mat-option *ngFor="let topping of toppings" [value]="topping.rate">{{topping.name}}</mat-option>
                            </mat-select>
                        </mat-form-field>
                    </mat-card-content>
                    <span class="flex-spacer"></span>

                    <button mat-button color="primary"><i class="fa fa-plus-circle"></i> Add to Cart</button>
                </mat-card>

            </div>
    </div>


In the div section, I'm currently displaying the base price and aim to update it dynamically upon selecting extra toppings. I've considered using a two-way binding approach, but I'm looking for fresh ideas to move forward.

Additionally, I'm seeking guidance on how to ensure that the price changes only reflect on the specific item selected.

Answer №1

For creating a new component to represent a menu item, you can define a MenuItemComponent. To pass 'item' and 'category' as variables to this component through parent-child relationship, refer to https://angular.io/guide/component-interaction. Include a variable for the selected topping price and set up an event handler for the selection to update this variable. Here's how the new component can be structured:

@Component({
    selector: 'app-menu-item',
    templateUrl: './menuitem.component.html'
  })
  export class MenuItemComponent {
    @Input() item;
    @Input() category;
    private chosenToppingPrice = 0;

    constructor() {}

    onToppingSelect(event) {
      this.chosenToppingPrice = event.target.value;
    }
  }

The HTML structure of the component will be:

<mat-card *ngIf="item.category == category.name" class="itemcard">
    <mat-card-header>
        <mat-card-title>{{item.name}}</mat-card-title>
        <mat-card-subtitle>{{item.category}}</mat-card-subtitle>
        <span class="flex-spacer"></span>
        <div>$ {{item.price_large + chosenToppingPrice}}</div>
    </mat-card-header>
    <mat-card-content>
        <mat-form-field>
            <mat-label>Extra Toppings</mat-label>
            <mat-select multiple>
                <mat-option *ngFor="let topping of toppings" [value]="topping.rate" (change)="onToppingSelect($event)">{{topping.name}}</mat-option>
            </mat-select>
        </mat-form-field>
    </mat-card-content>
    <span class="flex-spacer"></span>
    <button mat-button color="primary"><i class="fa fa-plus-circle"></i> Add to Cart</button>
</mat-card>

And the menu.component.html will look like:

<div fxFlex *ngFor="let category of categories">
    <h3>{{category.name}}</h3>
    <div *ngFor="let item of items">
        <app-menu-item [item]="item" [category]="category"></app-menu-item>
    </div>
</div>

This approach allows for individual manipulation of each card data. Instead of using

*ngIf="item.category == category.name"
, consider utilizing the map function to streamline the process.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the process for setting up a subrouter using React Router v6?

This is the current React Router setup I am using: const router = createBrowserRouter([ { path: "/", element: ( <Page activeNav="home" > <Home /> </Page> ) }, { ...

Adding a QR code on top of an image in a PDF using TypeScript

Incorporating TypeScript and PdfMakeWrapper library, I am creating PDFs on a website integrated with svg images and QR codes. Below is a snippet of the code in question: async generatePDF(ID_PRODUCT: string) { PdfMakeWrapper.setFonts(pdfFonts); ...

Select dropdown menu with dynamic search feature

I need assistance with creating an editable mat select dropdown that fetches data from an API as an array of objects. I want the dropdown to have a filter autocomplete feature where if a user types 'R', it should filter out options starting with ...

Tips for transforming a Json array into an object in Angular 5

I am working with a Json array that looks like this: [{"name":"ip","children":{"label":"ip","value":"","type":"text","validation":"{ required: true}"}} ,{"name":"test","children":{"label":"test","value":"","type":"text","validation":"{ required: true}"}} ...

Invalid Redux store: Element type is not valid; a string type is expected

I am running into an issue while setting up the redux store with typescript for the first time. The error message I am encountering is: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) ...

I need a way to call a function in my Typescript code that will update the total value

I am trying to update my total automatically when the quantity or price changes, but so far nothing is happening. The products in question are as follows: this.products = this.ps.getProduct(); this.form= this.fb.group({ 'total': ...

Is it possible to access the line number of a node using the TypeScript compiler API?

Is there a method to retrieve the line number of a node besides using node.pos? For example, something like node.lineNumber? ...

Tips for resolving the "trim" of undefined property error in Node.js

Looking to set up a basic WebAPI using Firebase cloud functions with express and TypeScript. Here's the code I have so far: import * as functions from 'firebase-functions'; import * as express from 'express'; const app = express( ...

Setting up Datatable in Angular 2+ without relying on jQuery

I need assistance with initializing a datatable for a table that has a unique id. Can you provide guidance on the syntax to achieve this? Here is an example of my table structure: <table id="myDataTable"> <thead> <tr> ...

Angular 9 - Auto-adjust the height of the text box as the user types, returning to its original size when no longer in focus

I need a solution where an input field's height adjusts to display the user's entry, then returns to normal size when they click away. It should function similar to this example image: https://i.stack.imgur.com/yKcik.png Once the user enters th ...

Ways to address memory leakage issues in Angular

Is there a way to manually optimize the Garbage Collector by forcefully pushing variables into it? For example, if we have a root or global level variable in an Angular component that is no longer needed when switching to another page, how can we ensure it ...

Angular material is experiencing an issue where content is being cut off or

I am currently working on a project using AngularJS for a web application. I have encountered an issue where some of the content in the md-content element is being clipped. For instance, the body tag has the style: overflow: hidden, and the child md-conte ...

Utilizing Angular's reactive forms to populate an array field with an array of data

I am currently using Angular 6 along with Reactive form to create a form. Within the ngOnInit() function, I have set up a form group in the following manner: this.landingPageForm = this.formBuilder.group({ title: new FormControl('', [ Val ...

What could be the reason for the defaultCommandTimeout not functioning as expected in my script

Is there a way to wait for only one particular element in Cypress without having to add wait commands everywhere in the test framework? I've come across the solution of adding defaultCommandTimeout in the cypress.json file, but I don't want it t ...

Ngrx/effects will be triggered once all actions have been completed

I've implemented an effect that performs actions by iterating through an array: @Effect() changeId$ = this.actions$.pipe( ofType(ActionTypes.ChangeId), withLatestFrom(this.store.select(fromReducers.getAliasesNames)), switchMap(([action, aliases ...

Selecting a GoJS Node using keys

In Angular with TypeScript, what is the best way to select a node from a diagram based on its key? Currently, I am required to left-click a newly created node in order to select it, but I would like for it to be automatically selected upon creation. I ha ...

Utilizing Arrow Functions with Parameters in Angular

I am currently working on an Angular 4 app and I am attempting to create a queue of actions. Each action should only be executed after the previous one has finished, and each action should receive its own set of parameters. public activeRegistrationAndS ...

Displaying Image Preview in Angular 2 After Uploading to Firebase Storage

At the moment, I am facing an issue where the uploaded image is not being displayed after the uploadTask is successful. This problem arises due to the asynchronous loading nature of the process, causing the view to attempt to display the image before the u ...

How can we design a Protobuf structure for a map that contains an array of objects as the value?

I need help with encoding a map in a protobuf format. Here is an example of the map: const newVisMap = new Map<number, IOutput[]>(); The map contains an array of objects that share a common interface, as shown below (with one optional property): int ...

Setting a default value for a complex prop in Vue through Type-based props declarations

I'm struggling with this issue: Argument of type 'HelloWorldProps' is not assignable to parameter of type 'InferDefaults<LooseRequired<HelloWorldProps>>'. Types of property 'complexProp' are incompatible.ts( ...