Skip to content
Advertisement

Why doesn’t this function replace the existing value in the associative array – Angular

I’ve made sure to import my interface:

import { DayMoodModel } from '../objectModels/dayMood'; 

I initialized the array of objects with some test data (the date property has the type Date, in case you’re wondering):

  moodsAssigned: DayMoodModel[] = [
    { 
      date: this.today,
      mood: 'great'
    }
  ]

This is the function in question:

  addMood(moodName: string) {
    let obj: DayMoodModel = { date: this.currentDay, mood: moodName };
    for(let i = 0; i < this.moodsAssigned.length; i++) {
      if(this.moodsAssigned[i].date == this.currentDay) {
        this.moodsAssigned[i].mood = moodName;
      }
      else if(i == this.moodsAssigned.length - 1 && this.moodsAssigned[i].date != this.currentDay) {
        this.moodsAssigned.push(obj);
      }
    }
    console.log(this.moodsAssigned);
  }

When called, on a date that’s already in the array of objects, it acts like that data isn’t already in there for that date. I’ll include a photo of the console log at the bottom of the post. In this test I called the function on the date that is already in the array, expecting it to replace the ‘mood’ value with the new mood, but it just added a new object to the array.

I’ve gone over this code multiple times, logging out variables at key places to ensure it’s reading everything correctly. I don’t know what’s wrong with the logic..

picture of the array logged to the console

Answer

The problem is you’re trying to compare two complex objects, yet you only care about the day, month, and year. Just a straight == isn’t going to work.

Here is a proper comparison function from another question: How to tell if two dates are in the same day or in the same hour?

function sameDay(d1, d2) {
  return d1.getFullYear() === d2.getFullYear() &&
    d1.getMonth() === d2.getMonth() &&
    d1.getDate() === d2.getDate();
}

However, if you don’t want duplicates, instead of brute-force searching an array you can utilize ISO strings (YYYY-MM-DDTHH:MM:SS) as keys in a Map. You can just take the first 10 characters if you don’t care about the timestamp.

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

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.scss'],
})
export class TestComponent implements OnInit {
  today = this.getISO(new Date());
  moodsAssigned = new Map<string, string>([
    [this.today, 'great'],
  ]);

  constructor() {}

  ngOnInit(): void {}

  getISO(date: Date) {
    return date.toISOString().substring(0, 10);
  }

  addMood(moodName: string) {
    this.moodsAssigned.set(this.today, moodName);
  }
}

You can also convert an ISO string back into a Date object with the Date constructor – both YYYY-MM-DDTHH:MM:SS and YYYY-MM-DD work.

const today = new Date("2022-01-30")
Advertisement