Search code examples
angularangular-servicesangular-inputangular-output

Why doesn't a value update correctly in object and html?


I am making an itinerary generator, all the activities have their duration (in minutes) and the itinerary have a start time so when I generate the itinerary I update the hour in base of activity duration and show the updated hour in the next activity. For example if itinerary start at 6:00 PM and the first activity has a time of 5 minutes, that time will be added to the hour and it will display in the HTML something like:

  • 06:00 First activity (5 min)
  • 06:05 Second activity (2 min)
  • 06:07 Third activity (10 min)

But when update the time, instead of passing it to the next activity it is added to it. For example:

  • 06:05 First activity (5 min)
  • 06:07 Second activity (2 min)
  • 06:17 Third activity (10 min)

Mi code:

Activity Interface:

export interface Activity{
  activityName : string;
  duration     : number;
  zone         : string;
  participants : Participante [];
  time        ?: Date
}

Program component:

export class ProgramComponent {

  program    !: Program[]
  startTime  !: Date; 
  time       !: Date; //It's the time I send and receive from child



  constructor( private gpService: ProgramGeneratorServices ) {
    //I save the start time from Form, don't show all the interfaces 'çause I don't think it's necessary
    this.startTime = this.program[0].startTime;

    this.time = this.programa[0].startTime;
  }

  //This function is only for reset the hour to start, I do two itinerary for 2 weeks so I need restart the hour for ngFor
  resetHour() {
    this.time = this.startTime
  }

  //This function update the hour inside this program component
  updateMinutes( activity?: Activity ) {
    this.time = this.gpService.addMinutes( this.time, activity?.duration);
  }

  //This function update the hour receiving the time from a child component
  updateTime( updatedTime: Date ) {
    this.time = updatedTime;
  }
}

Program html:

<div *ngFor="let subPrograma of programa;"
          class="mb-5"> {{ resetHour() }}

   <div class="my-3">
          <div class="col-6 titulo_seccion ps-2">
            {{ subProgram.sections[1].sectionName | uppercase }}
          </div>
         
//Send the activity data and the time to child and returns the updated time to send to the next activity
          <app-actividad
            *ngFor="let activity of subProgram.sections[1].activities"
            [activity]="activity"
            [time]="time"
            (timeChange)="updateTime($event)"
          ></app-actividad>
   </div>
</div>

Activity app (Child component):

export class ActividadComponent implements OnInit{


  @Input() activity  !: Actividad;
  @Input() time      !: Date;

  @Output() timeChange = new EventEmitter<Date>();

  constructor( private gpService: ProgramGeneratorService ) {
  }

//In OnInit assign time to activity and next to update the time whit a services function
  ngOnInit(): void {
    this.activity.time = this.time;
    this.addMinutes();
  }

  addMinutes(): void {
    this.time = this.gpService.addMinutes( this.time, this.activity.duration);
    this.timeChange.emit( this.time );
  }

}

Activity HTMl (Child)

<div class="row">
  
<div class="col-4">
    <div class="row">
      <div class="col text-start">
        <span> {{ time | date: 'hh:mm' }}
          <span class="cr">
            <span class="point">•</span>
               //THIS is where I print the time
            {{ activity.activityName }} 
                <span *ngIf="activity.time > 0" class="ms-1">
                    ({{ activity.time }} mins)
               </span>
          </span>
        </span>
      </div>

    </div>
  </div>


</div>

Program Generator Services:

export class GeneradorProgramaService {

  constructor( private http: HttpClient ) { }

//This is the function that updates the time
  addMinutes( currentTime: Date, mins: number = 5 ): Date {
    return new Date( currentTime.getTime() + mins * 60000 );
  }
}

Hope someone can help me, I've been stuck for a few hours (If you see something weird is because I omitted code that I think isn't necessary and only put the part related to the problem).


Solution

  • You use time in the HTML and you override time in the addMinutes function in the child component.

    ...
    
    ngOnInit(): void {
        this.activity.time = this.time;
        this.addMinutes();
    }
    
    addMinutes(): void {
    
     // Here, you override the time. That's why you see the weird one in the HTML.
     this.time = this.gpService.addMinutes( this.time, this.activity.duration);
    
     this.timeChange.emit( this.time );
    }
    
    
    addMinutes_NoOverride() {
    
      // Store the new time in a const and then emit it.
      const newTime = this.gpService.addMinutes(this.time, this.activity.duration);
    
      this.timeChange.emit(newTime);
    }