I'm picking up Angular (and Typescript with it). I created a small app that has two components. It's for keeping track of work hours (yeah, I know, there are COTS products for that, this is for educational purposes).
One component is for creating a new hour entry (employee project hours date). It has some input boxes and an "Add" button.
The other component shows the hours that the user booked for the selected day. When the "Add" button is clicked in the first component, this component should refresh the data from the API/database.
When I google this, all answers point to @Input arguments. In this case, the detail component has an employeeId and a date as input. These inputs don't change. Only the result (database content) changes for those parameters. I thought of calling one of the methods on the detail component from the container of those two components, but I found no way to do that.
How can I force the detail component to refresh, after the "Add" button is clicked?
Would be grateful for any pointers.
EDIT: Relevant code
dailyHoursOverview.components.ts
import { HttpClient } from "@angular/common/http";
import { Component, Input, OnChanges, OnInit, SimpleChanges } from "@angular/core";
import { Activity } from "../shared/Activity";
import { Employee } from "../shared/Employee";
import { Project } from "../shared/Project";
@Component({
selector: "hour-daily",
templateUrl: "./dailyHoursOverview.component.html"
})
export class DailyHoursOverview implements OnInit, OnChanges
{
// @Input() date: string = "";
@Input() employeeId: number = 0;
@Input() date: string = "";
_http: HttpClient;
entries: HourEntry[] = [];
totalHours: number= 0;
constructor(http: HttpClient) {
this._http = http;
}
ngOnChanges(changes: SimpleChanges): void {
this.refreshData();
}
ngOnInit(): void {
this.refreshData();
}
refreshData() {
this._http.get<HourEntry[]>("http://localhost:5257/Employee/" this.employeeId "/HourEntry/ByDay/" this.date)
.subscribe(
result => {
this.entries = result;
this.totalHours = this.entries.reduce((sum, entry) => sum (entry.hours), 0);
},
error => console.error(error)
);
}
}
interface HourEntry {
project: Project;
activity: Activity;
employee: Employee;
hours: number;
date: string;
}
main.component.html (container of both sub components)
<div >
<div >
<div >
<hours-new [employeeId]="employeeId" [hourDate]="date" (entryCreated)="onEntryCreated();"></hours-new>
</div>
</div>
<div >
<div >
<hour-daily [employeeId]="employeeId" [date]="date"></hour-daily>
</div>
</div>
</div>
newHourEntry.component.ts
import { HttpClient } from '@angular/common/http';
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Activity } from '../shared/Activity';
import { Project } from '../shared/Project';
import { Employee } from '../shared/Employee';
import { NewHourEntryDto } from '../shared/NewHoursEntryDto';
@Component({
selector: "hours-new",
templateUrl: "./newHourEntry.component.html"
})
export class NewHourEntryComponent implements OnInit {
@Input() employeeId: number = 0;
@Input() hourDate: string = "";
@Output() entryCreated: EventEmitter<any> = new EventEmitter();
private _http: HttpClient;
employeeName: string = "";
hourEntry: NewHourEntryDto;
projects: Project[];
activities: Activity[];
constructor(http: HttpClient) {
this._http = http;
this.hourEntry = { "activityId": 0, "projectId": 0, "date": "", "hours": 0, "employeeId": 0 };
this.projects = [];
this.activities = [];
}
ngOnInit(): void {
// Get options for comboboxes
this._http.get<Project[]>('http://localhost:5257/Project')
.subscribe({
next: result => { this.projects = result; },
error: error => console.error(error)
});
this._http.get<Activity[]>("http://localhost:5257/Activity")
.subscribe({
next: result => { this.activities = result; },
error: error => console.error(error)
});
this._http.get<Employee>("http://localhost:5257/Employee/" this.employeeId)
.subscribe({
next: result => { this.employeeName = result.name; },
error: error => console.error(error)
});
}
createHourEntry(): void { // OnClick for the "Add" Button
this.hourEntry.date = this.hourDate;
this.hourEntry.employeeId = this.employeeId;
this._http.post("http://localhost:5257/HourEntry", this.hourEntry)
.subscribe({
next: result => { },
error: error => console.error(error)
});
this.entryCreated.emit();
}
}
CodePudding user response:
you can use @Input() setters
Here is an example that shows what I mean
I hope it is useful for you
CodePudding user response:
I would let main.component.html handle the creation and refreshing the data (smart) and only pass data to newHourEntry and dailyHoursOverview (dumb) cfr Smart and dumb components