Reputation: 435
I have following script:
this.employees.forEach( lpEmpl => {
lpEmpl.vacation.forEach( lpVac => {
const start = (new Date(lpVac.start)).toLocaleDateString('en-US', options);
const end = (new Date(lpVac.end)).toLocaleDateString('en-US', options);
retVal.push( {
title: `${lpEmpl.lastname}`,
start: `${start}`,
end: `${end}`,
color: '#efefef'
});
});
});
My classes look like this:
export class Vacation {
id: number;
start: Date;
end: Date;
}
export class Employee {
id: number;
lastname: string;
firstname: string;
email: string;
availability: Availability;
vacation: Vacation[];
}
When I start the application and the script is executed it "ends" in a infinite loop. To find the error I debugged the application but cannot find anything wrong. Interestingly when I slow down the app by debugging, the loop ends up normal and the data is displayed correctly.
Is it because I use nested loops?
Thanks!
EDIT:
The component:
@Component({
selector: 'calendar',
templateUrl: './calendar.html',
styleUrls: ['./calendar.scss'],
providers: [BaThemeConfigProvider, EmployeeService]
})
export class Calendar {
calendarConfiguration: any;
_calendar: Object;
@Input()
employees: Employee[];
constructor(private _baConfig: BaThemeConfigProvider,
private _basicTablesService: EmployeeService) {
_basicTablesService.getEmployees().subscribe(results => this.employees = results);
this.calendarConfiguration = this.getData();
this.calendarConfiguration.select = (start, end) => this._onSelect(start, end);
}
public onCalendarReady(calendar):void {
this._calendar = calendar;
}
private getData(): any {
const dashboardColors = this._baConfig.get().colors.dashboard;
return {
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
defaultDate: '2018-10-26',
selectable: true,
selectHelper: true,
editable: true,
eventLimit: true,
events: this.printDays()
};
}
private _onSelect(start, end): void {
if (this._calendar !== null) {
let title = prompt('Event Title:');
let eventData;
if (title) {
eventData = {
title: title,
start: start,
end: end
};
jQuery(this._calendar).fullCalendar('renderEvent', eventData, true);
}
jQuery(this._calendar).fullCalendar('unselect');
}
}
private printDays(): any {
const retVal = [];
const options: Intl.DateTimeFormatOptions = {
day: '2-digit', month: '2-digit', year: 'numeric'
};
this.employees.forEach( lpEmpl => {
lpEmpl.vacation.forEach( lpVac => {
const start = (new Date(lpVac.start)).toLocaleDateString('en-US', options);
const end = (new Date(lpVac.end)).toLocaleDateString('en-US', options);
retVal.push( {
title: `${lpEmpl.lastname}`,
start: `${start}`,
end: `${end}`,
color: '#efefef'
});
});
});
return retVal;
}
the view:
<ba-full-calendar [baFullCalendarConfiguration]="calendarConfiguration" baFullCalendarClass="blurCalendar" (onCalendarReady)="onCalendarReady($event)"> </ba-full-calendar>
The embedded component:
@Component({
selector: 'ba-full-calendar',
templateUrl: './baFullCalendar.html'
})
export class BaFullCalendar {
@Input() baFullCalendarConfiguration:Object;
@Input() baFullCalendarClass:string;
@Output() onCalendarReady = new EventEmitter<any>();
@ViewChild('baFullCalendar') public _selector:ElementRef;
ngAfterViewInit() {
let calendar = jQuery(this._selector.nativeElement).fullCalendar(this.baFullCalendarConfiguration);
this.onCalendarReady.emit(calendar);
}
}
I use a template from akveo, that offers a calender component. So i cannot post the complete code in here.
Upvotes: 0
Views: 1948
Reputation: 71901
Problem is the misunderstanding of the async nature of JS, the subscribe callback is called after getData
. Refactor to this:
constructor(
private _baConfig: BaThemeConfigProvider,
private _basicTablesService: EmployeeService
) {}
ngAfterViewInit(): void {
this._basicTablesService.getEmployees().subscribe(results => {
this.employees = results;
this.calendarConfiguration = this.getData();
this.calendarConfiguration.select = (start, end) => this._onSelect(start, end);
let calendar = jQuery(this._selector.nativeElement).fullCalendar(
this.baFullCalendarConfiguration
);
this.onCalendarReady.emit(calendar);
});
}
Let's ignore the fact of using jQuery
inside an angular app though ;) Anyways, it was indeed a race condition, one that could only be won by using a breakpoint. This made sure the request for data was finished, and therefore already set the this.employees
value. Without a breakpoint, the getData()
was called before the http request finished.
Upvotes: 1