What is the best way to individually update elements in an array in Ionic v5?

As a newcomer to Ionic and TypeScript, I would appreciate your kindness in helping me with a problem I am facing. I have an array of objects that get updated when adding an 'exercise', where you can specify the number of sets and reps. The issue is that changing the value of the input for sets and reps updates every instance of the array. I understand this is because each instance of the array shares the same [(ngModel)] tag, but I am unsure how to resolve this. Any assistance would be greatly appreciated.

Below is my HTML:


<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-back-button></ion-back-button>
    </ion-buttons>
    <ion-title>Create</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content class ="ion-padding" >
  <ion-item>
    <ion-input class ="name" [(ngModel)]="workoutNameValue" placeholder="Name of workout?"></ion-input>
  </ion-item>
  <ion-button expand="block" (click)="add()">Add Exercise</ion-button>
  <ion-list *ngFor="let exercise of exercises">
    <ion-card>
      <ion-card-content>
        <ion-item lines="none">
          <ion-label><h2>{{exercise}}</h2></ion-label>
          <ion-button (click)="removeExercise()" slot = "end"><ion-icon name="close-outline"></ion-icon></ion-button>
        </ion-item>
        <ion-item>
          <ion-label class = "numberOf"><h3>How many sets?</h3></ion-label>
          <ion-input type="number"  [(ngModel)]="sets"></ion-input>
        </ion-item>
        <ion-item>
          <ion-label class = "numberOf"><h3>How many reps?</h3></ion-label>
          <ion-input type="number" [(ngModel)]="reps"></ion-input>      
        </ion-item>
      </ion-card-content>
    </ion-card>
  </ion-list>
  
</ion-content>

<ion-footer class ="ion-padding">
  <ion-button expand="block" (click)="create(workoutNameValue)">Create Workout</ion-button>
</ion-footer>

And here is my TypeScript code:


import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { ModalController, NavController, NavParams } from '@ionic/angular';
import { ExerciseModalComponent } from '../exercise-modal/exercise-modal.component';
import { WorkoutsPage } from '../workouts/workouts.page';

@Component({
  selector: 'app-create',
  templateUrl: './create.page.html',
  styleUrls: ['./create.page.scss'],
})
export class CreatePage implements OnInit {

  exerciseList: any = "";
  workoutName: string;
  exercises: any[] = [];
  workout: any[] = [];
  exerciseDetails: [{name: string, sets: number, reps: number}] = [{name: null, sets: null, reps: null}];
  sets;
  reps;
  workoutNameValue;

  constructor(private router: Router ,private http: HttpClient, private modalCtrl:ModalController) { }

  ngOnInit() {
    
    this.http.get('https://wger.de/api/v2/exercise/').subscribe((response) => {console.log(response);this.exerciseList = response['results']});
  }

  async add(){
    const modal = await this.modalCtrl.create({
      component : ExerciseModalComponent
      
    });
     
    modal.onDidDismiss()

    .then((data) => {
      this.exerciseList = data.data;
      this.exercises.push(this.exerciseList);
      console.log(this.exercises);
  });
    await modal.present();
  }

  removeExercise(){
    this.exercises.splice(this.exerciseList, 1);
  }

  create(){
    this.exerciseDetails.push({name:this.exerciseList,sets:this.sets,reps:this.reps})
    console.log(this.exerciseDetails);
    this.router.navigate(['./workouts']);
  }
}

I also need help declaring an empty array of objects with specific types. Currently, the initialized object is in the array, but I'm unsure how to initialize it without the object.

Answer №1

<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-back-button></ion-back-button>
    </ion-buttons>
    <ion-title>Create</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content class ="ion-padding" >
  <ion-item>
    <ion-input class ="name" [(ngModel)]="workoutNameValue" placeholder="Name of workout?"></ion-input>
  </ion-item>
  <div *ngFor="let exercise of exerciseDetails;let i of index;">
    <ion-button expand="block" (click)="add(exercise,i)">Add Exercise</ion-button>
    <ion-list>
      <ion-card>
        <ion-card-content>
          <ion-item lines="none">
            <ion-label><h2>{{exercise?.name}}</h2></ion-label>
          </ion-item>
          <ion-item>
            <ion-label class = "numberOf"><h3>How many sets?</h3></ion-label>
            <ion-input type="number"  [(ngModel)]="exercise.sets"></ion-input>
          </ion-item>
          <ion-item>
            <ion-label class = "numberOf"><h3>How many reps?</h3></ion-label>
            <ion-input type="number" [(ngModel)]="exercise.reps"></ion-input>      
          </ion-item>
        </ion-card-content>
      </ion-card>
    </ion-list>
  </div>
  
</ion-content>

<ion-footer class ="ion-padding">
  <ion-button expand="block" (click)="create(workoutNameValue)">Create Workout</ion-button>
</ion-footer>
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { ModalController } from '@ionic/angular';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage {
  exercises: any[] = [];
  exerciseDetails: any = []
  workoutNameValue;

  constructor() { }

  ngOnInit() {
   
  }

  add(item,index) {
    console.log(item,'item')
    this.exerciseDetails[index].sets = item.sets;
    this.exerciseDetails[index].reps = item.reps;
// or 
 this.exerciseDetails.filter( (val, i) => {
      if( i == index) {
        val.sets =  item.sets;
        val.sets = item.reps;
      }
    });
  }

  
  

  create() {
    this.exercises.push({ name: this.workoutNameValue, sets: '', reps:''})
    console.log(this.exercises);
    this.exerciseDetails = this.exercises;
  }
}

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

Creating a JSON utility type for an already existing type, such as JSON<SomeExistingType>

Is there any tool or utility available that can accomplish this task? const foo: Foo = { ... } const bar: string = JSON.stringify(foo) const baz: JSON<Foo> = JSON.parse(foo) JSON<Foo> would essentially mirror all the properties of Foo, with th ...

Error occurs when attempting to filter data through input text pasting in Angular

Currently, I am working on a web application that utilizes the Angular framework and angularfire2. The issue I am encountering is related to the data filter functionality not functioning correctly when pasting copied text. Interestingly, it works perfectly ...

Creating validation for an autosave reactive form in Angular 2: A step-by-step guide

Seeking advice on implementing an autosave feature for a reactive Angular 2 form. The idea is that as the user types in values, the form should automatically save if the input is valid. Below is the code snippet: export class BusinessFoundationsPage { ...

Error message in TypeScript with Puppeteer library: "Element not found"

Incorporating puppeteer-core as a dependency in my TypeScript project within Visual Studio 2019 has caused an issue during the build process. The error message displayed is shown by a red squiggly line under Element: https://i.stack.imgur.com/HfJCu.png ...

Guide on implementing ng-if in an Ionic 2 HTML template

To display records if found and show "no records found" otherwise, I have implemented the code below: <div ng-if="program.videourl"> <video width="100%" controls="controls" preload="metadata" webkit-playsinline="webkit-playsinline" class="vide ...

Choosing the correct key and handling parsing errors

As I work on converting a class component to TypeScript, I encountered an error while trying to implement one of my onChange methods. The error message stated: "Argument of type '{ [x: number]: any; }' is not assignable to parameter of type &ap ...

Ionic 3 Storage Timing Explained

I have a scenario where I am trying to load JSON data from storage and display it on the HTML template of my page. However, when I try to do this, I encounter errors suggesting that the information is not yet available upon entering the page. I'm sta ...

Explain a category of instance used in a template parameter

I am currently working on implementing a basic IOC container with type-checking capabilities. My goal is to pass the "register" method an abstract class type along with an instance of a derived type. In the "resolve" function, I aim to provide an abstrac ...

Utilizing Json Data for Master-Detail Views in Ionic

I'm currently working with Ionic v1 and I am facing an issue while trying to create a list and its corresponding detail view. When I click on an item in the list, the detail view does not display the data of the selected item. Factory .factory(&apos ...

Combining nested Observables within an outer array without using inner subscribe (RxJS)

Looking at the TypeScript functions below, which are used for async HTTP-Calls: public retrieveAllMembersIdsFromGroup(groupId: string): Observable<string[]> public retrieveMember(memberId: string): Observable<Member> How can these be combined ...

Experimenting with throws using Jest

One of the functions I'm testing is shown below: export const createContext = async (context: any) => { const authContext = await AuthGQL(context) console.log(authContext) if(authContext.isAuth === false) throw 'UNAUTHORIZED' retu ...

Steps for Properly Defining Next.js getServerSideProps as a Function Declaration

I've been working on implementing getServerSideProps (additional information available here, and detailed API documentation here), but my challenge lies in utilizing it as a function declaration instead of an expression. Despite searching for relevant ...

What is the best way to globally incorporate tether or any other feature in my Meteor 1.3 TypeScript project?

I've been working hard to get my ng2-prototype up and running in a meteor1.3 environment. Previously, I was using webpack to build the prototype and utilized a provide plugin to make jQuery and Tether available during module building: plugins: [ ne ...

Transferring data from a child to a parent component in Angular 2 using a combination of reactive and template-driven approaches

Recently delving into Angular 2 ( and Angular overall ) , I found myself at a crossroads with my co-worker. He opted for the template-driven method while I leaned towards the reactive-driven approach. We both built components, with his being a search produ ...

Unable to perform a default import in Angular 9 version

I made adjustments to tsconfig.json by adding the following properties: "esModuleInterop": true, "allowSyntheticDefaultImports": true, This was done in order to successfully import an npm package using import * as ms from "ms"; Despite these changes, I ...

What is the best way to pass a conditional true or false value to React boolean props using TypeScript?

I am currently utilizing the Material UI library in combination with React and Typescript. Whenever I attempt to pass a conditional boolean as the "button" prop of the component, I encounter a typescript error stating: Type 'boolean' is not assi ...

Discover the method for dynamically setting the rangeSelector's min and max values multiple times in Angular Highcharts

I'm looking to dynamically set the range of an angular highstock chart by interacting with another component such as a table or button. For example, attempting to use setExtremes for selecting range T1 or T2 does not seem to work properly in this cod ...

The test window displays the Angular test component

During my test runs, I have noticed a strange occurrence. Components are appearing in the DOM near where the tests are being conducted. What's even more peculiar is that only one component is visible at a time. This phenomenon seems to occur with ever ...

Utilize Material icons in CSS for a list in Angular 9

My task involves altering the HTML provided by a content management system for one of our applications. Specifically, I need to replace all "ul"s with <mat-icon>check_circle_outline</mat-icon> instead of the default "." The challenge lies in t ...

I prefer not to run the next.js SWR until after the initial rendering

Development Setup ・ next.js ・ typescript ・ swr This uses swr for communication purposes. I am looking to only trigger it when the query value changes. However, it is also being executed during the initial rendering. How can I prevent it ...