(Angular) "Property 'display' is used before its initialization" - html

I'm trying to create a timer in Angular in which I should be able to save the various values of the time (start, finish and length, right now just length) and "print" them in HTML.
I tried inserting this.display in the length property of the interface "result" but it says "Property 'display' is used before its initialization". I think I should be using the ngOnInit or the constructor in some way but I'm unsure on how to proceed.
I've created the function clearTimer() which should both work as a function for clearing the current displayed timer and saving the value in a list.
Feel free to also correct my current code if you don't find it optimal for its purpose.
HTML:
<div class="modalbox" [class.active]="modalboxActive">
<div class="modal">
<p>What did you do?</p>
<input type="text" [(ngModel)]="activity.name" #task />
<button
(click)="addTask(task.value)"
(click)="task.value = ''"
[disabled]="activity.name === ''"
(click)="clearTimer()"
>
OK
</button>
</div>
</div>
<div class="boxSuper">
<div class="boxLeft">
<div class="containerUp">
<button id="start" (click)="startTimer()">START</button>
<button id="pause" (click)="pauseTimer()">PAUSE</button>
<button id="stop" (click)="stopTimer()">STOP</button>
</div>
<div class="containerDown">
<p>{{ display }}</p>
</div>
</div>
<div class="boxRight">
<div class="containerLeft">
<div class="leftList">
<ul class="listElement" *ngFor="let item of duration">
<li>
Length:
<span>{{ item.length }}</span>
</li>
</ul>
</div>
</div>
<div class="containerRight">
<div class="rightList">
<ul class="listElement" *ngFor="let item of list">
<li>
Activity:
<span>{{ item.name }}</span>
</li>
</ul>
</div>
</div>
</div>
</div>
TS:
import { importExpr } from '#angular/compiler/src/output/output_ast';
import { Component, OnInit } from '#angular/core';
import { timer } from 'rxjs';
import { Activity } from '../activity';
import { Result } from '../result';
#Component({
selector: 'app-timer',
templateUrl: './timer.component.html',
styleUrls: ['./timer.component.css'],
})
export class TimerComponent implements OnInit {
ngOnInit() {}
time: number = 0;
display: string | undefined;
interval: any;
modalboxActive = false;
activity: Activity = {
name: '',
};
list: any[] = [];
result: Result = {
start: undefined,
end: undefined,
length: this.display, // here display gets marked in red and it says "Property 'display' is used before its initialization."
};
duration: any[] = [];
addTask(item: string) {
this.list.push({ name: this.activity.name });
this.activity.name = '';
this.modalboxActive = false;
}
clearTimer() {
this.duration.push({ length: this.result.length });
}
startTimer() {
console.log('go');
this.interval = setInterval(() => {
if (this.time === 0) {
this.time++;
} else {
this.time++;
}
this.display = this.transform(this.time);
}, 1000);
}
transform(value: number): string {
var sec_num = value;
var hours = Math.floor(sec_num / 3600);
var minutes = Math.floor((sec_num - hours * 3600) / 60);
var seconds = sec_num - hours * 3600 - minutes * 60;
return hours + ':' + minutes + ':' + seconds;
}
pauseTimer() {
clearInterval(this.interval);
}
stopTimer() {
this.modalboxActive = true;
clearInterval(this.interval);
console.log('show');
}
}
"Result" interface:
export interface Result {
start: string | undefined;
end: string | undefined;
length: string | undefined;
}

Related

Angular App deosn't dispay data from table althgouh the exist in the console

One of the most important things to make a website friendly is the response time, and pagination comes for this reason. For example, this bezkoder.com website has hundreds of tutorials, and we don’t want to see all of them at once. Paging means displaying a small number of all, by a page.
here is the class for the "Dossier entity":
export class Dossier {
id?: any;
title?:string;
creationDate?:string;
statusDossier?:string;
documentNumber?:number;
activityTitle?:string;
published?:boolean;
}
This is a kind of server-side paging, where the server sends just a single page at a time. ngx-pagination supports this scenario, so We actually only need to use tutorials and totalItems when working with this library.
This service will use Angular HttpClient to send HTTP requests.
services/dossier.service.ts
import { Injectable } from '#angular/core';
import {HttpClient} from "#angular/common/http";
import {Observable} from "rxjs";
import {Dossier} from "../models/dossier.model";
const baseUrl = 'http://localhost:8080/api/dossiers';
#Injectable({
providedIn: 'root'
})
export class DossierService {
constructor(private http: HttpClient) { }
getAll(params: any): Observable<any> {
return this.http.get<any>(baseUrl, { params });
}
get(id: any): Observable<Dossier> {
return this.http.get(`${baseUrl}/${id}`);
}
create(data: any): Observable<any> {
return this.http.post(baseUrl, data);
}
update(id: any, data: any): Observable<any> {
return this.http.put(`${baseUrl}/${id}`, data);
}
delete(id: any): Observable<any> {
return this.http.delete(`${baseUrl}/${id}`);
}
deleteAll(): Observable<any> {
return this.http.delete(baseUrl);
}
findByTitle(title: any): Observable<Dossier[]> {
return this.http.get<Dossier[]>(`${baseUrl}?title=${title}`);
}
}
We can customize the label displayed on the “previous”/”next” link using previousLabel/nextLabel, and enable “responsive” to hide individual page links on small screens.
For pagination, we’re gonna use DossierService.getAll() methods.
components/dossiers-list/dossiers-list.component.ts
export class DossiersListComponent implements OnInit {
dossiers: Dossier[] = [];
currentDossier: Dossier = {};
currentIndex = -1;
title = '';
page = 1;
count = 0;
pageSize = 3;
pageSizes = [3, 6, 9];
constructor(private dossierService: DossierService) { }
ngOnInit(): void {
this.retrieveDossiers();
}
getRequestParams(searchTitle: string, page: number, pageSize: number): any {
let params: any = {};
if (searchTitle) {
params[`title`] = searchTitle;
}
if (page) {
params[`page`] = page - 1;
}
if (pageSize) {
params[`size`] = pageSize;
}
return params;
}
retrieveDossiers(): void {
const params = this.getRequestParams(this.title, this.page, this.pageSize);
this.dossierService.getAll(params)
.subscribe({
next: (data) => {
const { dossiers, totalItems } = data;
this.dossiers = dossiers;
this.count = totalItems;
console.log(data);
},
error: (err) => {
console.log(err);
}
});
}
handlePageChange(event: number): void {
this.page = event;
this.retrieveDossiers();
}
handlePageSizeChange(event: any): void {
this.pageSize = event.target.value;
this.page = 1;
this.retrieveDossiers();
}
refreshList(): void {
this.retrieveDossiers();
this.currentDossier = {};
this.currentIndex = -1;
}
setActiveTutorial(dossier: Dossier, index: number): void {
this.currentDossier = dossier;
this.currentIndex = index;
}
removeAllDossiers(): void {
this.dossierService.deleteAll()
.subscribe({
next: res => {
console.log(res);
this.refreshList();
},
error: err => {
console.log(err);
}
});
}
searchTitle(): void {
this.page = 1;
this.retrieveDossiers();
}
}
and finally here is the html file:
<div class="list row">
<div class="col-md-8">
<div class="input-group mb-3">
<input
type="text"
class="form-control"
placeholder="Search by title"
[(ngModel)]="title"
/>
<div class="input-group-append">
<button
class="btn btn-outline-secondary"
type="button"
(click)="searchTitle()"
>
Search
</button>
</div>
</div>
</div>
<div class="col-md-12">
<pagination-controls
previousLabel="Prev"
nextLabel="Next"
[responsive]="true"
(pageChange)="handlePageChange($event)"
></pagination-controls>
</div>
<div class="col-md-6">
<h4>Tutorials List</h4>
<ul class="list-group">
<li
class="list-group-item"
*ngFor="
let tutorial of dossiers | paginate : {
itemsPerPage: pageSize,
currentPage: page,
totalItems: count
};
let i = index
"
[class.active]="i == currentIndex"
(click)="setActiveTutorial(tutorial, i)"
>
{{ tutorial.title }}
</li>
</ul>
</div>
<div class="col-md-6">
<!-- <app-tutorial-details-->
<!-- [viewMode]="true"-->
<!-- [cu]="currentDossier"-->
<!-- ></app-tutorial-details>-->
</div>
<div class="mt-3">
<button class="m-3 btn btn-sm btn-danger" (click)="removeAllDossiers()">
Remove All
</button>
Items per Page:
<select (change)="handlePageSizeChange($event)">
<option *ngFor="let size of pageSizes" [ngValue]="size">
{{ size }}
</option>
</select>
</div>
</div>

How can I remove items from a list of tasks in Angular?

I'm creating a scheduler in which I can add tasks I've done in a certain amount of time. The tasks get added in a to-do list-like manner.
I'm trying to remove individual items from a list both from the front-end and from LocalStorage but I haven't found a solution that works yet. The function I'm trying to make work is "RemoveTask()".
Here's my code:
HTML:
<div class="modalbox" [class.active]="modalboxActive">
<div class="modal">
<p>What did you do?</p>
<input type="text" [(ngModel)]="activity.name" maxlength="22" />
<button (click)="addTask()" [disabled]="activity.name === ''">OK</button>
</div>
</div>
<div class="boxSuper">
<div class="boxLeft">
<div class="containerUp">
<button id="start" (click)="startTimer()">START</button>
<button id="pause" (click)="pauseTimer()">PAUSE</button>
<button id="stop" (click)="stopTimer()">STOP</button>
<button (click)="removeAll()">REMOVE ALL</button>
</div>
<div class="containerDown">
<p>{{ display }}</p>
</div>
</div>
<div class="boxRight">
<div class="containerLeft">
<ul class="listElementLeft" *ngFor="let item of tasks">
<div class="card">
<ul class="order">
<li class="list-group-item"><span>START:</span>{{ item.start }}</li>
<li class="list-group-item"><span>END:</span>{{ item.end }}</li>
<li class="list-group-item">
<span>LENGTH:</span>{{ item.length }}
</li>
</ul>
<div class="subcard">
<li>
{{ item.name }}
</li>
</div>
<div class="buttonCard">
<button (click)="removeTask(item.id)">REMOVE</button>
</div>
</div>
</ul>
</div>
</div>
</div>
TS:
import { importExpr } from '#angular/compiler/src/output/output_ast';
import { Component, OnInit } from '#angular/core';
import { timer } from 'rxjs';
import { Activity } from '../activity';
import { Result } from '../result';
#Component({
selector: 'app-timer',
templateUrl: './timer.component.html',
styleUrls: ['./timer.component.scss'],
})
export class TimerComponent implements OnInit {
ngOnInit() {
this.tasks = JSON.parse(localStorage.getItem('token') ?? '');
}
time: number = 0;
display: string | undefined;
interval: any;
modalboxActive = false;
startTime: string | undefined;
endTime: string | undefined;
id: number | undefined;
activity: Activity = {
name: '',
};
tasks: Result[] = [];
startFunc() {
this.startTime = new Date().toString().split(' ')[4];
}
endFunc() {
this.endTime = new Date().toString().split(' ')[4];
}
//task actions
addTask() {
var el: Result = {
id: this.id!,
name: this.activity.name,
end: this.endTime,
start: this.startTime,
length: this.display,
};
this.tasks.push(el);
localStorage.setItem('token', JSON.stringify(this.tasks));
this.activity.name = '';
this.modalboxActive = false;
this.resetTimer();
}
removeAll() {
localStorage.clear();
}
removeTask(id: number) {
// this.tasks.splice(id, 1);
this.tasks = this.tasks.filter((item) => item.id !== id);
}
//timer actions
startTimer() {
console.log('go');
this.interval = setInterval(() => {
if (this.time === 0) {
this.time++;
} else {
this.time++;
}
this.display = this.transform(this.time);
}, 1000);
this.startFunc();
}
transform(value: number): string {
var sec_num = value;
var hours = Math.floor(sec_num / 3600);
var minutes = Math.floor((sec_num - hours * 3600) / 60);
var seconds = sec_num - hours * 3600 - minutes * 60;
return hours + ':' + minutes + ':' + seconds;
}
pauseTimer() {
clearInterval(this.interval);
}
stopTimer() {
console.log('show');
this.modalboxActive = true;
clearInterval(this.interval);
this.endFunc();
}
resetTimer() {
console.log('reset');
this.time = 0;
}
}
Result interface:
export interface Result {
id: number;
start: string | undefined;
end: string | undefined;
length: string | undefined;
name: string | undefined;
}
It looks like when you add an item in task list, the task.id is always undefined. You need to give it an unique id in order to identify it on removal.
Try to change the following code:
from:
ngOnInit() {
this.tasks = JSON.parse(localStorage.getItem('token') ?? '');
}
// task actions
addTask() {
var el: Result = {
id: this.id!, // always is undefined
name: this.activity.name,
end: this.endTime,
start: this.startTime,
length: this.display,
};
this.tasks.push(el);
localStorage.setItem('token', JSON.stringify(this.tasks));
this.activity.name = '';
this.modalboxActive = false;
this.resetTimer();
}
removeAll() {
localStorage.clear();
}
removeTask(id: number) {
// this.tasks.splice(id, 1);
this.tasks = this.tasks.filter((item) => item.id !== id);
}
to:
ngOnInit() {
this.tasks = JSON.parse(localStorage.getItem('token')) ?? [];
}
// task actions
addTask() {
var el: Result = {
id: this.tasks.length + 1,
name: this.activity.name,
end: this.endTime,
start: this.startTime,
length: this.display,
};
this.tasks.push(el);
localStorage.setItem('token', JSON.stringify(this.tasks));
this.activity.name = '';
this.modalboxActive = false;
this.resetTimer();
}
removeAll() {
this.tasks = [];
localStorage.removeItem('token');
}
removeTask(id: number) {
this.tasks = this.tasks.filter((item) => item.id !== id);
localStorage.setItem('token', JSON.stringify(this.tasks)); // also, update localStorage
}
You can check a working example here.

How to reset timer I've created in Angular on click?

I'm creating a small app which keeps track of what activity I've done in a certain timespan once I write down said activity inside of an input field, once I click "OK" it should appear in a list.
I'm stuck on how I should proceed to reset the timer once I click the "OK" button, so basically what I should add inside the "resetTimer()" function which is supposed to trigger each time I add a task in a list.
HTML:
<div class="modalbox" [class.active]="modalboxActive">
<div class="modal">
<p>What did you do?</p>
<input type="text" [(ngModel)]="activity.name" />
<button (click)="addTask()" [disabled]="activity.name === ''">OK</button>
</div>
</div>
<div class="boxSuper">
<div class="boxLeft">
<div class="containerUp">
<button id="start" (click)="startTimer()">START</button>
<button id="pause" (click)="pauseTimer()">PAUSE</button>
<button id="stop" (click)="stopTimer()">STOP</button>
</div>
<div class="containerDown">
<p>{{ display }}</p>
</div>
</div>
<div class="boxRight">
<div class="containerLeft"></div>
<div class="containerRight">
<ul class="listElement" *ngFor="let item of tasks">
<li>
Activity:
<span>{{ item.name }}</span>
Length:
<span>{{ item.length }}</span>
</li>
</ul>
</div>
</div>
</div>
TS:
import { importExpr } from '#angular/compiler/src/output/output_ast';
import { Component, OnInit } from '#angular/core';
import { timer } from 'rxjs';
import { Activity } from '../activity';
import { Result } from '../result';
#Component({
selector: 'app-timer',
templateUrl: './timer.component.html',
styleUrls: ['./timer.component.css'],
})
export class TimerComponent implements OnInit {
ngOnInit() {}
time: number = 0;
display: string | undefined;
interval: any;
modalboxActive = false;
activity: Activity = {
name: '',
};
tasks: Result[] = [];
addTask() {
var el: Result = {
name: this.activity.name,
end: '',
start: '',
length: this.display,
};
this.tasks.push(el);
this.activity.name = '';
this.modalboxActive = false;
this.resetTimer();
}
resetTimer() {
console.log('reset');
}
startTimer() {
console.log('go');
this.interval = setInterval(() => {
if (this.time === 0) {
this.time++;
} else {
this.time++;
}
this.display = this.transform(this.time);
}, 1000);
}
transform(value: number): string {
var sec_num = value;
var hours = Math.floor(sec_num / 3600);
var minutes = Math.floor((sec_num - hours * 3600) / 60);
var seconds = sec_num - hours * 3600 - minutes * 60;
return hours + ':' + minutes + ':' + seconds;
}
pauseTimer() {
clearInterval(this.interval);
}
stopTimer() {
this.modalboxActive = true;
clearInterval(this.interval);
console.log('show');
}
}
Result interface:
export interface Result {
start: string | undefined;
end: string | undefined;
length: string | undefined;
name: string | undefined;
}
If you are trying to just reset it back to 0, all you would need to do is:
resetTimer(){
this.time = 0;
}

Function triggers immediately when I start to type a value to input area

I am trying to calculate total duration from the entered values. But when I start to type, it triggers the calculateTotal function. And gives me this error:
ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'null: 273'. Current value: 'null: 294'.
Why this function triggers and changes the values randomly? Shouldn't it be triggered after clicking the button?
app.component.html
<div>
<label>Duration</label>
<input [(ngModel)]="durationModel.Duration" type="text" name="Duration" value="" #inputValue />
<button (click)="addDuration()">Submit</button>
<div [hidden]="durationList.length === 0">
<ul>
<li *ngFor="let duration of durationList">
{{calculateDuration(duration)}}
</li>
</ul>
<div>Total Duration : {{calculateTotal(21)}}</div>
</div>
</div>
app.component.ts
export class DurationModel {
Duration: number;
}
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
durationModel: DurationModel = new DurationModel();
durationList = [];
totalDuration = 0;
addDuration() {
this.durationList.push(this.durationModel.Duration);
this.durationModel = new DurationModel();
}
calculateDuration(duration) {
if (duration > 60) {
const hours = Math.floor(duration / 60);
const minutes = Math.floor(duration % 60);
return `${hours} hours ${minutes} min.`;
}
return `${duration} min.`;
}
calculateTotal = (duration) => {
console.log(duration);
return this.totalDuration += duration;
}
}
Stackblitz Demo
The reason for this is because your html invokes the method calculateTotal(...) when the page loads. Make the following changes:
.ts
export class AppComponent {
calTotal;
...
calculateTotal = (duration) => {
console.log(duration);
this.calTotal = this.totalDuration += duration;
}
}
.html
<div>Total Duration : {{ calTotal }}</div>
Thereby, on click of the button the appropriate value is stored in calTotal and it can be retrieved in the template accordingly.
EDIT:
Your approach to sum up the time entered by the user is way to complicated IMO. You can simplify it to:
.ts
export class AppComponent {
durationList = [];
totalDuration = 0;
displayTotal: string;
addDuration(time: number) {
this.durationList.push(time);
this.totalDuration = this.totalDuration + Number(time);
this.displayTotal = this.calculateDuration(this.totalDuration);
}
calculateDuration(duration) {
if (duration > 60) {
const hours = Math.floor(duration / 60);
const minutes = Math.floor(duration % 60);
return `${hours} hours ${minutes} min.`;
}
return `${duration} min.`;
}
}
.html
<div>
<label>Duration</label>
<input type="number" #inputValue />
<button (click)="addDuration(inputValue.value)">Submit</button>
<div [hidden]="durationList.length === 0">
<ul>
<li *ngFor="let duration of durationList">
{{calculateDuration(duration)}}
</li>
</ul>
<div>Total Duration : {{displayTotal}}</div>
</div>
</div>
Stackblitz Demo

ERROR Error: formControlName must be used with a parent formGroup directive

It throws me this error in console, however the form is working right whenever I clic.
Seriously, I don't see the mistake, I have another template with the same syntax and it doesn't throw me this error
<div class="container-fluid">
<div class="row">
<div class="col-md-5">
<div class="card">
<div class="header">
<h4 class="title">Comparativa mensual</h4>
<p class="category">Año actual</p>
</div>
<div class="content">
<app-pie-graph #graphmonths></app-pie-graph>
</div>
</div>
</div>
<div class="col-md-7">
<div class="card ">
<div class="header">
<div class="formGroup">
<form [formGroup]="dataForm" (ngSubmit)="submit($event)">
<h4 class="title inline">Comparativa diaria</h4>
<my-date-range-picker name="mydaterange" [options]="myOptions" formControlName="myDateRange"></my-date-range-picker>
<button type="submit" class="btn btn-primary">Consultar</button>
</form>
</div>
<p class="category">Vista de una semana</p>
</div>
<div class="content">
<div class="row">
<div class="col-sm-8">
<app-pie-graph #graphdays></app-pie-graph>
</div>
</div>
</div>
</div>
</div>
</div>
Error
ERROR Error: formControlName must be used with a parent formGroup directive. You'll want to add a formGroup
directive and pass it an existing FormGroup instance (you can create one in your class).
Example:
<div [formGroup]="myGroup">
<input formControlName="firstName">
</div>
In your class:
this.myGroup = new FormGroup({
firstName: new FormControl()
});
UPDATE: ts file------------------------------------------------------------------------------------------------------------------------------------------------
import { Component, ViewChild, OnInit, AfterViewInit, QueryList } from '#angular/core';
import { LinearGraphComponent } from '../../shared/graph/linear-graph/linear-graph.component';
import { PieGraphComponent } from '../../shared/graph/pie-graph/pie-graph.component';
import { Validators, FormGroup, FormControl } from '#angular/forms'
import { Data } from '../data';
import { ActivatedRoute } from '#angular/router';
#Component({
selector: 'app-overview',
templateUrl: './overview.component.html',
styleUrls: ['./overview.component.css']
})
export class OverviewComponent implements AfterViewInit, OnInit{
#ViewChild('graphdays') private pieGraphDays: PieGraphComponent;
#ViewChild('graphmonths') private pieGraphMonths: PieGraphComponent;
#ViewChild('generaloverview') private linearGraph: LinearGraphComponent;
//COMMON
public getDataRetriever(): Data { return this.dataRetriever; }
//COMMON
//private disableButton(){ this.blocked = true; }
//COMMON
//private activateButton(){ this.blocked = false; }
//COMMON VARIABLE
private userid = parseInt(this.route.parent.snapshot.params.id);
private dataForm = new FormGroup({
myDateRange: new FormControl(null, Validators.required)
});
constructor(
private dataRetriever: Data,
private route: ActivatedRoute
){
}
ngOnInit(){
}
private getMonthAgo(since: Date): Date{
var monthAgo = new Date(since.getTime());
monthAgo.setMonth(monthAgo.getMonth() - 3);
monthAgo.setHours(8, 0, 0, 0);
return monthAgo;
}
private displayLastMonthDaysLinear(){
var that = this;
var yesterday = this.getYesterday();
var monthAgo = this.getMonthAgo(yesterday);
this.getDataRetriever().getRangeDays(this.userid, monthAgo, yesterday, function(){
let data = that.getDataRetriever().getData();
let labels = that.getDataRetriever().getXLabels();
console.log(labels);
that.linearGraph.setChart(data, labels);
});
}
private displayLastWeekPie(){
var that = this;
var monday = this.getMondayCurrentWeek();
var yesterday = this.getYesterday();
if(monday.getDate() === new Date().getDate()) //If today is monday
monday.setDate(monday.getDate()-7); //Get monday from previous week
this.getDataRetriever().getRangeDays(this.userid, monday, yesterday, function(){
let data = that.getDataRetriever().getData();
let labels = that.getDataRetriever().getXLabels();
console.log(labels);
that.pieGraphDays.setChart(data[0].data, labels);
});
}
private displayLastMonthsPie(){
var now = new Date();
var newYear = new Date(now.getFullYear(), 0, 1, 8, 0, 0, 0);
var last = new Date(new Date().setMonth(now.getMonth()-1));
var that = this;
if(newYear.getMonth() === now.getMonth()) //If we are in January (spetial case)
newYear.setFullYear(newYear.getFullYear() - 1); //Get January from past year
this.getDataRetriever().getCountingPerMonth(this.userid, newYear, last, function(){
let data = that.getDataRetriever().getData();
let las = that.getDataRetriever().getXLabels();
console.log(data);
that.pieGraphMonths.setChart(data, las);
});
}
private getDaysToMonth(month, year): number[] { //month not included
var date = new Date(year, month, 1);
var days = [];
while (date.getMonth() < month) {
days.push(new Date(date).setHours(8,0,0,0));
date.setDate(date.getDate() + 1);
}
return days;
}
private getYesterday(): Date{
var today = new Date();
today.setDate(today.getDate() - 1);
today.setHours(8,0,0,0);
return today
}
private getMondayCurrentWeek(): Date{
var d = new Date();
var day = d.getDay(),
diff = d.getDate() - day + (day == 0 ? -6:1); // adjust when day is sunday
d.setDate(diff);
d.setHours(8,0,0,0);
return d;
}
ngAfterViewInit(){
this.displayLastMonthsPie();
this.displayLastWeekPie();
this.displayLastMonthDaysLinear();
console.log(this.linearGraph);
}
submit(){
let range = this.getPickedDayRange();
var that = this;
this.getDataRetriever().getRangeDays(this.userid, range[0], range[1], function(){
let data = that.getDataRetriever().getData();
let labels = that.getDataRetriever().getXLabels();
that.pieGraphDays.setChart(data[0].data, labels);
});
}
//COMMON CLASS
private getPickedDayRange(): Date[]{
var begDate = new Date(this.dataForm.value.myDateRange.beginJsDate);
var endDate = new Date(this.dataForm.value.myDateRange.endJsDate);
return [begDate, endDate];
}
}
I pieced together the answers from another post.
The short answer is that you have to declare the formGroup in the parent component, then pass in the formGroup to the child component.
app.component.ts
feedbackValues = [1,2,3,4,5];
constructor(private formBuilder: FormBuilder) {
this.surveyForm = this.formBuilder.group({
rowForm: this.formBuilder.group({
rating: ['']
})
});
app.component.html
<form [formGroup]="surveyForm" (ngSubmit)="onSubmit()" >
<app-survey-row [feedbackValues]=feedbackValues [parentGroup]="surveyForm"></app-survey-row>
<button type="submit">Submit</button>
</form>
survey-row.component.ts
export class SurveyRowComponent implements OnInit {
#Input() feedbackValues;
#Input() parentGroup: FormGroup;
constructor( private formBuilder: FormBuilder) {
}
ngOnInit() {
}
}
survey-row.component.html
<div [formGroup]="parentGroup">
<div formGroupName="rowForm">
<div *ngFor="let val of feedbackValues; let i = index">
<input id="{{i+1}}" type="radio" value="{{i+1}}" formControlName="rating">
<label for="{{i+1}}">{{i+1}}</label>
</div>
</div>
</div>
Notice how the [formGroup] is passed in by the parent component, and the formGroupName is not declared in survey-row, but in app.component.ts
dataForm is declared as private in your component. What if you try to declare it as public (in order to make it reachable from the view)?
I didn't realize which was the solution but finally I didn't need those formularies because the widget triggers already a function