Currently, I am using Angular and attempting to extract data from the child object's key value. Here is the JSON data provided:
"other_lessons": [
{
"id": 290,
"name": "Christmas Test #290",
"course": {
"id": 43,
"name": "Christmas Test ",
"description": "",
"teacher": {
"id": 4,
"name": "Sandy's Teacher",
"email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6f0e0d0c2f1c410c0002">[email protected]</a>",
"role": "TEACHER",
"token": "abcd",
"about": "Blah blah blah ",
"phone": "2222222222",
"image_url": "xyz",
"payment_information": {}
}
]
The objective is to access the details of course.name and course.id from the data. However, an error keeps surfacing in my developer console:
ERROR TypeError: Cannot read property 'name' of undefined
at Object.eval [as updateRenderer] (ng:///AppModule/AppTileComponent.ngfactory.js:30)
at Object.debugUpdateRenderer [as updateRenderer] (vendor.bundle.js:105951)
at checkAndUpdateView (vendor.bundle.js:105102)
at callViewAction (vendor.bundle.js:105445)
at execComponentViewsAction (vendor.bundle.js:105377)
at checkAndUpdateView (vendor.bundle.js:105103)
at callViewAction (vendor.bundle.js:105445)
at execComponentViewsAction (vendor.bundle.js:105377)
at checkAndUpdateView (vendor.bundle.js:105103)
at callViewAction (vendor.bundle.js:105445)
Oddly enough, fetching id and name from the JSON data works just fine. The code snippet I've implemented looks like this—I'm passing the details to the selector tag as follows:
<widget-app-tile>
homepage.component.html
<widget-app-block title="You may be interested in">
<div class="row">
<div class="col-md-6" *ngFor="let lesson of lessons">
<widget-app-tile [lesson]="lesson"></widget-app-tile>
</div>
</div>
</widget-app-block>
app-tile.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { Lesson } from '../../models/models';
@Component({
selector: 'widget-app-tile',
templateUrl: './app-tile.component.html',
styleUrls: ['./app-tile.component.css']
})
export class AppTileComponent implements OnInit {
@Input() lesson : Lesson = <Lesson> {}
constructor() { }
ngOnInit() {
}
}
app-tile.component.html
<div class="content-details">
<div class="details">
<h5>{{lesson.course.name}}</h5>
<img class="icon" src="/assets/images/logo-transparent.png" alt="No Internet" align="right"/>
</div>
When attempting to fetch {{lesson.course.name}}, it triggers an error. Yet, calling {{lesson.name}} or {{lesson.id}} functions smoothly and displays the data.
I've utilized the Cerialize Library. Below is my model class structure:
model.ts
import { deserialize, deserializeAs, Deserialize } from 'cerialize';
/* UTILITY METHODS */
export function cast(data, modelClass) {
return Deserialize(data, modelClass)
}
export function castCollection (collection, modelClass) {
return collection.map( item => cast(item, modelClass))
}
/* MODELS */
export class Course {
@deserialize id: number
@deserialize name: string
}
export class Lesson {
@deserialize id: number
@deserialize name: string
@deserializeAs(Course) course : Course
}
This model is employed for extracting data; interfaces are not used.
EDITS
Testing on the home page directly yielded positive results, whereas implementing app-tile.component.ts did not provide desired outcomes. The code snippet integrated is as follows:
homepage.component.html
<div class="" *ngFor="let lesson of lessons" >
#{{lesson.id}} - {{lesson.name}}; Course: {{lesson.course.name}}
</div>
<widget-app-block title="You may be interested in">
<div class="row">
<div class="col-md-6" *ngFor="let lesson of lessons">
<widget-app-tile [lesson]="lesson"></widget-app-tile>
</div>
</div>
</widget-app-block>
The above implementation works without errors. One additional detail is presented below:
homepage.component.ts
export class MyClassesComponent implements OnInit {
lessons : Lesson[] = []
constructor(private http : HttpClient) { }
ngOnInit() {
}
ngAfterViewInit(){
this.http.get("/ui/student/home").subscribe( data => {
this.lessons = castCollection(data['other_lessons'], Lesson)
})
}