Angular: Show list in view with different object keys - json

I have the following JSON object:
header: {
first: {
title: {
name: "Test
}
},
second: {
title: {
name: "Test 2"
},
desc: {
name: "Description"
}
}
}
Now I want to show it in view like that:
How can I manage to do that in the view? Since the keys will vary every time. For example once you have header, another time main and so on... Something like JSONEditor, where you can edit JSON objects. But I want to create something like that with my own design. I tried with ngIf but it seems really difficult. I'd be really thankful for any suggestions or help.

You can use the KeyValuePipe to iterate over objects using ngFor.
<!-- app-your-node component -->
<div *ngFor="let item of object | keyvalue">
{{ title }}
<app-your-leaf *ngIf="yourLogicThatThisIsALeaf(item); else node"
[title]="item.key" [object]="item.value"><app-your-leaf>
<ng-template #node>
<app-your-node [title]="item.key" [object]="item.value"></app-your-node>
</ng-template>
</div>

Related

Access an Array inside an Object with square brackets inside a ngFor

Basically, I've created a HTML that similar to the example :
<div *ngFor="let formElements of formTemplate">
<div *ngFor="let opt of staticEnumVals[formElements.testId]">
<!-- do smth here -->
</div>
</div>
Basically formTemplate is an Array with Objects, each Object has a property called "testId".
staticEnumVals is an Object thats build like that
{
"testId": [ {},{},{} ],
"testId2" [ {},{},{} ],
}
The keys "testId" and "testId2" are actual keys that match the Keys from formTemplate[i].testId.
Basically I want to iterate through an array out of my staticEnumVals and the array is selected dynamically based on the id from the first *ngFor
Basically im looking for an elegant way to achieve my second iteration, square brackets doesnt work.
I think my problem is clear enough, im sorry for the weird title.
Thanks in advance
After adding types to the staticEnumVals this worked for me.
#Component({
selector: 'test',
template: `
<div *ngFor="let formElements of formTemplate">
<div *ngFor="let opt of staticEnumVals[formElements.testId]">
{{opt.name}}
</div>
</div>
`
})
export class TestComponent {
private formTemplate: { testId: string }[] = [
{testId: '3'}, {testId: '2'}, {testId: '3'}
];
private staticEnumVals: { [id: string]: [any] } = {
'1': [{name: 'id1'}],
'2': [{name: 'id2'}],
'3': [{name: 'id3'}],
};
}

Is there a way to make certain elements in a list invisible with angular *ngFor?

I am building a basic inventory tracking web app with Angular and I'm running into an issue. I want my main page to immediately display the most recent inventory data. The app is in its infancy, so the inventory data is being fed to it via a mock inventory list as shown here:
import { Inventory } from './inventory';
export const INVENTORY: Inventory[] = [
{ item: 'generic', type: 'sticker', count: 14 },
{ item: 'sonny', type: 'pti', count: 9 },
{ item: 'ribbon', type: 'pti', count: 4 },
{ item: 'sonny', type: 'box', count: 56 },
{ item: 'generic', type: 'box', count: 6 },
{ item: 'salad', type: 'box', count: 12 },
{ item: 'foam', type: 'other', count: 39 },
{ item: 'glue', type: 'other', count: 41 },
{ item: 'twine', type: 'other', count: 2 }
];
The list includes a type attribute so that I can filter by type later on.
To display this list, I'm using the HTML as follows:
<ul class="inventory">
<h3>Stickers</h3>
<li *ngFor="let item of inventory">
<a *ngIf="item.type === 'sticker'>
<span class="badge">{{item.item}}</span> {{item.count}}
</a>
</li>
</ul>
As you can see, I create a list element and call *ngFor="let item of inventory" to iterate over the entire list. Next *ngIf checks if the item type is 'sticker' and if so, it writes the item.item and item.count variables to the display. The span class="badge" is for css formatting purposes only.
The problem is, this displays the blank css attributes for every item in the list, and populates the ones where type === 'sticker'. I only want to display those items with type = 'sticker', and make the rest invisible. You can see what I mean at the image below.
Web output showing css formatted list items for all items and populating only the elements of the list with type === 'sticker'
How can I do this?
To resolve this issue, Use below CSS in component.css
ul li{
list-style: none
}
Sample working ocde for reference- https://stackblitz.com/edit/angular-cql9hi?file=src/app/app.component.css
Option 2:
Use ng container and move *ngFor to ng-container and *ngIf to li element
<ul class="inventory">
<h3>Stickers</h3>
<ng-container *ngFor="let item of inventory">
<li *ngIf="item.type === 'sticker'">
<a>
<span class="badge">{{item.item}}</span> {{item.count}}
</a>
</li>
</ng-container>
</ul>
working sample code for reference - https://stackblitz.com/edit/angular-x4lzgc?file=src/app/app.component.html
ng-container allows to wrap elements like block without creating new element
Please refer this link for more details on ng-container - <ng-container> vs <template>

Trouble getting data out of API using Vue JS

I'm having trouble iterating over data from a json file in Vue JS. I've got everything set up and have access to the json. What am I missing here:
JSON
{
"test": "example",
"data": [
{
"name": "My Name",
"address": "My Address"
}
]
}
Vue JS html
{{ someData['name'] }}
<ul>
<li v-for="item in someData" v-bind:key="item.id">
{{ item }}
</li>
</ul>
and my script:
created() {
this.$http.get('http://localhost:3000/properties.json').then(response => {
// get body data
this.someData = response.body
}, response => {
// error callback
});
}
The result I'm getting is:
Result
As you can see, in my v-for simply specifying item grabs each of the items here, but I want to be able to do something like {{ item['name'] }} and {{ item['address'] }}
The main problem is in your JSON file. VueJS v-for is iterating over the keys in your JSON file, in this case {{ item }} will be getting name and address. That is the reason of your output.
To solve this...
Format your JSON file as
[{name: 'John', address: 'Jane'}]
Doing this your VueJS v-for will be iterating over JSON array and {{ item }} will get the value { name: 'John', address: 'Jane' } and now you can do {{ item.name }} {{ item.address }}
An example here
EDIT: Update your API request code
created() {
this.$http.get('http://localhost:3000/properties.json').then(response => {
// get body data
this.someData = [response.body]
}, response => {
// error callback
});
}
You can simply do the following:
<template v-for="(item, key) in someData">
<span v-if="key == 'address'">{{item}}</span>
</template>
The crucial point is that the v-for="item in someData" part in the component's view iterates over values of the someData object, namely "John" and "Jane".
Depending on what exactly is your goal, you should either reformat the JSON to be an array of objects (as suggested by #F.bernal), or change the logic of v-for directive.

convert object to json

How do convert object to JSON and output it on html page?
public User:UserInfo=
{
firstName: "O",
lastName: "K",
email: "ol#op.com",
country: "uk",
avatarUrl: null,
receiveNotifications: true
}
I wish you had given us a bit more detail in your question, but I will do my best here so bear with me! Let's say you have an object that looks like this
a.component.ts
public obj = {
name: "Oleg",
question: "convert object to json",
description: "Some cool question about angular and JSON"
}
To present this data, your view would look like this
a.component.html
<h1> {{ obj.name }} </h1>
<h2> {{ obj.question }} </h2>
<p> {{ obj.description }} </p>
Please pay attention to how my class member is set to public, this is important whenever you are going to create an AoT build of the application.
If you are having trouble understanding, my simplified example. Check out this example
I can see that you are coming from the jQuery world, but with angular.js things are getting much simpler, please check this jsFiddle:http://jsfiddle.net/pkozlowski_opensource/ASspB/1/
With angular.js you can attach events much, much simpler:
<input type="button" ng-click="showJson()" value="Object To JSON" />
and then in your controller:
$scope.showJson = function() {
$scope.json = angular.toJson($scope.user);
}
In fact this could be done even easier with angular.js filters, check this jsFiddle: http://jsfiddle.net/pkozlowski_opensource/ASspB/2/ which has:
{{user | json}}
You can try the following:
let jsonStr=JSON.stringify(user).

How to implement nested data form in angular2

Here is Json schema :
{
"_id" : ObjectId("59031d77fd5e1c0b3c005d15"),
"resume_data" : {
"work_experience" : [
{
"company" : "example",
"website" : "example.com",
"position" : "Internship",
"highlights" : "Learn To Create API In Laravel Framework. and also Learn Angular 2 for Front end Development.",
"project_experience" : [
{
"projectName" : "Fb Project",
"teamMember" : "5",
"technology" : "PHP,Laravel-5,Angular-2,MongoDb",
"projectPosition" : "Back-end Developer"
}
]
}
]
}
}
Here is image:
I have reference of this answer but i don't know about nested form data. can anyone explain how to implement it.
Here is your code, which sets the data you are receiving from backend, here I have stored it in a variable data.
Please notice, this is a shortened version of your form, but the basics are there, you only need to add the few missing properties in corresponding form arrays.
The build of the empty form looks is just a FormArray named work_experience matching your json structure:
this.myForm = this.fb.group({
work_experience: this.fb.array([])
})
We add the fields when you are receiving the data, call a function called setWorkExperience in the callback when receiving data:
setWorkExperience(){
// get the formarray
let control = <FormArray>this.myForm.controls.work_experience;
// iterate the array 'work_experience' from your JSON and push new formgroup with properties and the inner form array
this.data.work_experience.forEach(x => {
// add the rest of your properties also below
control.push(this.fb.group({company: x.company, project_experience: this.setFormArray(x)}))
})
}
setFormArray is called from the previous function, where we patch the data with from project_experience to the inner form array:
setFormArray(x) {
// create local array which is returned with all the values from the 'project_experience' from your JSON
let arr = new FormArray([])
x.project_experience.map(y => {
// add the rest of your properties below
arr.push(this.fb.group({projectName: y.projectName}))
})
return arr;
}
The template would then look like this:
<form [formGroup]="myForm">
<!-- Outmost array iterated -->
<div formArrayName="work_experience">
<div *ngFor="let a of myForm.get('work_experience').controls; let i=index">
<h3>COMPANY {{i+1}}: </h3>
<div formGroupName="{{i}}">
<label>Company Name: </label>
<input formControlName="company" /><span><button (click)="deleteCompany(i)">Delete Company</button></span><br><br>
<!-- inner formarray iterated -->
<div formArrayName="project_experience">
<div *ngFor="let b of myForm.controls.work_experience.controls[i].controls.project_experience.controls; let j=index">
<h4>PROJECT {{j+1}}</h4>
<div formGroupName="{{j}}">
<label>Project Name:</label>
<input formControlName="projectName" /><span><button (click)="deleteProject(a.controls.project_experience, j)">Delete Project</button></span>
</div>
</div>
<button (click)="addNewProject(a.controls.project_experience)">Add new Project</button>
</div>
</div>
</div>
</div>
</form>
In the template you can see the buttons for add and delete of projects and companies. Adding and deleting companies are straightforward, where initCompany() returns a formGroup:
deleteCompany(index) {
let control = <FormArray>this.myForm.controls.work_experience;
control.removeAt(index)
}
addNewCompany() {
let control = <FormArray>this.myForm.controls.work_experience;
control.push(this.initCompany())
}
In the add project we pass as parameter from the template the current formArray control, to which we just push a new FormGroup:
addNewProject(control) {
control.push(this.initProject())
}
In the delete function we pass the current formarray as well as the index of the project we want to delete:
deleteProject(control, index) {
control.removeAt(index)
}
That should cover pretty much everything.
Plunker
Please Check it Out This
Plunker Here
Json Store Like This
{
"name": "",
"work_experience": [
{
"name": "asdasd",
"project_experience": [
{
"Project_Name": "asdasdasd"
},
{
"Project_Name": "asdasdasd"
}
]
}
]
}