I am new to angular. I am trying to display Json object in component. I am using keyvalue pipe with *ngFor to achieve this.
My Json Object
{
"categories": [
{
"categories": {
"id": 1,
"name": "Delivery"
}
},
{
"categories": {
"id": 2,
"name": "Dine-out"
}
},
{
"categories": {
"id": 3,
"name": "Nightlife"
}
},
{
"categories": {
"id": 4,
"name": "Catching-up"
}
},
{
"categories": {
"id": 5,
"name": "Takeaway"
}
}
]
}
My Component HTML:
<div *ngFor="let obcategories of users | keyvalue">
<div *ngFor="let obcategory of obcategories.value | keyvalue">
<div *ngFor="let nestedobcategory of obcategory.value | keyvalue">
{{nestedobcategory.value}}
</div>
</div>
</div>
It is displaying all both id value and name value. I want to display only name value.
Any help is much appreciated.
You can use {{nestedobcategory.value.name}} to access the name property:
<div *ngFor="let obcategories of users | keyvalue">
<div *ngFor="let obcategory of obcategories.value | keyvalue">
<div *ngFor="let nestedobcategory of obcategory.value | keyvalue">
{{nestedobcategory.value.name}}
</div>
</div>
</div>
Working Demo
Change:
{{ nestedobcategory.value }}
To:
{{ nestedobcategory.value.name }}
Code after changes:
<div *ngFor="let nestedobcategory of obcategory.value | keyvalue">
{{ nestedobcategory.value.name }}
</div>
Working Demo
A minor change would be:
nestedobcategory.value => nestedobcategory.value.name
IMP : In such cases use JsonPipe just to check what object you getting. If you use
{{ nestedobcategory.value | json }}
It will display your objects in the JSON Structure (Key/Value pair) and then you can access values that you want to display on the HTML.
Related
I would like to read JSON data in my VueJS code.
Here my code :
<template>
{{info}}
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
info: null
};
},
mounted(){
axios
.get('data/products.json')
.then(response => (this.info = response.data.data)),
}
</script>
I have that on the website :
[ { "id": "1000", "code": "1", "name": "Certificats", "description":
"cert Description", "status": "ERROR"}, { "id": "1005", "code": "2",
"name": "Autre", "description": "Product Description", "status":
"ERROR"} ]
I would like to be able to call only for example info.id to print just the id or to use it like an attribute in a v-if or in a v-for.
For example be able to do something like that :
<div :v-for="number in info.id">
{{number}}
</div>
Do you know how to do it ?
Thanks
<div v-for="infoItem in info" :key="infoItem.id">
{{ infoItem.id }}
</div>
Another solution to show only the ids of the errors would be
<div v-for="infoItem in info" :key="infoItem.id">
<div v-if="infoItem.status === 'ERROR'"
{{ infoItem.id }}
</div>
</div>
It's bad practise to combine v-for and v-if in the same line.
I'd suggest you change your v-for loop, and reference whichever key you want to access
<div :v-for="item in info">
{{ item.id }}
{{ item.name }}
</div>
and so on.
I am seeking the below result with nested JSON. I am not able to retrive/call keys and values in template dynamically. Refrence link is attached for detail veiw
Angular Code
let checklist = {
"CS": [
{
"id": "1",
"name": "A"
},
{
"id": "2",
"name": "B"
},
{
"id": "3",
"name": "C"
}
],
"Comment": [
{
"id": "1",
"name": "D"
},
{
"id": "2",
"name": "E"
},
{
"id": "3",
"name": "F"
}
]
}
<div *ngFor="let item of Checklist | Key">
{{key}}
<div>{{item}}</div>
</div>
Desired Result
Use keyvalue pipe to loop over Objects within template, Use some css to modify the display but a code like below will serve your need.
<div *ngFor="let item of checklist | keyvalue">
<div>
{{item.key}}
</div>
<div>
<p *ngFor="let eachValue of item.value">
{{eachValue.name}}
</p>
</div>
</div>
https://stackblitz.com/edit/angular-jgwk8n?file=src%2Fapp%2Fapp.component.html
Edit
For angular version < 6, keyvalue pipe doesn't exist. You can create your own custom pipe, maybe like:
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'customKeyvalue',
pure: true // keyvalue pipe is actually impure, which means this value would be false
})
export class CustomKeyvaluePipe implements PipeTransform {
transform(inputOb: any): any {
let returnVal = [];
for (let eachKey in inputOb) {
returnVal.push({key: eachKey, value: inputOb[eachKey]})
}
return returnVal
}
}
Now in case your Object changes dynamically without changing its original reference then you would have to make the above pipe as impure (pure: false). This has a downside of being triggered in every change detection.
https://stackblitz.com/edit/angular-jgwk8n?file=src%2Fapp%2Fapp.component.html
You can use Object.keys to get the keys of the object.
This is your component:
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
public checklist: any;
public ObjectKeys = Object.keys;
name = 'Angular';
ngOnInit() {
this.checklist = {
"CS": [
{
"id": "1",
"name": "A"
},
{
"id": "2",
"name": "B"
},
{
"id": "3",
"name": "C"
}
],
"Comment": [
{
"id": "1",
"name": "D"
},
{
"id": "2",
"name": "E"
},
{
"id": "3",
"name": "F"
}
]
};
}
}
This is the HTML:
<table border="1">
<tbody>
<tr *ngFor="let key of ObjectKeys(checklist)">
<td colspan="2" style="border-right-style: solid; border-width: 1px;">
{{ key }}
</td>
<td>
<div *ngFor = "let entry of checklist[key]">
{{ entry.name }}
</div>
</td>
</tr>
</tbody>
</table>
This is the result:
You can add CSS to make it look better, but you get the gist now :)
This is the StackBlitz link which you can edit.
The trick here is to use the display: inline-block and vertical-align: top.
It's similar to xyz example.
<div *ngFor="let item of checklist | keyvalue" >
<div style="display:inline-block;">
{{item.key}}
</div>
<div style="display:inline-block;vertical-align: top;">
<div *ngFor="let eachValue of item.value" >
{{eachValue.name}}
</div>
</div>
</div>
Example: https://angular-hzuexu.stackblitz.io
So I am using a JSON object that looks something like this:
data: [
{
title: "Post Title One",
categories: {
data: [
{
id: 1,
name: "Category Name 1"
}
]
}
},
{
title: "Post Title Two",
categories: {
data: [
{
id: 2,
name: "Category Name 1"
},
{
id: 3,
name: "Category Name 2"
}
]
}
}
]
and I want to grab all the categories for each post and display them using Vue. So what I have currently is:
<div v-for="post in posts">
<div>{{ post.categories.data }}</div>
</div>
In that {{ post.categories.data }} I am trying to display the category name from the JSON object. When I use what I have above the whole array is displayed in the div. When I try to do something like
{{ post.categories.data.name }}
or
{{ post.categories.data[0].name }}
I don't display the name of the category. I would really like to display the name of every category a post has, but can't seem to get it to display correctly.
EDIT: Also posts is the data property I am using in VueJS and am setting the JSON object to become that property.
You should use map method in conbination with destructuring.
<div v-for="post in posts">
<div>{{ post.categories.data.map(({name}) => name).join(' ') }}</div>
</div>
I have a json as following.
{
"id":14,
"discussion":8,
"parent":0,
"userid":2,
"subject":"communication skill discussion 2",
"message":"<p>hi all to communication discussion 2 </p>",
"children":[
24,
16,
15
]
},
{
"id":15,
"discussion":8,
"parent":14,
"userid":2,
"subject":"Re: communication skill discussion 2",
"message":"<p>hiiiiiiiiii</p>",
"children":[
25,
23
],
},
{
"id":23,
"discussion":8,
"parent":15,
"userid":2,
"created":1461562317,
"modified":1461562317,
"mailed":0,
"subject":"Re: communication skill discussion 2",
"message":"<p>helloooo</p>",
"children":[
],
}
I want first fetch the details whose Ids matches with the elments in children array
such as for id:14 there are 3 children 24,16,15.Then the control should go directly to id:15 and fetch details of id:15.Again id has children eg. consider id:23 which has no children and will directly print the message.
Please guide me how will I achieve this using ng-repeat of angular ?
Refer to the demo.
Please find the code below:
HTML:
<div ng-app="app" ng-controller="test">
<div ng-repeat="(key,value) in data">
{{key + 1}}) --
<span ng-if="value.children.length > 0">
{{value.children}}
</span>
<span ng-if="!(value.children.length > 0)">
No children found!!
</span>
</div>
</div>
JS:
var app = angular.module('app', []);
app.controller('test', function($scope) {
$scope.data = [{
"id": 14,
"discussion": 8,
"parent": 0,
"userid": 2,
"subject": "communication skill discussion 2",
"message": "<p>hi all to communication discussion 2 </p>",
"children": [
24,
16,
15
]
}, {
"id": 15,
"discussion": 8,
"parent": 14,
"userid": 2,
"subject": "Re: communication skill discussion 2",
"message": "<p>hiiiiiiiiii</p>",
"children": [
25,
23
],
}, {
"id": 23,
"discussion": 8,
"parent": 15,
"userid": 2,
"created": 1461562317,
"modified": 1461562317,
"mailed": 0,
"subject": "Re: communication skill discussion 2",
"message": "<p>helloooo</p>",
"children": [
],
}];
});
UPDATE: As per the request
Demo
HTML:
<div ng-app="app" ng-controller="test">
<div ng-repeat="(key,value) in data">
[{{key + 1}}] --
<div ng-if="value.children.length > 0">
<div ng-repeat="item in value.children">
<span>{{item}}</span> <span class="green" ng-bind-html="getMessage(item)"></span>
</div>
</div>
<span ng-if="!(value.children.length > 0)">
No children found!!
</span>
<br />
</div>
</div>
JS:
$scope.getMessage = function(itemId) {
var flag = true;
var msg;
angular.forEach($scope.data, function(value, key) {
if (flag && value.id == itemId) {
flag = false;
msg = value.message;
}
});
return $sce.trustAsHtml(msg);
}
CSS:
.green {
color: green;
}
Use ng-repeat to display the records.
<ul ng:controller="Cntl">
<li ng:repeat="item in data">
{{item.subject}}: Parent
<ul>
<li ng:repeat="child in item.children">{{child}} : Children
</li>
</ul>
</li>
This is one of the way to display in html. Based on your page design ng-repeat will change.
You can use lodash or underscore _.where:
<div ng:controller="Cntl">
<div ng:repeat="item in data">
{{item.subject}}<br/>
Children
<div ng:repeat="child in item.children">{{_.where(data, {id:child});}}
</div>
</div>
First you need to restructure your json into a tree structure. May be you want to have a look at this post. Then you have to recursively add templates
I have an angular controller called productImages which returns following JSON data:
{
"Product_1":[
{ "image_id":"12469",
"name":"My Product 1 - Variety 1",
"url":"\/\/mystorefront.net\/120\/small\/1911791794.jpg"
},
{
"image_id":"12470",
"name":"My Product 1 - Variety 2",
"url":"\/\/drfuittf5cya9.cloudfront.net\/121\/small\/1911802897.jpg"
}
],
"Product_2":[
{ "image_id":"122349",
"name":"My Product 2 - Variety 1",
"url":"\/\/drfuittf5cya9.cloudfront.net\/122\/small\/1911791794.jpg"
},
{
"image_id":"123470",
"name":"191123897.jpg",
"name":"My Product 2 - Variety 2",
"url":"\/\/drfuittf5cya9.cloudfront.net\/123\/small\/1911802897.jpg"
}
]
}
In my angular code I have written:
<div ng-controller="productImages">
<div ng-repeat="product in products">
{{product.image_id}}
</div>
</div>
When I run this the ng-repeat div gets repeated twice but product.image_id does not show up. If I do {{product}} instead or {{product.image_id}} I get the whole JSON printed.
How do I print this JSON in angularJS? Also, How do I get Product_1, Product_2 printed?
Your object Product_1 seems to be an array which in turn has images.
I think you will need nested for loops to display the images
You try to repeat over the properties of an object.
Accourding to the documentation here you'll have to use
<div ng-repeat="(key, value) in myObj"> ... </div>
each property of your object is an array so I think that something like:
<div ng-repeat="(key, value) in myObj">
<div ng-repeat= "product in value">
{{product.image_id"}}
</div>
</div>
should do the trick
Use two loops for this as:
angular.module('app',[]).controller('mainCtrl', function($scope){
$scope.products = {
"Product_1":[
{ "image_id":"12469",
"name":"My Product 1 - Variety 1",
"url":"\/\/mystorefront.net\/120\/small\/1911791794.jpg"
},
{
"image_id":"12470",
"name":"My Product 1 - Variety 2",
"url":"\/\/drfuittf5cya9.cloudfront.net\/121\/small\/1911802897.jpg"
}
],
"Product_2":[
{ "image_id":"122349",
"name":"My Product 2 - Variety 1",
"url":"\/\/drfuittf5cya9.cloudfront.net\/122\/small\/1911791794.jpg"
},
{
"image_id":"123470",
"name":"191123897.jpg",
"name":"My Product 2 - Variety 2",
"url":"\/\/drfuittf5cya9.cloudfront.net\/123\/small\/1911802897.jpg"
}
]
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app' ng-controller='mainCtrl'>
<div ng-repeat="product in products">
<div ng-repeat="item in product">
{{item.image_id}}
</div>
<hr/>
</div>
</div>
Your JSON syntax is incorrect. If I understand correctly, each of our product has several varieties. It should be as follows:
{
"Products": [
{
"Product": [
{
"image_id": "12469",
"name": "My Product 1 - Variety 1",
"url": "//mystorefront.net/120/small/1911791794.jpg"
},
{
"image_id": "12470",
"name": "My Product 1 - Variety 2",
"url": "//drfuittf5cya9.cloudfront.net/121/small/1911802897.jpg"
}
]
},
{
"Product": [
{
"image_id": "122349",
"name": "My Product 2 - Variety 1",
"url": "//drfuittf5cya9.cloudfront.net/122/small/1911791794.jpg"
},
{
"image_id": "123470",
"name": "My Product 2 - Variety 2",
"url": "//drfuittf5cya9.cloudfront.net/123/small/1911802897.jpg"
}
]
}
]
}
And you HTML should be:
<div ng-controller= "Products">
<div ng-repeat= "for oneproduct in Products">
<div ng-repeat="for variety in oneproduct">
{{variety.image_id"}}
</div>
</div>
</div>
Not tested this though...
You can't iterate on the object productImages because it's not an array.
You can iterate the objects "Product_1" and "Product_2".
If you want iterate the object productImage you have to write it ad an array.