Pass JSON array to custom element in Angular? - arrays

I can't seem to pass a JSON array in a angular component (custom element). I have the code in which I loop through the JSON array, and I have the array data set up in #Inject. Example:
import {
Input,
Component,
ViewEncapsulation,
EventEmitter,
Output
} from '#angular/core';
#Component({
selector: 'custom-wrapper',
template: `
<ul>
<li *ngFor="let item of items
{{ item.title }}
{{ item.age }}
</li>
</ul>
`,
encapsulation: ViewEncapsulation.Native
})
export class WrapperComponent {
#Input() items: any[];
}
Then, in my index.html file I call the custom element and I'm trying to pass a JSON array of objects into it, for example:
<custom-wrapper [items]="[{"title": "Mr", "age" : 23}, {"title": "Ms", "age" : "25"}]"></custom-wrapper>
All I get is an empty <custom-wrapper [items]="[{"title": "Mr", "age" : 23}, {"title": "Ms", "age" : "25"}]"></custom-wrapper> when I'm in inspect mode, and nothing is being listed.
Can someone help me locate the issue?

You should pass you're array using single quotes as you're using double quotes for attributes.
So this should be you're index.html:
<custom-wrapper [items]="[{title: 'Mr', age: 23}, {title: 'Ms', age: 25}]"></custom-wrapper>
Also in you're WrapperComponent, fix your li like this:
<li *ngFor="let item of items">

Related

how to pass array of different values as props in vue

everyone I hope everyone is doing great. I'm new to vue.js and was learning prop's which is pretty intersting. The thing is I want to pass an array as props and want to display it in the child component. here is my code
parent component
<template>
<div id="app">
<showProduct :product="['products']"/>
</div>
</template>
<script>
import showProduct from './components/showProduct.vue'
export default {
name: 'App',
components: {
showProduct
},
data(){
return{
products:[
{productid:"01",productname:"t shirt",price:"50$",description:"a good description"},
{productid:"02",productname:"jeans pant",price:"150$",description:"a good description of jeans"},
{productid:"02",productname:"leather jacker",price:"250$",description:"a good description of jacket"},
],
}
}
}
</script>
where as the child component code is given below
<template>
<h1>{{product}}</h1>
</template>
<script>
export default {
name:'showProduct',
props:[
'product'
],
methods:{
}
}
</script>
now I want to do the following:
Pass just a single element for instance product id as a 'props'.
Pass the whole array of products and display it in child components.
Any hint and suggestion will be welcomed.
Like this you will receive in the child component array of names, and index of the current item, so you can get just the name of the item in the child component.
Also don't forget to add unique key where you use v-for directive.
Like this you will receive in the child component array of names, and index of the current item, so you can get just the name of the item in the child component.
Also don't forget to add unique key where you use v-for directive.
Parent.vue
<template>
<div>
<child
v-for="(skill, index) in skills.length"
:key="skill.name"
:index="index"
:names-array="skills.map(a => a.name)"
/>
</div>
</template>
<script>
import Child from './Child'
export default {
name: 'Parent',
components: {
Child
},
data () {
return {
skills: [
{
name: 'Frozen Yogurt',
required: 1,
vMode1: ''
},
{
name: 'Ice cream sandwich',
required: 3,
vMode1: ''
},
{
name: 'Eclair',
required: 1,
vMode1: ''
}
]
}
}
}
</script>
Child.vue
<template>
<div>
<div>Index: {{ index }}</div>
<div>Names Array: {{ namesArray }}</div>
<div>Name: {{ namesArray[index] }}</div>
</div>
</template>
<script>
export default {
name: "Child",
props: ["names-array", "index"]
};
</script>
Output:
Index: 0 Names Array: [ "Frozen Yogurt", "Ice cream sandwich",
"Eclair" ] Name: Frozen Yogurt
Index: 1 Names Array: [ "Frozen Yogurt", "Ice cream sandwich",
"Eclair" ] Name: Ice cream sandwich
Index: 2 Names Array: [ "Frozen Yogurt", "Ice cream sandwich",
"Eclair" ] Name: Eclair

How to display an array of objects inside the html template in Angular 2?

I am building web app that will have a list of 3d models. I’m doing it for a practice purposes, in order to gain some initial knowledge of angular 2.
Each listed model, will have name, main picture, category, and a slider (array of images).
Model data array is:
export var MODELS: Model[] = [{
id: 1,
name: 'Model 1',
image: 'app/img/models/model-1.jpg',
category: 'Cat 1',
slides: [
{ alt: 'Model 1 front view' , url: 'app/img/models/model-2.jpg' },
{ alt: 'Model 1 rear view' , url: 'app/img/models/model-2.jpg' },
{ alt: 'Model 1 side view' , url: 'app/img/models/model-2.jpg' }
]
},
{
id: 2,
name: 'Model 2',
image: 'app/img/models/model-2.jpg',
category: 'Cat 2',
slides: [
{ alt: 'Model 2 front view' , url: 'app/img/models/model-2.jpg' },
{ alt: 'Model 2 rear view' , url: 'app/img/models/model-2.jpg' },
{ alt: 'Model 2 side view' , url: 'app/img/models/model-2.jpg' }
]
}
];
Service that is used for proper displaying of certain model is:
#Injectable()
export class ModelService {
getModels(): Promise<Model[]> {
return Promise.resolve(MODELS);
}
getModel(id: number): Promise<Model> {
return this.getModels()
.then(models => models.find(model => model.id === id));
}
}
Model detail’s page template is:
<div *ngIf="model">
<h2>{{model.name}} details!</h2>
<img [src]="model.image" alt="{{model.name}}"/>
<div>{{model.slides}}</div>
</div>
These are Mostly stuff that I used from: https://angular.io/docs/ts/latest/tutorial/
However, when I try to use simplest way to display slides array into model-detail page, it shows [object Object]. I read that this is might be a common issue in angular 2, that can be resolved by using custom pipes. Unfortunately, I have no clue how to write one for this certain case.
General question will be: How to properly display array of objects (slides) on html template, and wrap them separately into img tag.
Here is plunker example link: http://plnkr.co/edit/HVo3dtGprMHsPYeyRWBR?p=preview
Thanks in advance,
That's because your slides property is in fact an Object, it's an array so displaying the property alone will simply display 'object'. What you need to do is iterate over the slides property and separately create img divs:
<img *ngFor="let slide of model.slides" [alt]="slide.alt" [src]="slide.url" />
this is what your updated template would look like from your plunkr:
<ul class="models">
<li *ngFor="let model of models" (click)="gotoDetail(model)">
<img *ngFor="let slide of model.slides" [src]="slide.url"/>
{{model.name}},{{model.category}}
</li>
</ul>
You could use *ngFor in an img tag I have included some of my practice code to show you what I mean.
<div class="col-md-6" *ngFor="let picture of imageUrl; let i = index; trackBy: trackByFn">
<div class="portfolio-item"
style="padding-bottom: 10px;">
<a (click)="galleryOpen = false;componentIndex = i;" data-toggle="dropdown" href="#" name="gal2">
<img class="img-portfolio img-responsive" src={{picture}} height="350" width="455"
style="height: 350px; max-width: 455px;">
</a>
</div>
</div>
The *ngFor in this case could just a easily be placed in the img tag. I hope this helps you out.

Two-tier sorting for ng-repeat

For example, I have the following collection used for ng-repeat:
$scope.pokedex = [{
type: "Fire",
pokemon: ["Charizard", "Moltres"]
},{
type: "Rock",
pokemon: []
},{
type: "Fighting",
pokemon: ["Machamp", "Hitmonchan"]
},{
type: "Dragon",
pokemon: []
}];
This collection will be churned out in a ng-repeat directive. In the actual application, the collection will be retrieved from a database, so it may be unsorted. I want to sort it in the following manner: priority sort types with Pokemon to the top, then sort each group by name.
Edit: I need to clarify what the backend data consists of. In the above example, $scope.pokedex consists of a constant number of types - these are categories. The application retrieves Pokemon from the database and fill up each category's list accordingly. The full range of types is intentionally hardcoded into the array and will remain unchanged regardless of whether the list of Pokemon in it is empty or not.
When the web page is generated using ng-repeat, the desired end state is as follows:
An accordion is displayed with each type as a header, and the list of Pokemon in the body as a list/table.
All empty categories shall be disabled but still visible, their headers given a particular CSS format, and all of them PUSHED TO THE BOTTOM beneath the non-empty categories.
The empty group and non-empty group shall individually be sorted by category/type name.
Everything except the pushing of empty groups to the bottom and the sorting by name have been implemented. These are my final requirements to implement.
How can I do that? Is there a way to do it in advance, or via orderBy during ng-repeat, or any other workable solution?
You Can Try like this This
<ul>
<li ng-repeat="people in peoples | orderObjectBy:'pokemon':true">{{ people.name }}</li>
</ul>
Please try the code below
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="pokemonController">
<ul>
<li ng-repeat="people in peoples | orderBy:['-pokemon.length','name']">
name: {{people.name}} - number of Pokemons: {{people.pokemon.length}}
<hr />
</li>
</ul>
</div>
</div>
<script>
var app = angular.module('myApp',[]);
app.controller('pokemonController', ['$scope', function($scope){
$scope.peoples = [{
name: "Obama",
pokemon: ["Charizard", "Dragonite", "Moltres"]
},{
name: "Merkel",
pokemon: []
},{
name: "Putin",
pokemon: ["Machamp", "Hitmonchan"]
},{
name: "Kim",
pokemon: []
}];
}]);
</script>

Ng-repeat inside ng-repeat

<ul ng-repeat="cate in restaurant.categories"><li>{{cate}}</li>
<li ng-repeat="menuItem in restaurant.menuItems" ng-show="menuItem.category == cate">{{menuItem.name}}</li></ul>
I want one ng-repeat loop inside another and to show the menu only if the menuItem is in the category. I only have items in the first category loop, and empty for all the other categories.
Categories and menuItem are 2 different arrays. If the menuItem's category is under the current category it should be added to the page.
menuItems = {{name: dish1, category:soup},
{name: dish2, category:beef}}
categories = {beef, soup}
#show-me-the-code : Bill Bi has two different array. So the best option to achieve this is by filter in inside loop as stated in my comment.
Here is the final code with filter for inside loop. I am including fiddler for quick reference.
<div ng-app ng-controller="testCtrl">
<ul ng-repeat="cate in categories">
<li>{{cate}}</li>
<li ng-repeat="menuItem in menuItems | filter:{category: cate}">{{menuItem.name}}</li>
</ul>
</div>
function testCtrl($scope) {
$scope.menuItems = [{name: 'dish1', category:'soup'},
{name: 'dish2', category:'beef'}];
$scope.categories = ['beef', 'soup']
}
Fiddle : JSFiddle
I would change my data representation to match what you are actually trying to display like so:
$scope.restaurant = {
categories: [{
name: "beef",
menuItems: [{
name: "dish1",
"price": "$10"
}, {
name: "dish2",
"price": "$15"
}]
}, {
name: "soup",
menuItems: [{
name: "dish1",
"price": "$20"
}, {
name: "dish2",
"price": "$25"
}]
}]
};
This way you could easily match your two nested loops like this:
<div ng-app ng-controller="testCtrl">
<ul ng-repeat="cate in restaurant.categories">
<li>{{cate.name}}</li>
<li ng-repeat="menuItem in cate.menuItems">{{menuItem.name}} - {{menuItem.price}}</li>
</ul>
</div>
Check out this fiddle if you would like to see it in action.
If you need to stick to your JSON data, you will have to do filtering to pull the contents you want to display.

display all items in an array of objects with each or jQuery .map()

I have an array of objects like this in a JSON:
[
{
"Name":"John Doe",
"Age":46,
"Hometown":"Anytown, USA",
},
{
"Name":"Jane Q. Public",
"Age":23,
"Hometown":"Mayberry, NC",
},
{
"Name":"Andrew Andrews",
"Age":62,
"Hometown":"New York, NY"
},
]
I need to convert it to HTML with this format:
<div class="person">
<h2>Name</h2>
<p class="name">John Doe</p>
<h2>Age</h2>
<p class="age">46</p>
<h2>Hometown</h2>
<p class="hometown">Anytown, USA</p>
</div>
...
Would it be best to use jQuery's .map() for this? Or each ? How should I set it up?
I was able to do this with the loadJSON plugin, which is very handy in creating an HTML template from actual HTML. I'd still be interested in a .map() or each way to do it.

Resources