I have a json file named (for now) 0.json. I want to display certain arrays within the json object as individual values (maybe display them as badges).
here is my json:
[
{
"id": "Chinwe Chukuwogu Roy WordPress Biography Website",
"name": "Chinwe Roy Biography Website",
"practices": ["UX", "HTML WireFraming", "Front-End Development", "Custom WordPress Theming"],
"technology": ["WordPress", "HTML", "CSS", "JQuery", "TweenMax", "Inkscape", "Photoshop"],
"time": "6 Weeks",
"description": "A biography website celebrating the work of world reknowned Artist, Chinwe Chukwogu Roy",
"images": "../assets/img/ux.svg",
"header": "../assets/img/wordpress-project.svg",
"behance": "https://www.behance.net/gallery/33173663/UI-Design-A-Website-Biography-Project"
}
]
I call the json like this within my controller:
$http.get('app/resources/v1/projects/' + $routeParams.id + '.json').success(function (details) {
$scope.details = details;
});
HTML:
<div class="row" ng-controller="ProjectCtrl">
<ng-header class="header-directive">{{ detail.header }}</ng-header>
<div class="container">
<div class="row">
<div class="col-md-12 work-parent" ng-repeat="detail in details">
<div class="work-child">
<h1>{{ detail.id }}</h1>
<br>
<p>{{ detail.description }}</p>
<small><strong>technologies:</strong> {{ detail.technology }}</small>
<small><strong>design practice:</strong> {{ detail.practices }}</small>
<small><strong>turnaround:</strong> {{ detail.time }}</small>
<ul class="social-icons">
<li class="behance">behance</li>
</ul>
</div>
</div>
</div>
</div>
</div>
The issue I am having is that I am unable to show e.g practices as individual values. I just get an complete array in the view when I bind detail.practices with an ng-repeat.
How would I manage this in my controller?
Just nest another ng-repeat inside your main one, so along the lines of:
<small ng-repeat="practice in detail.practices"><strong>design practice:</strong> {{ practice }}</small>
Or however else you want them to appear.
instead of this :
<small><strong>design practice:</strong> {{ detail.practices }}</small>
you can write this , so that you get each value of the array
<small><strong>design practice:</strong>
<ul>
<li ng-repeat="practice in detail.practices">{{ practice }}</li>
</u>
</small>
Hope that helps, good luck.
Try to use indexes
<div class="col-md-12 work-parent" ng-repeat="{index, detail} in details">
<div class="work-child">
<h1>{{ detail.id }}</h1>
<br>
<p>{{ detail.description }}</p>
<small><strong>technologies:</strong> {{ detail.technology }}</small>
<small><strong>design practice:</strong> {{ detail.practices }}
<div ng-if="detail.practices.length > 0">
<b ng-repeat="practice in details[index].practices">{{ practice }}</b>
</div>
</small>
<small><strong>turnaround:</strong> {{ detail.time }}</small>
<ul class="social-icons">
<li class="behance">behance</li>
</ul>
</div>
</div>
Related
I've got a multi-object array and I'd like to have it loop through a particular group of objects.
This is my code so far
<template>
<div>
<h1>My Test App</h1>
<button v-on:click="getHockeyData">Get Team Data</button>
<div v-for="hockeyData in hockeyDataList" :key="hockeyData.id" >
<p>{{ hockeyDataList.teams[0].roster.roster[1].person.fullName }}</p>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: "Weather",
data() {
return {
hockeyDataList: []
};
},
methods: {
getHockeyData() {
axios.get("https://statsapi.web.nhl.com/api/v1/teams/21?expand=team.roster").then(response => (this.hockeyDataList = response.data));
}
}
};
</script>
I know the loop won't work in it's current state. The portion of my output within the loop that I need to increment is roster[1] - I'm new to Vue so not sure how to use the v- commands to increment that 1 until there are no more instances of it.
Any help or feedback would be greatly appreciated!
Just loop over the others, really you want to start from teams as that's the way the JSON is structured
Example using various parts of the JSON, view the file for others.
<div v-for="team in hockeyDataList.teams" :key="team.id">
<h1>{{ team.name }}</h1>
<div>{{ team.venue.name }}, {{ team.venue.city }}</div>
<div>Created in: {{ team.firstYearOfPlay }}</div>
<div>Division: {{ team.division.name }} - Conference: {{ team.conference.name }}</div>
<h2>Roster</h2>
<div v-for="player in team.roster.roster" :key="team.id + '-' + player.person.id">
<h3>{{ player.person.fullName }}</h3>
<div>
Number: {{ player.jerseyNumber }} - Position: {{ player.position.name }} {{ player.position.type }}
</div>
</div>
</div>
<div v-for="team in hockeyDataList.teams" :key="team.id" >
<p v-for="roster in team.roster.roster :key="roster.id">
{{ roster.person.fullName }}
</p>
</div>
It's not necessary, but if you want to, you can get index in a v-for as well:
<div v-for="(team, index) in hockeyDataList.teams" :key="team.id" >
<p>
{{ hockeyDataList.teams[index].roster.roster[1].person.fullName }}
</p>
</div>
v-for increments the index automatically for you. The problem is that the api returns a json and not an array we can iterate on. By looking at the api response, we can see that teams is the array we can iterate on.
<v-for="(team, i) in hockeyDataList.teams" :key="i">
where index automatically increments until the end of list. We can then iterate through the roster.
<v-for="(roster, j) in team.roster.roster" :key="j">
Putting it all together
<div v-for="(team, i) in hockeyDataList.teams" :key="i">
<div v-for="(roster, j) in team.roster.roster" :key="j">
<p>{{ hockeyDataList.teams[i].roster.roster[j].person.fullName }}</p>
</div>
</div>
I'm trying to display all the reply from this json :
https://www.reddit.com/r/AskReddit/comments/k8w43d/people_with_the_last_name_pepper_who_have.json
So, depending of the post im loading and the reply, my number of children will differ. How can I loop throught it until I reach the last reply with children (body[2].data.children) ?
Like this :
<div class="replies-box" *ngFor="let reply of comments.body[1].data.children">
<div class="reply-header">
<p class="reply-author"><b>From</b> : {{ reply.data.author }}</p>
<p class="reply-send"><b>Send</b> : {{ this.getDateReply(reply.data.created_utc) }}</p>
</div>
<div class="text-first-reply" [innerHTML]="this.getHtmlDecode(reply.data.body_html)">
</div>
</div>
I have only the first level of reply, is there a way to simply loop through them all ?
Thanks in advance.
I would use a recursion type of approach.
Develop a app-comment component and if comment has children, loop over the children and display the app-comment. That way it will loop over the comments until no more children
<div *ngIf='comment'>
<span *ngIf='comment.kind; else showComment'>Kind: {{ comment.kind }}</span>
<ng-template #showComment>
<span>{{ comment }}</span>
</ng-template>
<div>
<app-comment *ngFor='let child of comment.data?.children' [comment]='child'> </app-comment>
</div>
</div>
See this sample illustration
Simply use ngFor inside ngFor with help of ng-container (will not create extra dom elements)
<div class="replies-box">
<ng-container *ngFor="let commentBody of comments.body">
<ng-container *ngFor="let reply of commentBody.data.children">
<div class="reply-header">
<p class="reply-author">
<b>From</b> : {{ reply.data.author }}
</p>
<p class="reply-send">
<b>Send</b> : {{ this.getDateReply(reply.data.created_utc) }}
</p>
</div>
<div class="text-first-reply" [innerHTML]="this.getHtmlDecode(reply.data.body_html)">
</div>
</ng-container>
</ng-container>
</div>
I read a lot of articles and posts and question in StackOverflow and the others but did not get my answer. I'm implementing a simple comment and reply component for my Laravel project.
* I have a table like below: *
id | name | body | reply_id | status
---------------------------------------------------------
1 | bran | good | null | accepted
2 | sansa | awe full article | 1 | accepted
3 | jan | soo Cool | 1 | accepted
4 | nightK | dont post it again| Null | accepted
5 | kalici | wow nice | Null | accepted
6 | worm | why ?? | 4 | accepted
If reply_id filed be Null i get it as main comment not as reply of comment
in my vuejs mounted() i will get all comments that are Null reply_id and accepted by admin from method named by getComments() and call it in mounted() .
also i'm using laravel pagination
my getComments as below vue code :
getComments(page = 1) {
var self = this;
axios.get('/comment/pagination/+post_id+ '?page=' + page)
.then(function(response) {
self.comments = response.data;
});
and show it with blow html and vuejs tags :
<div v-for="comment in comments.data" :key="comment.id" class="comments">
<div class="media comment" v-if="comment.reply==null">
<img src="/images/avar.png" width="50px" height="50px" alt="image">
<div class="media-body">
<h6 v-if="comment.user"> {{ comment.user['f_name'] }} {{ comment.user['l_name'] }} </h6>
<h6 v-if="!comment.user">{{ comment.name }}</h6>
<ul class="list-inline">
<li class="list-inline-item"><span class="fa fa-calendar"></span>{{ comment.created_at }}</li>
<li class="list-inline-item">Reply</li>
</ul>
<p>
{{ comment.body }}
</p>
</div>
</div>
<hr>
</div>
until here my component works well. shows just the main comments.
now its time to load the replies of main comments .
i use a method with name getReplies :
getReplies(MainCommentId) {
console.log(MainCommentId);
var self = this;
axios.get('/comment/replies/' + MainCommentId)
.then(function(response) {
console.log(response.data.data);
self.replies = response.data.data;
});
},
and then i changed my main comment view to below :
<div v-for="comment in comments.data" :key="comment.id" class="comments">
<div class="media comment">
<img src="/images/avar.png" width="50px" height="50px" alt="image">
<div class="media-body">
<h6 v-if="comment.user"> {{ comment.user['f_name'] }} {{ comment.user['l_name'] }} </h6>
<h6 v-if="!comment.user">{{ comment.name }}</h6>
<ul class="list-inline">
<li class="list-inline-item"><span class="fa fa-calendar"></span>{{ comment.created_at }}</li>
<li class="list-inline-item">Reply</li>
</ul>
<p>
{{ comment.body }}
</p>
<!-- Nested Comment -->
{{ getReplies(comment.id) }}
<div v-for="reply in replies" :key="reply.id" class="media comment">
<img src="/images/avar.png" width="50px" height="50px" alt="image">
<div class="media-body">
<h6 v-if="reply.user"> {{ reply.user['f_name'] }} {{ reply.user['l_name'] }} </h6>
<h6 v-if="!reply.user">{{ reply.name }}</h6>
<ul class="list-inline">
<li class="list-inline-item"><span class="fa fa-calendar"></span>{{ reply.created_at }}</li>
<li class="list-inline-item">Reply</li>
</ul>
<p>
{{ reply.body }}
</p>
</div>
</div>
</div>
</div>
<hr>
</div>
but when it wants to get replies by the method by each step of v-for main comments it will continuously send the request and the change data in HTML reply part. it acts like crazy like the below image.
any help will be appreciated.
This line {{getReplies(comment.id)}} create that issue, getReplies() called repeatedly and resetting replies
You must preload the replies and store it like this
this.replies = {
'1': [{
'message': "test"
},
{
'message': "test"
},
],
'2': [{
'message': "test"
},
{
'message': "test"
},
]
};
The keys( Now 1 and 2) of your replies array will be main comment id
And add this function in methods
methods : {
getReply (commentID) {
return this.replies[commentID];
}
}
Change the code like this
<div v-for="reply in getReply(comment.id)" :key="reply.id" class="media comment">
<img src="/images/avar.png" width="50px" height="50px" alt="image">
<div class="media-body">
<h6 v-if="reply.user"> {{ reply.user['f_name'] }} {{ reply.user['l_name'] }} </h6>
<h6 v-if="!reply.user">{{ reply.name }}</h6>
<ul class="list-inline">
<li class="list-inline-item"><span class="fa fa-calendar"></span>{{ reply.created_at }}</li>
<li class="list-inline-item">Reply</li>
</ul>
<p>
{{ reply.body }}
</p>
</div>
</div>
Right now, I have a bunch of filters that use ng-click to filter some JSON data pulled in from a factory:
<ul class="brands">
<li><a href="#" ng-click="brandFilter = null">All</li>
<li>Apple</li>
<li>Samsung</li>
<li>HTC</li>
</ul>
<div ng-controller="phonesController">
<div class="phonesContent">
<article ng-repeat="phones in phoneData | filter:brandFilter" class="phone-article">
<img src="{{ phones.image }}" alt="{{ phones.name }}" class="phone-img">
<p>{{ phones.name }}</p>
<p>Price: ${{ phones.price }}</p>
<p>No term: ${{ phones.no-term }}</p>
</article>
</div>
</div>
It works well, but I'm wondering how I can programmatically generate the links and use ng-click to filter. My best attempt so far:
<div ng-controller="phonesController">
<ul class="brands">
<li><a href="#" ng-click="brandFilter = null">All</li>
<li ng-repeat="phones in phoneData | unique: 'manufacturer'">{{ phones.manufacturer }}</li>
</ul>
<div class="phonesContent">
<article ng-repeat="phones in phoneData | filter:brandFilter" class="phone-article">
<img src="{{ phones.image }}" alt="{{ phones.name }}" class="phone-img">
<p>{{ phones.name }}</p>
<p>Price: ${{ phones.price }}</p>
<p>No term: ${{ phones.no-term }}</p>
</article>
</div>
</div>
The links are generating properly and the data is showing up in the phonesContent div, but the filtering is not working. I keep getting a $parse:syntax error so something is wrong with my expression where brandFilter = { 'manufacturer' = phones.manufacturer } (I think).
Rob has pointed out why your code is not working, but I would say it's best to avoid having assignment statements in your directives. That way the interface to your controler is clearly defined.
I'd suggest adding a scope function setFilter() to your controller that sets the filter value:
$scope.setFilter = function (value) {
$scope.brandFilter = value ? { manufacturer: value } : null;
};
Then you can do this:
<li><a href="#" ng-click="setFilter(null)">All</li>
<li ng-repeat="phones in phoneData | unique: 'manufacturer'">
{{ phones.manufacturer }}
</li>
i have this situation
<div ng-repeat="test in current">
<div ng-if="test.view == null">
<i class="icon ion-checkmark"></i>
</div>
</div>
but test.view== null doesn't work, neither just checking for test.view or test.view == ''
any ideas?
thanks
edit:
in the loop, sometimes test.view, has a value sometimes is NULL if i do:
<div ng-if="!test.view">1</div>
<div ng-if="test.view">2</div>
i will only see 1
You should check for !test, here is a fiddle showing that.
<span ng-if="!test">null</span>
See the correct way with your example:
<div ng-if="!test.view">1</div>
<div ng-if="!!test.view">2</div>
Regards, Nicholls
You can also use ng-template, I think that would be more efficient while run time :)
<div ng-if="!test.view; else somethingElse">1</div>
<ng-template #somethingElse>
<div>2</div>
</ng-template>
Cheers
Here is a simple example that I tried to explain.
<div>
<div *ngIf="product"> <!--If "product" exists-->
<h2>Product Details</h2><hr>
<h4>Name: {{ product.name }}</h4>
<h5>Price: {{ product.price | currency }}</h5>
<p> Description: {{ product.description }}</p>
</div>
<div *ngIf="!product"> <!--If "product" not exists-->
*Product not found
</div>
</div>