Cannot read property 'setRowData' of undefined / Issue with HTML template? - ag-grid-angular

Am maintaining an AG-GRID re-usable template with all necessary methods (clear filer/ CSV download/ Autofit..etc options) --- Base Template.
I have another AG-Grid template , which uses "Base Template" (thru dependency injection) and populate grid with a row of data based on searchString value. (Sample file below)
import { Component, OnInit, } from '#angular/core';
import { GridOptions, GridApi, } from "ag-grid-community";
import { ReportersgridComponent } from '../../commonpages/reportersgrid/reportersgrid.component'
#Component({
selector: 'app-reporters',
templateUrl: './reporters.component.html',
styleUrls: ['./reporters.component.scss']
})
export class ReportersComponent implements OnInit {
private reporterGrid: GridOptions;
constructor(public reportersGrid: ReportersgridComponent, ) {
this.reporterGrid = <GridOptions>{};
this.reporterGrid.enableSorting = true;
this.reporterGrid.enableFilter = true;
this.reporterGrid.enableColResize = true;
this.reporterGrid.columnDefs = this.reportersGrid.createColumnDefs();
this.reporterGrid.rowData = this.reportersGrid.createRowData();
}
ngOnInit() {
}
//Search Function
performSearch() {
let searchString = "";
this.populateFiteredReporter(searchString);
// this.reporterGrid.api.setRowData(reporterGrid.rowData)
}
populateFiteredReporter(searchString) {
this.reporterGrid.rowData = [
{ fullName: 'fName,mName,lName2', address: "address2", country: "country2", postcode: "postcode2", phone: "phone", email: "email", qualification: "MBBS", institution: "institution", department: "department" },
];
var str = JSON.stringify(this.reporterGrid.rowData);
console.log('data:' + str);
this.reporterGrid.api.setRowData(this.reporterGrid.rowData);
//this.reportersGrid.populateFiteredReporter(searchString);
}
}
In HTML of the above file, I am using "Base Template" s SELECTOR AS HTML TAG. (
<app-reportersgrid></app-reportersgrid>
) to display the grid portion.
Above gives error -> Cannot read property 'setRowData' of undefined.
Please note that if I replace Base Template's selector with base template's FULL HTML portion for ag-grid (which has (gridReady)="onGridReady($event)"), page works fine.
Can I get help to stick back to my original idea of keeping base template intact? (Note that all base template functions like export to csv, autofit etc works fine - those are coded in the base template along with OnGridReadty().)
Thanks in Advance..
ASJ.
22/10/2019 /* Template of reporters.component.html*/
<div>
<div class="col-md-12">
<div class="card">
<div class="card-header text-uppercase font-weight-bold">
Search
</div>
<div class="card-body">
<div>
<div class="row">
<div class="col-sm-4">
<div class="form-group">
<span>Name <i>(First/Middle/Last)</i></span>
<input type="text" class="form-control" [(ngModel)]="reporterName">
</div>
</div>
</div>
</div>
</div>
<div class="card-footer">
<div class="row">
<div class="col-6 col-sm-4 col-md-2 col-xl mb-3 mb-xl-0">
<button type="button" class="btn btn-normal btn-primary" (click)="performSearch()" style="width: 100px; ">Search</button>
<button type="button" class="btn btn-normal btn-light" style="width: 100px;">Reset</button>
</div>
</div>
</div>
</div>
</div>
<app-reportersgrid></app-reportersgrid>
</div>
Base template - HTML of the AG-GRID
<div class="centered-content">
<div>
<ag-grid-angular #agGrid style="width: 100%; height: 358px;" class="ag-theme-balham"
[gridOptions]="reporterGrid" [enableSorting]="true" enableFilter [sideBar]="sideBar"
enableColResize [pagination]="true" [paginationPageSize]=10
rowDragManaged=true
(gridReady)="onGridReady($event)">
<ag-grid-column headerName="Name" field="fullName"></ag-grid-column>
<ag-grid-column headerName="Address" field="address" [width]="150"></ag-grid-column>
<ag-grid-column headerName="Country" field="country"></ag-grid-column>
<ag-grid-column headerName="Postcode" field="postCode"></ag-grid-column>
<ag-grid-column headerName="Phone" field="phone"></ag-grid-column>
<ag-grid-column headerName="Email" field="email"></ag-grid-column>
<ag-grid-column headerName="Qualification" field="qualification"></ag-grid-column>
<ag-grid-column headerName="Institution" field="institution"></ag-grid-column>
<ag-grid-column headerName="Department" field="department" [cellRenderer]="countryCellRenderer">
</ag-grid-column>
</ag-grid-angular>
</div>
</div>
/ReportersGridcomponent.ts file/
import { Component, OnInit } from '#angular/core';
//import { HttpClient, HttpErrorResponse } from '#angular/common/http';
import {GridOptions, GridApi, Grid} from "ag-grid-community";
#Component({
selector: 'app-reportersgrid',
templateUrl: './reportersgrid.component.html',
styleUrls: ['./reportersgrid.component.scss']
})
export class ReportersgridComponent implements OnInit {
private reporterGrid: GridOptions;
private gridApi:GridApi;
private gridColumnApi;
filterName: string | null;
constructor( ) {
this.reporterGrid = <GridOptions>{};
this.reporterGrid.enableSorting = true;
this.reporterGrid.enableFilter = true;
this.reporterGrid.enableColResize = true;
this.reporterGrid.columnDefs = this.createColumnDefs();
this.reporterGrid.rowData = this.createRowData();
}
ngOnInit() {
}
createColumnDefs() {
this.reporterGrid.columnDefs = [
{
headerName: "Name",
field: "fullName",
width:100,
},
{
headerName: "Address",
field: "address",
},
{
headerName: "Country",
field: "country",
},
{
headerName: "Postcode",
field: "postCode",
},
{
headerName: "Phone",
field: "phone",
},
{
headerName: "Email",
field: "email",
},
{
headerName: "Qualification",
field: "qualification",
},
{
headerName: "Institution",
field: "institution",
},
{
headerName: "Department",
field: "department",
}
];
return this.reporterGrid.columnDefs
}
createRowData(){
this.reporterGrid.rowData = [
// {fullName: 'fName,mName,lName',address:"address1",country: "country",postcode: "postcode",phone: "phone",email:"email",qualification:"MBBS",institution:"institution",department:"department"},
];
return this.reporterGrid.rowData;
}
onGridReady(params) {
this.gridApi = params.api;
this.gridColumnApi = params.columnApi;
this.autoSizeAll()
}
autoSizeAll() {
var allColumnIds = [];
this.gridColumnApi.getAllColumns().forEach(function(column) {
allColumnIds.push(column.colId);
});
this.gridColumnApi.autoSizeColumns(allColumnIds);
}
onCSVExport() {
this.reporterGrid.api.exportDataAsCsv();
}
onSearchTextChange(newData: string) {
this.reporterGrid.api.setQuickFilter(newData);
}
clearFilters() {
if (this.gridApi.isQuickFilterPresent())
{
this.gridApi.setQuickFilter('');
this.filterName="";
}
}
// populateFiteredReporter(searchString){
// this.reporterGrid.rowData = [
// {fullName: 'fName,mName,lName2',address:"address2",country: "country2",postcode: "postcode2",phone: "phone",email:"email",qualification:"MBBS",institution:"institution",department:"department"},
// ];
// var str= JSON.stringify(this.reporterGrid.rowData);
// console.log('data:'+str);
// this.reporterGrid.api.setRowData(this.reporterGrid.rowData);
// //return this.reporterGrid.rowData;
// }
}

The first thing you need to do is set your grid component to accept grid options from its parent:
#Input() public reporterGrid: GridOptions;
Here is an abbreviated version of what your grid component should look like. I suggest using properties or fields, instead of using methods to create your rows and columns. Just a suggestion.
export class ReportersgridComponent implements OnInit {
#Input() public reporterGrid: GridOptions;
private columnDefs = [
// put your column def json here
];
private rowDefs = [
// Put your row def json here
];
constructor() {
}
ngOnInit() {
this.reporterGrid.columnDefs = this.columnDefs;
this.reporterGrid.rowData = this.rowDefs;
}
// rest of your file
}
And your reporters component ts file should look like this:
export class ReportersComponent implements OnInit {
private reporterGridOptions: GridOptions;
constructor() {
this.reporterGridOptions = {
enableSorting: true,
enableFilter: true,
enableColResize: true,
};
}
ngOnInit() {
}
// other code...
}
In your reporter component html, you need to pass in this value through the element like this:
<app-reportersgrid [reporterGrid]="reporterGridOptions"></app-reportersgrid>
Another suggestion, I would take some time to properly name things, adjust casing, and format your code so it is easier to read. I hope this helps get you heading in the right direction. Basically you want to pass your options object to the grid component, so it can have access to it.
Also, you do not want to inject a component through a constructor. It will not be the same instance as the component in the template. Components are initialized and destroyed as they are rendered and removed from the view, and do not exist as singletons like services to.

Related

Pass data from parent component to child component using input, how to implement?

There is a parent component with all the logic of the chart, you need to transfer data to the child component using #Input (), that is, so that I can display the chart in any of the components using #Input.
The parent component is logs.component and the child component is echarts.component. It is necessary to pass the data to LoadEcharts(), it contains all the logic of the Chart, that is, that I could call it on any html component
logs.components.ts
export class LogsComponent implements OnInit {
sideNavStatus: boolean = false;
subscription!: Subscription;
logs!: Logs[];
constructor(private dataService: DataService) {
}
columnDefs = [
{ headerName: 'Username', field: 'username', flex: 1},
{ headerName: 'Event', field: 'event', flex: 1 },
{ headerName: 'Date', field: 'date', flex: 1 }
];
ngOnInit() {
this.LoadLogs();
this.LoadEcharts();
}
LoadLogs(): void {
this.dataService.getLogs().subscribe(logs => this.logs = logs);
}
LoadEcharts(): void {
const chartDom: HTMLElement = document.getElementById('main') as HTMLElement;
const myChart = echarts.init(chartDom);
this.subscription = this.dataService.getLogs().subscribe(data => {
myChart.setOption(this.initBasicEchart(data))
})
}
private initBasicEchart(data: Logs[]) {
const result: any = {};
data.forEach(el => {
const date = el.date.toString().substring(0, 10);
if (!result[el.event]) {
result[el.event] = {};
if (!result[el.event][date]) {
result[el.event][date] = 1;
}
} else {
if (!result[el.event][date]) {
result[el.event][date] = 1;
} else {
result[el.event][date] += 1;
}
}
});
const login = {
x: Object.keys(result.Login),
y: Object.values(result.Login)};
const reg = {
c: Object.keys(result.Registration),
z: Object.values(result.Registration)};
return {
title: {
text: 'Graphic login and registration.'
},
tooltip: {},
xAxis: {
type: 'category',
data: (reg.c, login.x)
},
yAxis: {
},
series: [
{
name: 'Login',
type: 'bar',
data: login.y,
},
{
name: 'Registration',
type: 'bar',
data: reg.z,
}
]
};
}
}
logs.component.html
<div class="container-fluid g-0">
<app-header (sideNavToggled)="sideNavStatus = $event;"></app-header>
<main>
<app-sidebar [sideNavStatus]="sideNavStatus"
[ngClass]="{'app-side-nav-open': sideNavStatus}"></app-sidebar>
<div class="display-area p-3" [ngClass]="{'display-area-shrink': sideNavStatus}">
<p class="fs-1 fw-bold fst-italic text-center">Login and registration statistics.
</p>
<app-aggreed
*ngIf="logs"
[logs]="logs"
[columnDefs]="columnDefs"
></app-aggreed>
</div>
</main>
</div>
<app-echarts
></app-echarts>
<app-footer></app-footer>
echarts.component.html
<div class="container-fluid g-0">
<app-header (sideNavToggled)="sideNavStatus = $event;"></app-header>
<main>
<app-sidebar [sideNavStatus]="sideNavStatus"
[ngClass]="{'app-side-nav-open': sideNavStatus}"></app-sidebar>
<div class="display-area p-3" [ngClass]="{'display-area-shrink': sideNavStatus}">
<div
id="main"
style="width: 500px; height: 300px"
>
</div >
</div>
</main>
</div>
<app-footer></app-footer>
export class EchartsComponent implements OnInit {
sideNavStatus: boolean = false;
subscription!: Subscription;
constructor(private dataService: DataService) {
}
ngOnInit(): void {
}
}
I tried to pass methods to the child component through the input but nothing comes out
From your code sample, I'm assuming you're trying to access the EchartsComponent ViewChild in the logs component and pass data to it.
Here's an example of how you can do that, minus some pieces from your sample code for brevity...
class LogsComponent {
#ViewChild(EchartsComponent)
echartsComponent: EchartsComponent;
LoadEcharts(): void {
const chartDom: HTMLElement = document.getElementById('main') as HTMLElement; // <-- not sure what this is
const myChart = echarts.init(chartDom); // <-- not sure what this is
this.subscription = this.dataService.getLogs().subscribe(data => {
this.echartsComponent.logs = data;
// `logs` doesn't exist in the current code for EchartsComponent.
// You'll need to add it.
});
}
}
What I don't see in your EchartsComponent is a logs property to set. If you're using a ViewChild in the parent component, you don't have to use #Input on the ViewChild instance, you have programmatic access to the component and can set properties or call methods.
If you want to use #Input(), you can do that too:
class EchartsComponent {
#Input()
logs: Logs[];
}
// logs.component.ts
class LogsComponent {
LoadEcharts(): void {
this.subscription = this.dataService.getLogs().subscribe(data => {
this.logs = data;
})
}
}
// logs.component.html
<app-echarts [logs]="logs"></app-echarts>
In this scenario, when the observable for getLogs() emits, the property logs is set to the new value. That value, being a new reference is passed to the child component via its input.
Hope that helps you out.

TypeError: Cannot read property 'join' of undefined

i am trying to integrate select2 in my html template but i keep getting this error. i want to be able to select multiple options at a time
i am not sure how to go about it.
help would be appreciated.
admin.ts
import { Component, OnInit } from '#angular/core';
import { Select2OptionData } from 'ng2-select2';
#Component({
selector: 'app-admin',
templateUrl: './admin.component.html',
styleUrls: ['./admin.component.scss']
})
export class AdminComponent implements OnInit {
public candidateData: Array<Select2OptionData>;
public options: Select2Options;
public value: string[];
public current: string;
constructor() { }
ngOnInit() { this.candidateData = [
{ id: '1', text: 'Mohammadu Buhari' },
{ id: '2', text: 'Atiku Abubakr' },
{ id: '3', text: 'John Doe'},
{ id: '4', text: 'Someone Else'}];
this.options = {
multiple: true
};
this.current = this.value.join(' | ');
}
changed(data: {value: string[]}) {
this.current = data.value.join(' | ');
}
}
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2">
<label>Candidates</label>
<select2
[data] = "exampleData"
[options] = "options"
[width] = "500"
[value] = "value"
(valueChanged) = "changed($event)"
></select2>
</div>
</div>
</div>
You must initialize your model because it's undefined when you try to access it in ngOnInit.
public value: string[] = [];

How to post an object to an array in a json using Angular 6

So I'm testing Angular 6 functionality out for fun to learn it and running a json-server to load a db.json to a localhost server to acquire via service calls which you can see here
{
"customers": {
"testingTitle": "Testing Title",
"trainData":[
{
"id": 1,
"name": "Test Name 1",
"email": "customer001#email.com",
"tel": "0526252525"
},
{
"id": 2,
"name": "Test Name 2",
"email": "customer002#email.com",
"tel": "0527252525"
},
{
"id": 3,
"name": "Customer003",
"email": "customer003#email.com",
"tel": "0528252525"
},
{
"id": 4,
"name": "123",
"email": "123",
"tel": "123"
}
]
}
I have a test.service.ts as followed which picks up the service:
import { Injectable } from '#angular/core';
import {HttpClient, HttpResponse, HttpErrorResponse, HttpHeaders, HttpParams} from '#angular/common/http';
import { Observable } from 'rxjs/Rx';
import { catchError, map } from 'rxjs/operators';
import 'rxjs/add/observable/throw';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
class Test {
testingTitle: string;
trainData:[
{
id : number;
name: string;
email: string;
tel: string;
}
];
}
#Injectable({providedIn: 'root'})
export class TestService {
constructor(private http: HttpClient) {}
public getAllTests(): Observable<Test[]>{
const params = new HttpParams().set('_page', "*").set('_limit', "*");
return this.http.get<Test[]>("http://localhost:3000/customers", {params}).pipe(map(res => res));
}
public postTests(object) {
return this.http.post("http://localhost:3000/customers", object).subscribe(data => {console.log("POST Request is successful ", data);},error => {console.log("Error", error);});
}
}
I have my test.ts which controls my calls etc.
import { Component, OnInit } from '#angular/core';
import { HttpClient } from "#angular/common/http";
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
import {FormBuilder, FormControl, FormGroup} from "#angular/forms";
import {TestService} from "./test.service";
class Customer {
id : number;
name: string;
email: string;
tel: string;
}
#Component({
selector: 'sample-template',
templateUrl: './test.component.html'})
export class TestComponent implements OnInit {
testForm: FormGroup;
testForm2: FormGroup;
public test: any;
name: string = '';
email: string = '';
tel: string = '';
public id: any;
constructor(private httpClient:HttpClient, private fb: FormBuilder, private TestService: TestService) {}
loadTasks(): void{
this.TestService.getAllTests().subscribe(response => {this.test = response;
console.log(this.test)})
}
ngOnInit() {
let trainData = [];
this.loadTasks();
this.testForm = this.fb.group({
testCd: 'Select'
});
this.testForm2 = this.fb.group({
id: this.id,
name: this.name,
email: this.email,
tel: this.tel
})
}
changeDropdown(formControl: FormControl, option: string): void {
formControl.patchValue(option);
console.log(option);
}
submitForm(){
let last:any = this.test[this.test.length-1];
this.id = last.id+1;
console.log(this.id);
this.testForm2.value.id = this.id;
console.log(this.testForm2.value);
this.TestService.postTests(this.testForm2.value);
}
}
And my html page which includes the following:
<label class="modelo-label">{{test?.testingTitle}}</label>
<form [formGroup]="testForm">
<div class="dropdown modelo-dropdown">
<label for="testCd" class="modelo-label">Testing</label>
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown" role="button" id="testCd" aria-haspopup="true" aria-expanded="true">{{testForm.get('testCd').value}}</button>
<div class="dropdown-menu modelo-dropdown-menu" aria-labelledby="testCd">
<a class="dropdown-item" *ngFor="let tests of test?.trainData; let i = index" id="tests.name" (click)="changeDropdown(testForm.get('testCd'), tests.name)">{{tests.name}}</a>
</div>
</div>
<form [formGroup]="testForm2" (ngSubmit)="submitForm()">
<div class="row">
<div class="col-12 col-sm-4 group">
<input type="text" id="name" formControlName="name" class="modelo-text-input"
[ngClass]="{'ng-not-empty' : testForm2.get('name').value.length !== 0}">
<label for="name">Name</label>
</div>
</div>
<div class="row">
<div class="col-12 col-sm-4 group">
<input type="text" id="email" formControlName="email" class="modelo-text-input"
[ngClass]="{'ng-not-empty' : testForm2.get('email').value.length !== 0}">
<label for="email">Email</label>
</div>
</div>
<div class="row">
<div class="col-12 col-sm-4 group">
<input type="text" id="tel" formControlName="tel" class="modelo-text-input"
[ngClass]="{'ng-not-empty' : testForm2.get('tel').value.length !== 0}">
<label for="tel">Telephone #</label>
</div>
</div>
<div class="col-1 group generateButton">
<button class="btn btn-primary" type="submit">Submit Info</button>
</div>
</form>
My Question is, I'm have everything set up for a post and what I'm trying to do is post testForm2.value to the json but under "trainData":[{}] that's within the JSON. I'm able to do so if I just drop all other objects inside the json and have just the array after "customers":... What exactly am I missing? I'm actually confusing myself right now and I may be overthinking this by alot. The post I have currently in this code works if I have just the array after "customers":.... so instead of me passing object which is the testForm2.value what else do I need to do? I hope this makes sense.
You have some strange things in your code. First :
In you API
return this.http.get<Test[]>("http://localhost:3000/customers", {params}).pipe(map(res => res));
I think what you want to do here is : (the pipe is useless you dont use it and it's not an array)
return this.http.get<Test>("http://localhost:3000/customers",{params});
In your component you want to push the update trainData list
submitForm(){
const lastTrainData = this.test.trainData[this.test.trainData.length-1];
const newTrainData = this.testForm2.value;
newTrainData.id = lastTrainData.id + 1;
this.test.trainData.push(newTrainData);
this.TestService.postTests(this.test);
}

How to bind rowdata of ag-grid inside gridoption using a httpservice

I am using ag-grid license edition and want to bring record set to the grid using a service. I am using Ag-Grid gridoption property and initializing rowdata
in the constructor of the component.ts class. But the data is not rendering. No error either. Please have a look of my component.ts class.
Please note: the web api is returning the json data correctly and the service in Angular is tested sucessfully without Ag-Grid
import {Component, OnInit} from "#angular/core";
import {GridOptions} from "ag-grid";
import {RedComponentComponent} from "../red-component/red-component.component";
import { person } from "../Shared/models/person.model";
import {personservice} from '../service/person.service';
#Component({
selector: 'app-my-grid-application',
templateUrl: './my-grid-application.component.html'
})
export class MyGridApplicationComponent implements OnInit{
private gridOptions: GridOptions;
private persons: person[];
constructor(private personservice: personservice) {
this.gridOptions = <GridOptions>{};
this.gridOptions.columnDefs = [
{
headerName: "ID",
field: "PersonId",
width: 100
},
{
headerName: "Name",
field: "PersonNm",
cellRendererFramework: RedComponentComponent,
width: 100
},
{
headerName: "Email",
field: "PersonEmail",
cellRendererFramework: RedComponentComponent,
width: 100
}
];
this.gridOptions.rowData = this.persons
}
ngOnInit() {
this.personservice.findAll().subscribe(
persons => {
this.persons = persons
},
error => {
console.log(error);
}
)
}
}
Instead of providing columnDefs and rowData with gridOptions, try providing them directly like this.
<ag-grid-angular
[gridOptions]="gridOptions"
[rowData]="rowData"
[columnDefs]="columnDefs"
>
</ag-grid-angular>
Also, declare columnDefs and rowData as component variables, and then assign them after getting the response.
rows: any[] = [];
columnDefs: ColDef[];
constructor(private personservice: personservice) {
this.gridOptions = <GridOptions>{};
this.columnDefs = [
// your column definition goes here
];
}
ngOnInit() {
this.personservice.findAll().subscribe(
persons => {
this.rows = persons
},
error => console.log(error)
)
}
Let me know if you face any issue after this.

How to loop through nested JSON data

I am trying to loop through json data bellow, to so each element. I need to get down to the details data and then in side that loop through the f1,f2 into a div. I have tried using the index but that didn't work. Also I don't know how many f1,f2 there will be as it is returned from an api
JSON data
{
"data":[
{
"title": "test",
"image": "assets/imgs/test.png",
"date": "22/07/2018 - 19.00",
"location": "test",
"details": [
{
"f1":[
{
"FunctioName": "test",
"Time": "10:00:00"
}
],
"f2":[
{
"FunctioName": "test",
"Time": "11:00:00"
}
]
}
]
}
]
}
HTML
<div *ngFor="let item of card">
<div class="swiper-zoom-container">
<div class="out-card-box">
<h2>Date</h2>
<p>{{item.date}}</p>
<h2>Program</h2>
<div *ngFor="let details of item.details; let i = index">
</div>
</div>
</div>
</div>
TS
import { Component } from '#angular/core';
import { App } from 'ionic-angular';
import { DataService } from "../../services/data";
import { LoginPage } from "../login/login";
import { AngularFireAuth } from "angularfire2/auth";
import { Storage } from "#ionic/storage";
#Component({
selector: 'page-card',
templateUrl: 'card.html',
})
export class CardPage {
card:any;
constructor(private dataservice: DataService, private afAuth:AngularFireAuth, private app:App, private storage:Storage) {
this.dataservice.cardData().subscribe(
data => {
var jsonObj = JSON.parse(data["_body"]);
this.card = jsonObj.data;
console.log(jsonObj.data)
}
);
}
You can create an object which will hold the returned data from the api and you can just navigate the object values.
Example:
export class Class1 {
data: Class2[];
}
export class Class2 {
title: string;
image: string;
date: string;
location: string;
details: Class3[];
}
export class Class3 {
f1: Class4[];
f2: Class4[];
}
export class Class4 {
FunctioName: string;
Time: string
}
#Component({
selector: 'page-card',
templateUrl: 'card.html',
})
export class CardPage {
card:Class1;
constructor(private dataservice: DataService, private afAuth:AngularFireAuth, private app:App, private storage:Storage) {
this.dataservice.cardData().subscribe(
data => {
this.card = data;
}
);
}
then in your component template
<div *ngFor="let item of card.data">
<div class="swiper-zoom-container">
<div class="out-card-box">
<h2>Date</h2>
<p>{{item.date}}</p>
<h2>Program</h2>
<div *ngFor="let details of item.details; let i = index">
<!-- Print the remaining items here -->
</div>
</div>
</div>
</div>