angular no access to object.id - html

hey i just started with angular and my problem is, why i have no access to my .id,.name and .color, the first code is my oberteile-names.ts where i have defined my const array
import { Oberteil } from './oberteile/oberteil';
export const OBERTEILE: Oberteil[] = [
{id:11, name: 'flannelshirt', color: 'vintagebrown'},
{id:12, name: 'flannelshirt', color: 'vintagegreen'},
{id:13, name: 'flannelshirt', color: 'vintagewhite'},
{id:14, name: 'cordhemd', color: 'black'},
{id:15, name: 'cordhemd', color: 'vintagebrown'},
{id:16, name: 'cordhemd', color: 'vintagegreen'},
{id:17, name: 'basicshirt', color: 'black'},
{id:18, name: 'basicshirt', color: 'white'}
];
here is my simple oberteil.ts
export interface Oberteil {
id: number;
name: string;
color : string;
}
so now i go into my oberteile.component.ts and initialize oberteil with the const OBERTEILE
import { Component, OnInit } from '#angular/core';
import { OBERTEILE } from '../oberteil-names';
#Component({
selector: 'app-oberteile',
templateUrl: './oberteile.component.html',
styleUrls: ['./oberteile.component.css']
})
export class OberteileComponent implements OnInit {
oberteil = OBERTEILE;
constructor() { }
ngOnInit(): void {
}
}
now i want to display them on my oberteile.component.html but i have no access to id
<h2>{{oberteil.id}}</h2>
i think it is very easy to be solved but i can not find any answers for it, even when i just want to display {{oberteile}}, it just display [object,Object]

oberteil is an array of multiple elements. You need to select a specific element of the array, or iterate over the array with *ngFor:
<h2>{{oberteil[0].id}}</h2><!-- display the ID of the first element -->
<h2 *ngFor="let element of oberteil">{{element.id}}</h2><!-- display IDs of all elements -->

oberteil is an array. You can't access it like that. You need to specify the index of the array.
Or if you are trying to show the id from each element of oberteil array, you can use *ngFor directive.
<h1 *ngFor="let o of oberteil">{{o.id}}</h1>
See *ngFor

oberteil is array, no Object, so you cannot bind the value with <h2>{{oberteil.id}}</h2>
It should be like that in *ngFor iteration to get all values
<div *ngFor="let item of oberteil">
<p>{{item.id}}</p>
<p>{{item.name}}</p>
<p>{{item.color}}</p>
</div>
It is just example to use your oberteil variable in html to bind the data.

Related

Why ngfor directive is not working, though I have created proper object in Typescript class

I have created proper Ingredient object in Typesript, also proper "model" for the object. Though ngfor directive is not working. I am getting this error "NG0303: Can't bind to 'ngforOf' since it isn't a known property of 'a'" on inspecting in browser.
My model code
export class Ingredient {
constructor(public name: string, public amount: number){}
}
My TypeScript code
import { Component, OnInit } from '#angular/core';
import { Ingredient } from '../shared/ingredient.model';
#Component({
selector: 'app-shopping-list',
templateUrl: './shopping-list.component.html',
styleUrls: ['./shopping-list.component.css']
})
export class ShoppingListComponent implements OnInit {
ingredients: Ingredient[] = [
new Ingredient ("Apple", 5),
new Ingredient ("Tomato", 5)
];
constructor() { }
ngOnInit(): void {
}
}
My HTML code
<div class="row">
<div class="col-xs-10">
<app-shopping-edit></app-shopping-edit>
<hr>
<ul class = "list-group">
<a class = "list-group-item"
style = "cursor : pointer"
*ngfor = "let ingredient of ingredients">
{{ ingredient.name }}({{ ingredient.amount}})
</a>
</ul>
</div>
</div>
Page is loading properly, but ingredients are not loading. On inspecting in browser this error "NG0303: Can't bind to 'ngforOf' since it isn't a known property of 'a'" is coming.
Can someone please help.
Try moving the *ngFor inside the ul tag.
Edit: You have a typo.. It's *ngFor="", not *ngfor="".
If you are inside AppModule check if you have BroswerModule in the imports array there.
If you are in some different module then check if CommonModule is a part of that module's array. CommonModule provides us with core Angular features like *ngIf or *ngFor in your specific case.
Also watch out, you typed *ngfor instead *ngFor.

Nested Components: How to pass data item from a component using *ngFor to another component which uses recursion?

I created my own custom element with the DropdownMenuTreeComponent to use inside another component as < dropdown-menu-tree > and I pass it a nodeTree which is an array of nodes:
nodeTree: Array<Node> = [];
Node = { Name:String, Children:Array<Node> }
Then, inside the DropdownMenuTreeComponent I try to pass a single node from my Array nodeTree to my NodesRendererComponent as I call it from inside the template of DropDownMenuTreeComponent with < nodes-rendered > and I pass it a "node" from nodeTree.
The issue here is that when I run the code while DropdownMenuTreeComponent is able to get the nodeTree from the 1st component it is nested( DropdownMenuTreeComponent being the 2nd component) it is not able to pass it to NodesRendererComponent as node.Name appears as undefined but I can see the "This works!" text in the screen.
I need this 3 levels of components because I need my NodesRendererComponent to be recursive and other aspects not relevant right now. So, what am I doing wrong or how can I make the NodesRendererComponent get each node from nodeTree while also being able to recurse?
DropdownMenuTreeComponent (Nested component #2):
#Component({
template: `<div>
<ul class="dropdown-menu-tree">
<li *ngFor="let node of nodeTree">
<nodes-renderer [node]="node"></nodes-renderer>
</li>
</ul>
</div>`,
styleUrls: ['./dropdown-menu-tree.component.css']
})
export class DropdownMenuTreeComponent implements OnInit{
#Input() nodeTree: any[];
constructor() {}
ngOnInit(){}
}
NodesRendererComponent (Nested Component #3):
#Component({
selector: 'nodes-renderer',
template: ` {{node.Name }}
<p> This Works! </p>
<li *ngFor="let node of node.Children">
<nodes-renderer [node]="node"></nodes-renderer>`
,
})
export class NodesRendererComponent implements OnInit{
#Input() node: any;
constructor() {
}
ngOnInit(){
}
}

How to retrieve and display an embedded Firestore object with Angular?

I would like to display a Firestore model containing a profile name and a list of describing hashtags with Angular 6.
Being new to Firestore I learned, that I should model it like this:
enter image description here
members {
id: xyz
{
name: Jones;
hashtag: {
global: true,
digital: true
}
...
}
Now, I try to understand how to display the keys of every hashtag property in my component list. My current code always displays [object Object] as result. My component code is:
import { Component } from '#angular/core';
import { AngularFirestore } from 'angularfire2/firestore';
import { Observable } from 'rxjs';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
items$: Observable<any[]>;
constructor(db: AngularFirestore) {
this.items$ = db.collection('Members').valueChanges();
console.log(this.items$);
}
}
My template code is:
<p>names and their interests</p>
<div *ngFor="let item of items$ | async">
<h4>{{item.name}}</h4>
<ul>
<li>{{item.hashtag}}</li>
</ul>
</div>
How can I fix this?
Think you're looking for (Angular 6.1):
<li *ngFor="let hashtag of item.hashtag| keyvalue">
{{hashtag.key}}:{{hashtag.value}}
</li>
What this will do is get the key and the value of the item.hastag and let them be used in hastag.

Angular 2: Remove the wrapping DOM element in a component

I am writing an HTML table component using data that is nested, such that the output might look like this:
<table>
<tr><td>Parent</td></tr>
<tr><td>Child 1</td></tr>
<tr><td>Child 2</td></tr>
<tr><td>Grandchild 1</td></tr>
</table>
I would like to create this using a recursive component as follows:
<table>
<data-row *ngFor="let row of rows" [row]="row"></data-row>
</table>
data-row:
<tr><td>{{row.name}}</td></tr>
<data-row *ngFor="let child of row.children" [row]="child"></data-row>
However, this adds a wrapping element around the table row which breaks the table and is invalid HTML:
<table>
<data-row>
<tr>...</tr>
<data-row><tr>...</tr></data-row>
</data-row>
</table>
Is it possible to remove this data-row wrapping element?
One Solution:
One solution is to use <tbody data-row...></tbody> which is what I'm currently doing, however this leads to nested tbody elements which is against the W3C spec
Other thoughts:
I've tried using ng-container but it doesn't seem to be possible to do <ng-container data-row...></ng-container> so that was a non starter.
I have also considered ditching the use of tables, however using an HTML table is the ONLY way to allow simple copying of the data into a spreadsheet which is a requirement.
The final option I've considered would be to flatten the data before generating the table, however, since the tree can be expanded and collapsed at will, this leads to either excessive rerendering or a very complicated model.
EDIT: Here's a Plunk with my current solution (which is against spec): http://plnkr.co/edit/LTex8GW4jfcH38D7RB4V?p=preview
Just use a class or attribute as the selector for the component and apply it to a table row element.
#Component({
selector: [data-row],
with
<tr data-row> </tr>
or
#Component({
selector: .data-row,
with
<tr class="data-row"></tr>
EDIT - i can only get it to work using content projection in the child component, and then including the td elements inside the components element in the parent. See here - https://plnkr.co/edit/CDU3Gn1Fg1sWLtrLCfxw?p=preview
If you do it this way, you could query for all the rows by using ContentChildren
import { Component, ContentChildren, QueryList } from '#angular/core';
import { DataRowComponent } from './wherever';
somewhere in your component...
#ContentChildren(DataRowComponent) rows: QueryList<DataRowComponent>;
That will be defined in ngAfterContentInit
ngAfterContentInit() {
console.log(this.rows); <-- will print all the data from each component
}
Note - you can also have components that recurse (is that a word?) themselves in their own templates. In the template of data-row component, you have any number of data-row components.
I found a solution from another stackoverflow thread, so I can't take credit, but the following solution worked for me.
Put :host { display: contents; } into the data-row component .css file.
If you wrap row components in a ng-container you should be able to get it done
<tbody>
<ng-container *ngFor="let row of rows; let i = index">
<data-row [row]="row"></data-row>
</ng-container>
</tbody>
#Component({
selector: 'my-app',
template: `
<table>
<ng-container *ngFor="let row of table">
<tbody data-table-row [row]="row"></tbody>
</ng-container>
</table>
`,
})
export class App {
table = [
{
name: 'Parent',
children: [
{
name: 'Child 1'
children: []
},
{
name: 'Child 2'
children: [
{
name: 'Grandchild 1'
children: []
}
]
}
]
}
]
}
#Component({
selector: 'tbody[data-table-row]',
template: `
<tr><td>{{row.name}}</td></tr>
<tbody *ngFor="let child of row.children" data-table-row [row]="child"></tbody>
`
})
export class DataTableRowComponent {
#Input() row: any;
}
posting another answer just to show what i was talking about ... I'll leave you alone after this, promise. Heh.
http://plnkr.co/edit/XcmEPd71m2w841oiL0CF?p=preview
This example renders everything as a flat structure, but retains the nested relationships. Each item has a reference to its parent and an array of its children.
import {Component, NgModule, VERSION, Input} from '#angular/core'
import {BrowserModule} from '#angular/platform-browser'
#Component({
selector: 'my-app',
template: `
<table *ngIf="tableReady">
<tr *ngFor="let row of flatList" data-table-row [row]="row"> </tr>
</table>
`,
})
export class App {
tableReady = false;
table = [
{
name: 'Parent',
age: 70,
children: [
{
name: 'Child 1',
age: 40,
children: []
},
{
name: 'Child 2',
age: 30,
children: [
{
name: 'Grandchild 1',
age: 10,
children: []
}
]
}
]
}
];
flatList = [];
ngOnInit() {
let flatten = (level : any[], parent? :any ) => {
for (let item of level){
if (parent) {
item['parent'] = parent;
}
this.flatList.push(item);
if (item.children) {
flatten(item.children, item);
}
}
}
flatten(this.table);
this.tableReady = true;
}
}
#Component({
selector: '[data-table-row]',
template: `
<td>{{row.name}}</td><td>{{row.age}}</td>
`
})
export class DataTableRowComponent {
#Input() row: any;
}

How do you pass the element in Angular2 Typescript binding?

How do I get the specific HTML dom element passed through a binding. Sorry if this is hard to understand, here's the code.
donut-chart.html
<div class="donut-chart" (donut)="$element"></div>
How do I pass the div element to donut?
This is the TS
dount-chart.ts
#Component({
selector: 'donut-chart',
template: require('./donut-chart.html'),
directives: [Widget, MorrisChart],
encapsulation: ViewEncapsulation.None,
styles: [require('./donut-chart.scss')]
})
export class DonutChart implements OnChanges{
#Input() height: number = 300;
#Input() data: any[] = [{label: 'loading', value: '0', color: '#eee'}];
morris3Options: any;
donut: any;
render(): void {
jQuery(this.donut).css({height: this.height}); // safari svg height fix
window['Morris']['Donut']({element: this.donut}, this.morris3Options);
}
I want the donut variable to be the element without using class/id. I need to use multiple donuts and jQuery, so I need a way to get the unique donut.
<div #someElement></div>
<div class="donut-chart" (donut)="someElement"></div>
it can also be the current element
<div #someElement class="donut-chart" (donut)="someElement"></div>