targetting deeply nested arrays in JSON data - json

I have been trying to list an actor name element with the following JSON format with angular js:
{movies: [
title: "Movie Title",
actors: {
list: [
{
name: "James Mason"
},
{
name: "Kirk Douglas"
},
{
name: "Paul Lukas"
},
{
name: "Peter Lorre"
}
]
}]
}
My parent ngrepeat element works with the top level element but can not access the actor names:
<ul ng-repeat="movie in items.movies">
<li>
<b>Title: </b> {{movie.title}}<br>
<b>Actor list:</b>
<ul>
<li ng-repeat="actor in movie.actors">
{{actor.list.name}}
</li>
</ul>
I have also tried the following:
<li>{{movie.actors['list'][0].name}}</li>
But the above only grabs the first name. I find the nesting very complicated to access with angularjs so if you could see something I am not, can you please help?

You still need to loop through 'list'
Add one more repeat.
ng-repeat="name in actor.list"

I fixed it:
<li ng-repeat="actor in movie.actors.list">{{actor.name}}</li>

Related

VUE-JS - CHECKBOX V-MODEL

enter image description here Hi Everyone Newbie at VUE.JS
I have a Checkboxes for MODULES and FUNCTIONS
I want to insert a Functions for every MODULE I have
Here's my sample code
<label> Modules:</label>
<li v-for="subModule1 in subModules" :key="subModule1.id">
<input type="checkbox" v-model="dataModules" :value="subModule1" />
{{subModule1}}<br>
[enter image description here][1]
{{subFunction}}
</div>
One thing that you could do is to create component like bellow I am not sure it will be a perfect solution but it should work atleast
<template>
<div>
<div v-for="module in modules" :key="module.text">
<h3>{{module.text}}</h3>
<ul>
<li
v-for="subModule in module.subModules"
:key="subModule.text"
>
{{subModule.text}}
<input type="checkbox" v-model="subModule.value"/>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
name: 'Example',
data(){
return {
modules:[
{
text:"Module 1",
subModules:[
{
text:"1-A",
value:false,
},
{
text:"1-b",
value:false,
}
]
},
{
text:"Module 2",
subModules:[
{
text:"2-A",
value:false,
},
{
text:"2-b",
value:false,
}
]
}
]
}
}
}
</script>
With this you are binding with array key is text but you can change it to something else and if you want to add new module or sub module just add it to array and it should be added to ui
If module dont pick new added items you something like deep copy and assign new array to module

Angular: Show list in view with different object keys

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>

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>

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"
}
]
}
]
}

custom jsTree css styling

I'm new to jsTree.How to apply custom css for jsTree div id like background color,node font style etc., any sample examples will be helpful
<div id="sampleTree"></div>
load jstree method
$('#sampleTree').jstree({
'core' : {
'data' : {
'url' : 'ajaxurl',
'data' : function (node) {
var test = ["jquery", "js", "css"];
return test;
}
}
}
});
since jstree is a totally javascript generated code, adding your own class would be not advisable, since adding it while the rendering time trough the jstree engine would make the system more complex. What you can do is, trace the classes in the themes/default/style.css
and make changes in the classes. some of them are .jstree hovered, clicked and so on.
If you want to put CSS onto individual entries use the html_data plugin. You can put it in your HTML strings with embedded CSS directly:
<div id="myTree">
<ul>
<li rel="root">
Parent 1
<ul>
<li><a style="font-weight:bold" href="#">Child 1</a></li>
<li><a style="color: red" href="#">Child 2</a></li>
</ul>
...
Yes you can change the theme css file according to you.
If you want more customization like changing the icons when open, when close etc then you can do it in jquery
$('#jstree-api').jstree({
'core': {
'data': jsonData
},
"types": {
"child": {
"icon": "glyphicon glyphicon-leaf"
},
"root": {
"icon": "glyphicon glyphicon-folder-close"
},
"default": {
"icon": "glyphicon glyphicon-folder-close"
}
},
"search": {
"case_insensitive": true,
"show_only_matches": true
},
"plugins": ["search", "themes", "types"]
});
$('#jstree-api').on('open_node.jstree', function (e, data) {
data.instance.set_icon(data.node, "glyphicon glyphicon-folder-open");
}).on('close_node.jstree', function (e, data) { data.instance.set_icon(data.node, "glyphicon glyphicon-folder-close"); });
Here is a series of articles on jsTree you can follow if you want.