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>
Related
I have JSON Array with following structure
items: [
{
ID: 11,
UserID: "test.com",
UserRole: "user",
timeStamp: "2021-03-23T15:54:02.125578",
dialogs: [
{
"Bot": "Why is data missing?",
"test.com": "not available",
"Bot": "please enter ID",
"test.com": "1234"
}
]
}
]
I have to display elements inside dialogs as list. i am using v-for but dialogs is displaying as array with commas. how can i show this with index? Following is v-for loop i am using
<ul v-for="item in items" :key="item">
<li v-for="(dialog, index) in dialogs" :key="index">{{key}}: {{dialogs}}</li>
</ul>
<ul v-for="item in items" :key="item">
<li v-for="(dialog, index) in item.dialogs" :key="index">{{index}}: {{dialog}}</li>
</ul>
There are 2 changes required.
In your dialogs you have duplicate keys, so they need to separated out into two different objects.
In your HTML part you need to loop as items.dialogs
Here is the full code.
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!',
items: [
{
ID: 11,
UserID: "test.com",
UserRole: "user",
timeStamp: "2021-03-23T15:54:02.125578",
dialogs: [
{
"Bot": "Why is data missing?",
"test.com": "not available",
},
{"Bot": "please enter ID",
"test.com": "1234"
}
]
}
]
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<ul v-for="(item, index) in items" :key="item">
<li v-for = "(data, index) in item.dialogs">
{{data}} {{index}}</li>
</ul>
</div>
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.
I have an array called reducedGroups.
In response to Javas commetn below I have restructured this array so that it is now an Array of Objects, the number of Objects contained will always differ.
It may look something like this:
[
{ "0": { "value": "ccc" }, "1": { "value": "aaa" }, "2": { "value": "ddd" }, "3": { "value": "bbb" } },
{ "0": { "value": "eeee" } },
{ "0": { "value": "fff" } },
{ "0": { "value": "ggg" } }
]
The code below arranges the internal arrays into groups and a Vuetify Text Field is shown above which allows the user to name each group.
<div v-for="(group, index) in reducedGroups" :key="index">
<v-flex>
<v-text-field label="Group Name" />
<div
v-for="item in group"
:key="item.value"
>{{ item.value}}</div>
<div>
<v-btn icon color="error" #click="removeGroup(index)">
<v-icon>mdi-trash-can</v-icon>
</v-btn>
</div>
</v-flex>
</div>
The output of this is shown below.
I have 2 questions:
1) How can I know when the user has given each group a name? - this will be used to trigger the trash cans to appear on screen
2) How can I then get access to the names of the groups that have been given by the user? - Once the user has removed the least relevant groups and just 3 remain, I want to print to screen the names of the remaining groups.
UPDATE: Restructured the data in response to Javas
I'm not sure your data structure is appropriate for the model, even after refactoring into objects. It seems like what you really have is an array of groups. And each group has (a) a name (initially empty), and (b) an array of values. If that's the case, a natural structure for your data would be something like
[
{ name: "", values: ["ccc", "aaa", "ddd", "bbb"] },
{ name: "", values: ["eeee"] },
{ name: "", values: ["fff"] },
{ name: "", values: ["ggg"] }
]
With that structure, the template becomes more straightforward. (I don't know the details of <v-text-field /> but assuming it's the same as a standard <textarea />:
<div v-for="(group, index) in reducedGroups" :key="index">
<v-flex>
<v-text-field label="Group Name" v-model="group.name"/>
<div
v-for="value in group.values"
:key="value"
>{{value}}</div>
<div>
<v-btn icon color="error" #click="removeGroup(index)">
<v-icon>mdi-trash-can</v-icon>
</v-btn>
</div>
</v-flex>
</div>
Edited to Add
In response to the comments, use computed properties to extract the names and to check for any empty
computed: {
groupNames() {
return reducedGroups.map(group => group.name);
},
allNamesPresent() {
return reducedGroups.every(group => group.name);
}
}
I might also suggest that working through a basic online Vue tutorial might be helpful to you.
I'm trying to print out each array item from a property in an object:
{
position:"Finance Office Assistant",
employer:"Washtenaw County Finance Department",
location:"Ann Arbor, MI",
start_date:"2012",
current: false,
end_date:"2012",
duties: [
"Item 1",
"Item 2",
"Item 3"
]
},
This object is in an array, with several other objects. I'm trying to create a function that loops through all of the objects and prints out the duties array items in an unordered list with the exact number of list items and array items.
Here is the function I'm trying to write to do the task
$scope.dutyList = function() {
var arrayLength = $scope.duties.length;
while (arrayLength > 0) {
console.log("dutyList run")
document.write("<li> {{ dutyList }} </li>");
--arrayLength;
}
}
You don't need a function to handle displaying data like this. Angular's ngRepeat is for this. To access the second level of of your data set you can nest two repeats in your unordered list. The first one (in a div) repeats the first layer of your data, and exposes the second layer, which repeat in the <li> tag:
<ul>
<div ng-repeat="d in data">
<li ng-repeat="duty in d.duties">{{duty}}</li>
</div>
</ul>
Plunker
As a general rule, you don't want to write directly to the document when using a framework like Angular. Instead, you should use the built in templating system and directives to render your page.
I'm making some assumptions about the end goal here, but, assuming the array of objects can be accessed by the controller and attached to the scope, you could print your unordered list of duties for each position using something like the following.
angular.module('myApp', []).controller('myCtrl', function($scope){
$scope.foo = [{
position:"Finance Office Assistant",
employer:"Washtenaw County Finance Department",
location:"Ann Arbor, MI",
start_date:"2012",
current: false,
end_date:"2012",
duties: [
"Item 1",
"Item 2",
"Item 3"
]
}, {
position:"Another Position",
employer:"Another Employer",
location:"Ann Arbor, MI",
start_date:"2012",
current: false,
end_date:"2012",
duties: [
"2nd Object, Item 1",
"2nd Object, Item 2",
"2nd Object, Item 3"
]
}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='myApp' ng-controller='myCtrl'>
<div ng-repeat='bar in foo'>
<h1>{{ bar.position }}</h1>
<ul>
<li ng-repeat='duty in bar.duties'>
{{ duty }}
</li>
</ul>
</div>
</div>
Here is the scenario, the page is made of backbone views (multiple views, around 20) and about 30 templates. All structured using requirejs architecture. But some of the values in the template such as heading tiles, sub heading titles and drop down values come from a single json object returned by an ajax request during page load. How do I pass these values around multiple templates?
If I understood correctly then you can do in the following way:
Link to jSFiddle
HTML:
<div id="container"></div>
<script type="text/template" id="modelTemplate">
<h1 data - id = "<%=Id%>" > <%= Name %> </h1>
<ul>
<%_.each(Titles,function(title){%>
<%=_.template($("#titleTemplate").html())(title)%>
<%});%>
</ul>
</script>
<script type="text/template" id="titleTemplate">
<li> <%= Name %>
<ul>
<%_.each(SubTitles,function(subTitle){%>
<%=_.template($("#subTitleTemplate").html())(subTitle)%>
<%});%>
</ul>
</li>
</script>
<script type="text/template" id="subTitleTemplate">
<li> <%= Name %> </li>
</script>
And JavaScript (instanceOfModel is some model that you populates with ajax request):
var model = Backbone.Model.extend({});
var instanceOfModel = new model({
Id: 1,
Name: "Some Name",
Titles: [{
Name: "First Title",
SubTitles: [{
Name: "SubTitle Name 1"
}, {
Name: "SubTitle Name 2"
}]
}, {
Name: "SecondTitle",
SubTitles: [{
Name: "SubTitle Name 3"
}, {
Name: "SubTitle Name 4"
}]
}, {
Name: "Last Title",
SubTitles: [{
Name: "SubTitle Name 5"
}, {
Name: "SubTitle Name 6"
}]
}]
});
var modelTemplate = _.template($("#modelTemplate").html());
$("#container").append(modelTemplate(instanceOfModel.toJSON()));