how can I print the key and value of the object inside the template?
The template is 'kendo chart series item tooltip'
My HTML
<kendo-chart-series-item-tooltip>
<ng-template let-value="value" let-category="category" let-series="series" let-dataItem="dataItem">
<div *ngFor="let item of dataItem.subObject| keyvalue">
{{item | json}}<br/>
Key:{{item.key}} and Value:{{item.value}}
<br/><br/>
</div>
</ng-template>
</kendo-chart-series-item-tooltip>
My JSON:
[
{
"id": "1Period",
"subObject": [{"Alex":"10"},{"Mathew":"5"}],
},
{
"id": "2Period",
"subObject": [{"Alex":"2"},{"Mathew":"50"}]
}
]
This code doesn't work and it returns this error:
Uncaught Error: Template parse errors:
The pipe 'keyvalue' could not be found
probably you want to set it like this
{
"id": "1Period",
"subObject": [
{
"key":"Alex",
"value":"10"}
}
and your HTML file like this
<kendo-chart-series-item-tooltip>
<ng-template >
<div *ngFor="let item of dataItem.subObject">
<br/>
Key:{{item.key}} and Value:{{item.value}}
<br/><br/>
</div>
</ng-template>
</kendo-chart-series-item-tooltip>
You can define the following custom pipe:
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'forObject'
})
export class ForObjectPipe implements PipeTransform {
transform(value: object): string[] {
if (!value) {
return [];
}
return Object.keys(value);
}
}
And use it like that:
<kendo-chart-series-item-tooltip>
<ng-template let-value="value" let-category="category" let-series="series" let-dataItem="dataItem">
<div *ngFor="let key of dataItem.subObject | forObject">
{{dataItem.subObject[key] | json}}<br/>
Key:{{key}} and Value:{{dataItem.subObject[key]}}
<br/><br/>
</div>
</ng-template>
</kendo-chart-series-item-tooltip>
Check out my boilerplate if you have issues defining the pipe.
Related
I just recently started learning Angular and I have a question. I want to implement a search method to search for a product on my site, I made search.pipe.ts, which works, but the input for input is in the header.component.ts component, and the products array is in the car-list.component.ts component.
car-list.component.html
<div *ngFor="let car of cars | paginate: { itemsPerPage: pageNumber, currentPage: currentPg} | **search:searchStr**" class="col-md-3">
<div class="product box">
<img src="{{'data:image/jpg;base64,' + car.image }}" alt="">
<h3>{{ car.name }}</h3>
<div class="price">{{ car.price | currency:'USD' }}</div>
<button class="btn btn-primary btn-sm">Add to cart</button> <!--(click)="addToCart(tempProduct)"-->
</div>
<br>
</div>
header.component.html
<form class="d-flex me-5">
<input type="text" class="form-control me-2" placeholder="Search cars...">
</form>
header.component.ts
export class HeaderComponent implements OnInit {
searchStr: string = '';
constructor() {
}
ngOnInit(): void {
}
}
search.pipe.ts
#Pipe({
name: 'search'
})
export class SearchPipe implements PipeTransform {
transform(cars: any[], value: any) {
return cars.filter(car => {
return car.name.includes(value);
})
}
}
I want the input values from the header component to be passed to the car-list component so that I can find the product I need.
In this case you can use a shared service where you can pass data from your header component and load that data in your products component.
For further reference - Angular 4 pass data between 2 not related components
use #Input and #Output decorators to communicate between components
I have a json initialised with key(key can be change,its dynamic), I need to manupulate into ngFor as per the static html.I have already tried but not working so I commented.Value of 'mainitem' will come as a heading and key of 'Seconditem' will come inside li tag.Here is the code below and demo https://stackblitz.com/edit/angular-ufbwzw?file=src%2Fapp%2Fapp.component.ts
app.component.html
<p>
Start editing to see some magic happen :)
</p>
<!--<div>
<ul>
<ng-container *ngFor="let item of jsonarray">
<h5>{{item.mainitem}}</h5>
<li *ngFor="let subItem of item.Seconditem | keyvalue">
{{subItem.key}} - {{subItem.value}}
</li>
</ng-container>
</ul>
</div>
-->
<div>
<ul>
<h5>My item 1</h5>
<li>createddate</li>
<li>enddate</li>
<h5>My item 2</h5>
<li>origindate</li>
<li>startdate</li>
</ul>
</div>
app.component.ts
import { Component, OnInit } from "#angular/core";
#Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
name = "Angular";
jsonarray = {
"575": [
{
mainitem: "My item 1",
Seconditem: {
createddate: "30-01-02",
enddate: "30-01-03"
}
},
{
mainitem: "My item 2",
Seconditem: {
origindate: "30-01-04",
startdate: "30-01-05"
}
}
]
};
ngOnInit() {}
}
<ul>
<ng-container *ngFor="let item of jsonarray | keyvalue">
<ng-container *ngFor="let value of item.value">
<h5>{{value.mainitem}}</h5>
<li *ngFor="let subItem of value.Seconditem | keyvalue">
{{subItem.key}} - {{subItem.value}}
</li>
</ng-container>
</ng-container>
</ul>
Working Stackblitz :- https://stackblitz.com/edit/angular-kfwv4m?file=src/app/app.component.html
I'm trying to access the nested data from the HTML template, but I get undefined or I get nothing as result (empty page with no class list or student list).
The HTML template:
<div class="container">
<label *ngFor="let class of listClass | keyvalue">
<span> {{class.value.name}} </span>
</label>
<div>
<label *ngFor="let student of class.students | keyvalue">
<span>{{student.value.fullName}} </span>
</label>
</div>
</div>
This is the fonction that gets the list of class and the students in it:
getListClasseStudent(){
this.classService.getStudents().subscribe((data) => {
this.listClass = data;
});
}
The nested data:
class:
0:{
code: "Math01"
teacher:
0: {id: 17551, name "Jack"}
students:
0: {studentId: 1, fullName: "Patrick bob"}
1: {studentId: 2, fullName: "Alice Alice"}
}
1:{
code: "English01"
teacher:
0: {id: 2, name "Nicolas"}
students:
0: {studentId: 1, fullName: "Patrick bob"}
1: {studentId: 2, fullName: "Alice Alice"}
}
I want to access to the list of student of each class, is there any efficient way to do it? thanks in advance.
<div class="container">
<div *ngFor="let c of listClass ">
<label >
<span> {{c.code}} </span>
</label>
<div>
<label *ngFor="let student of c.students ">
<span>{{student.fullName}} </span>
</label>
</div>
</div>
Try this (example without your pipe)
A 'Class' object don't have a attribute 'value.name' (probably gonna be injected by your pipe '| keyvalue' ).
Second *ngFor need t be inside of first, because he need's to iterate a students array, inside each class.
I hope this helps.
create a pipe like below
import { Pipe, PipeTransform } from "#angular/core";
#Pipe({ name: 'ObjNgFor', pure: false })
export class ObjNgFor implements PipeTransform {
transform(value: Object): Array<string> { return Object.keys(value); }
}
import the above pipe in app.module.ts and use pipe in the html page like below
<div *ngFor="let key of questions | ObjNgFor" class="row">
{{ questions[key].name}}
<div *ngFor="let r of questions[key].sub_sections | ObjNgFor ; let indx=index"
class="card-body">
{{ questions[key].sub_sections[r].name }}"
</div>
This example should work
I want to display content from the firebase I get the data from HTTP get request and I want to display it using ngFor
here is how i get the data
///a service
getMessages(){
return this.http.get('https://bigproject-dd88e.firebaseio.com/data.json')
.map((response:Response)=>{
const data: Message[]=response.json();
return data;
}
).catch(
(error:Response)=>{
return Observable.throw('something went wrong');
}
);
}
and here is my component
export class MessagesComponent implements OnInit {
Message=[];
constructor(private global:GlobalService) {
}
ngOnInit() {
this.GenaerateMessages();
}
GenaerateMessages(){
this.global.getMessages().subscribe(
Message=>this.Message=Message
);
}
}
and here is my HTML
<div *ngFor="let item of Message | keyvalue">
<p>{{item.value|json}}</p>
</div>
I get this on the screen
[ { "email": "loay-gohan#hotmail.com", "message": "loayy", "name": "loay", "phone": "123123123" } ]
[ { "email": "example#example", "message": "hi", "name": "..", "phone": "123123" } ]
how can I reach the inside fields name, message, phone...
it looks like eachitem.value contains one array with one object. If this is a case you can reach it like this:
<div *ngFor="let item of Message | keyvalue">
<div>EMAIL: {{ item.value[0].email }}</div>
<div>MESSAGE: {{ item.value[0].message }}</div>
<div>NAME: {{ item.value[0].name }}</div>
<div>PHONE: {{ item.value[0].phone }}</div>
<pre>{{ item.value | json }}</pre>
</div>
If item.value array has more than one object you might want to loop it wit additional inner ngFor
You do not use value.key. Don't you need it?
I have been trying to display a json file having multiple arrays in it on the front-end div tag in using Services Angular2 using Typescript. Can anyone help?
Also, If anyone can help transforming this code by adding Model and Interface class would be very helpful.
Here is the code:
SERVICE
export class HttpServiceDemo{
_data: any;
private url: string = "assets/sample.json"
constructor(private http: Http){}
getMyOrder(){
//return this.http.get(this.url)
// .map((response: Response)=> response.json());
return this.http.get(this.url)
.map(res => this.http = res.json().myOrder);
}
}
component.ts
export class SimpleHTTPComponentComponent implements OnInit {
data:any;
Order_date:any;
OrderNumber: number;
P_O_Number:number;
Total: number;
Quote_Status: string;
Expiration_Date: any;
Quote_Created_On: any;
constructor(public vara: HttpServiceDemo) {
}
ngOnInit() {
//calling myorder from json
this.vara.getMyOrder().subscribe(response => {
this.data=response;
for (var myOrder in this.data)
{
console.log(myOrder, this.data[myOrder]);
this.Order_date=this.data[myOrder].Order_Date;
this.OrderNumber=this.data[myOrder].OrderNumber;
this.P_O_Number=this.data[myOrder].P_O_Number;
this.Total=this.data[myOrder].Total;
this.Quote_Status=this.data[myOrder].Quote_Status;
}
})
}
sample.json
---------------
{
"accOrder":[
{
"Order_Date": "10-sep-1981",
"OrderNumber" : "E12345",
"P_O_Number": "P12345",
"Total": "123",
"Quote_Status": "In Progress"
},
{
"Order_Date": "1-oct-1981",
"OrderNumber" : "E82398",
"P_O_Number": "P87815",
"Total": "265",
"Quote_Status": "In Progress"
},
{
"Order_Date": "21-nov-1981",
"OrderNumber" : "E52367",
"P_O_Number": "P76549",
"Total": "454",
"Quote_Status": "In Progress"
},
{
"Order_Date": "10-dec-1981",
"OrderNumber" : "E42840",
"P_O_Number": "P23632",
"total": "123",
"Quote_Status": "Completed"
}
]
}
You are saying your console.log() shows the JSON just fine ?
Then, your data is correctly fetched into your component's data attribute.
You just have to go through your attribute in your template using *ngFor directive then.
Plunkr : https://plnkr.co/edit/4IdV3OHyNFNi90KXQQHP?p=preview
template: `
<div>
<div *ngFor="let order of data.accOrder" style="border: 1px solid lightgrey; padding: 15px; margin: 5px 0;">
Order_Date : {{ order.Order_Date }} <br>
OrderNumber : {{ order.OrderNumber }} <br>
P_O_Number : {{ order.P_O_Number }} <br>
Total : {{ order.Total }} <br>
Quote_Status : {{ order.Quote_Status }} <br>
</div>
</div>
`
PS : No need for your "for" loop inside ngOnInit() , this is not how you should access the data.
You should check out the ngFor doc to learn more about it.
EDIT :
As I said in my comment below, my previous Plunker was using raw data while you use asynchronous data in your use case (it's coming from an Observable sent from your service).
To make it work then, you have to check if your component already received the data before you try to display it. For that, you need to use the *ngIf directive.
New Plunkr : https://plnkr.co/edit/W5qykrh4blplGxTyp8aC?p=preview
template: `
<div *ngIf="data; else loading">
<div *ngFor="let order of data.accOrder" style="border: 1px solid lightgrey; padding: 15px; margin: 5px 0;">
Order_Date : {{ order.Order_Date }} <br>
OrderNumber : {{ order.OrderNumber }} <br>
P_O_Number : {{ order.P_O_Number }} <br>
Total : {{ order.Total }} <br>
Quote_Status : {{ order.Quote_Status }} <br>
</div>
</div>
<ng-template #loading>Fetching the data from the webservice... Wait 3 seconds !</ng-template>
`,
You have to create a parent div to the one with your *ngFor directive. In this parent div, use the *ngIf="data" directive. Everything inside it will not be displayed until there is some data into the data attribute.
I used here an if/else syntax which appeared with Angular4. But you don't need that. That's just here to display a message while there is no data. It could be a loading spinner for example, to let the user know he has to wait.
If you don't want to use this if/else condition, you can do it without it like that :
template: `
<div *ngIf="data">
<div *ngFor="let order of data.accOrder" style="border: 1px solid lightgrey; padding: 15px; margin: 5px 0;">
Order_Date : {{ order.Order_Date }} <br>
OrderNumber : {{ order.OrderNumber }} <br>
P_O_Number : {{ order.P_O_Number }} <br>
Total : {{ order.Total }} <br>
Quote_Status : {{ order.Quote_Status }} <br>
</div>
</div>
`,
Hope this helped :)