I'm trying to display data from a certain part of a string of JSON data.
Below is the part i want to display.
{
"-rank": "3",
"-teamId": "t3",
"-name": "Arsenal",
"-played": "31",
"-won": "17",
"-drawn": "7",
"-lost": "7",
"-for": "52",
"-against": "30",
"-points": "58",
"-goalDifference": "22"
Below is the JS.
$scope.leagueTable = $scope.myData.LeagueTable.Table.TeamPosition;
//League Table
for( var i = 0; i < $scope.leagueTable.length; i++) {
if($scope.leagueTable[i]['-teamId'] == "t3") {
$scope.arsenalStats = $scope.leagueTable[i];
break;
}
}
console.log($scope.arsenalStats);
And below is the HTML I am using. I just get blank results. no errors.
<div class="row" ng-repeat="val in leagueTable| limitTo:-1">
<div class="col">{{arsenalStats[$index]['-played']}}</div>
<div class="col">{{arsenalStats[$index]['-won']}}</div>
<div class="col">{{arsenalStats[$index]['-drawn']}}</div>
<div class="col">{{arsenalStats[$index]['-lost']}}</div>
<div class="col">{{arsenalStats[$index]['-points']}}</div>
</div>
Any ideas?
using leagueTable object, you should be using val.
<div class="row" ng-repeat="val in leagueTable| limitTo:-1">
<div class="col">{{val[$index]['-played']}}</div>
<div class="col">{{val[$index]['-won']}}</div>
<div class="col">{{val[$index]['-drawn']}}</div>
<div class="col">{{val[$index]['-lost']}}</div>
<div class="col">{{val[$index]['-points']}}</div>
</div>
Related
I'm pulling data from a database into a json array.
I have this data
[{"id":"0","name":"red","percentage":"60"},{"id":"1","name":"blue","percentage":"58"},{"id":"4","name":"green","percentage":"12"}]
The div has a structure like below (simplified here), and I'd like to build rows with the data from the json array (javascript or jquery solution)
<div id="json"
<div class="row">
<div class="col-xs-5"><span id="name"></span></div>
<div class="col-xs-2"></div>
<div class="col-xs-5"><input type="number" id="percentage"></div>
</div>
</div>
Use append() and each()
var data =[{"id":"0","name":"red","percentage":"60"},{"id":"1","name":"blue","percentage":"58"},{"id":"4","name":"green","percentage":"12"}]
$.each(data,function(i,v) {
$('#json').append('<div class="row"> <div class="col-xs-5"><span class="name">'+v.name+'</span></div><div class="col-xs-2"></div><div class="col-xs-5"><input type="number" class="percentage">'+v.percentage+'</div></div>')
});
see demo
or pure javascript:
var data =[{"id":"0","name":"red","percentage":"60"},{"id":"1","name":"blue","percentage":"58"},{"id":"4","name":"green","percentage":"12"}];
var string ="";
for (i in data) {
string +='<div class="row"> <div class="col-xs-5"><span class="name">'+data[i].name+'</span></div><div class="col-xs-2"></div><div class="col-xs-5"><input type="number" class="percentage">'+data[i].percentage+'</div></div>';
};
document.getElementById('json').innerHTML =string
see demo
You can use the .hmtl() function of JQuery.
Just need to pass the html code to a dom element.
For example:
${"#json"}.html(" <div class="row">
<div class="col-xs-5"><span id="name"></span></div> </div>");
var data= [{"id":"0","name":"red","percentage":"60"},{"id":"1","name":"blue","percentage":"58"},{"id":"4","name":"green","percentage":"12"}]
data = $.parseJSON(data);
$.each(data, function(i, item) {
$("body").append('<div class="row">
<div class="col-xs-5"><span id="name">'+item.name+'</span></div>
<div class="col-xs-2"></div>
<div class="col-xs-5"><input type="number" id="percentage" value='+item.percentage+'></div>
</div>')
})
try this
try the each loop like this:
var data = [{"id":"0","name":"red","percentage":"60"},{"id":"1","name":"blue","percentage":"58"},{"id":"4","name":"green","percentage":"12"}];
$.each(data, function(i, o){
$('#json').append($('<div/>').addClass('row')
.append(
$('<div/>').addClass('col-xs-5')
.append($('<span/>').attr('id', 'name').text(o.name)))
.append(
$('<div/>').addClass('col-xs-2'))
.append(
$('<div/>').addClass('col-xs-5')
.append($('<input/>')
.attr('type', 'number')
.attr('id', 'percentage').val(o.percentage))
));
});
but beware: the id attribute have to be unique (i think you have to use the "name" attribute in your input element)
Refer demo here.
Please find code below:
HTML:
<div id="json"></div>
JS:
var data = [{
"id": "0",
"name": "red",
"percentage": "60"
}, {
"id": "1",
"name": "blue",
"percentage": "58"
}, {
"id": "4",
"name": "green",
"percentage": "12"
}];
$(function() {
$.each(data, function(key, value) {
$('#json').append('<div class="row"><div class="col-xs-5"><span id="name">' + value.name + '</span></div><div class="col-xs-2"></div><div class="col-xs-5"><input type="number" class="input form-control" id="percentage" value="' + value.percentage + '" /></div></div>')
});
});
CSS:
.input {
width: inherit;
}
I have this json set that needs to be displayed (in columns):
{
"2": [
{
"$id": "1",
"serverId": 1622,
"innCode": "PLOIKJ7",
"propertyName": "Property 1",
},
{
"$id": "2",
"serverId": 1622,
"innCode": "BHGTRWA",
"propertyName": "Property 2",
}
],
"3": [
{
"$id": "3",
"serverId": 1623,
"innCode": "TGHRE#W",
"propertyName": "Property 3",
}
]
}
I can't think of a way to "loop" through it using ng-repeat. I have the following template defined as a starter:
<div ng-repeat="s in sets">
<div class="panel panel-info">
<div class="panel-heading"><span><bold>Server: {{s.serverNum}}</bold></span></div>
<div class="panel-body">
<div>
<input type="checkbox" value="all#" ng-click="doNothing($event)"/>Select All
</div>
<div class="divider"> </div>
<div ng-repeat="p in s.properties">
<label class="margin-right12">
<input type="checkbox" name="property_{{p.innCode}}"
value="{{p.innCode}}" ng-click="doNothing($event)"/> <small>{{innCode}} - {{p.propertyName}}</small>
</label>
</div>
</div>
</div>
</div>
Thanks!
You can do like this
Inside the controller
$scope.data = {
"2": [
{
"$id": "1",
"serverId": 1622,
"innCode": "PLOIKJ7",
"propertyName": "Property 1",
},
{
"$id": "2",
"serverId": 1622,
"innCode": "BHGTRWA",
"propertyName": "Property 2",
}
],
"3": [
{
"$id": "3",
"serverId": 1623,
"innCode": "TGHRE#W",
"propertyName": "Property 3",
}
]
};
Inside the template
<div ng-controller="yourCntroName">
<div ng-repeat="(key, val) in data">// By this line you will get all keys of your set. '2' and '3' in your case
<div ng-repeat="obj in val"> // val will give you value of key(first time '2' and second time '3' in your case) that is an array so again use repeat.
{{'$id = '+obj.$id+' ,'}}{{'serverId = '+obj.serverId}}
</div>
</div>
</div>
The documentation for the built-in ng-repeat directive is available here.
Based on that documentation, the applicable expression for your use case should be ng-repeat="(key, value) in expression". expression should be substituted with set in your code.
Eventually you should arrive at something like this:
<div ng-repeat="(count, servers) in sets">
<div class="panel panel-info">
<div class="panel-heading">
<span><bold>Server: {{count}}</bold></span>
</div>
<div class="panel-body">
<div>
<input type="checkbox" value="all#" ng-click="doNothing($event)" />Select All
</div>
<div class="divider"> </div>
<div ng-repeat="server in servers">
<label class="margin-right12">
<input type="checkbox" name="property_{{server.innCode}}" value="{{server.innCode}}" ng-click="doNothing($event)" /> <small>{{server.innCode}} - {{server.propertyName}}</small>
</label>
</div>
</div>
</div>
</div>
Your markup could use a lot of improvement, but one thing at a time - I suggest you read the doc.
Background:
I have created an AngularJS test app which, obtains data from a JSON file, which is separated into categories and within each category is an employee card which is displayed through ng-repeat. These categories can then be viewed utilising a slider (using bxSlider).
Aim:
With bxSlider you can use custom Next/Previous buttons, what I wanted to achieve was to dynamically display the relevant category names in the Next/Previous buttons (please see annotation link below - my level does not allow me to post images).
Website Category Slider Wireframe
For example: the current category on view is the 'Technology' department, the previous button may then show 'Motors' department and the next button may show 'Law' department.
I understand that the code below would allow me to access the Category name 'Technology'. However this needs to be done in a dynamic nature.
{{employees[0].category}}
Below this I will include all what I believe to be relevant code.
JSON file:
[
{
"category": "Technology",
"shortname": "tech",
"icon": "fa-desktop",
"cards": [
{
"id": "card-1",
"name": "George Sofroniou",
"shortname": "G_Sof",
"age": "23",
"company": "Pirean Ltd.",
"role": "Graduate UI Developer"
},
{
"id": "card-2",
"name": "Steve Jobs",
"shortname": "S_Jobs",
"age": "56 (Died)",
"company": "Apple Inc.",
"role": "Former CEO"
},
{
"id": "card-3",
"name": "Mark Zuckerberg",
"shortname": "M_Zuck",
"age": "30",
"company": "Facebook",
"role": "CEO"
},
{
"id": "card-4",
"name": "Tim Cook",
"shortname": "T_Cook",
"age": "54",
"company": "Apple Inc.",
"role": "CEO"
},
{
"id": "card-5",
"name": "Jony Ive",
"shortname": "J_Ive",
"age": "48",
"company": "Apple Inc.",
"role": "Senior Vice President of Design"
},
{
"id": "card-6",
"name": "Marissa Mayer",
"shortname": "M_May",
"age": "39",
"company": "Yahoo!",
"role": "CEO"
},
{
"id": "card-7",
"name": "Yves Behar",
"shortname": "Y_Beh",
"age": "47",
"company": "Fuseproject",
"role": "Founder"
}
]
},
{
"category": "Motors",
"shortname": "mot",
"icon": "fa-car",
"cards": [
{
"name": "Elon Musk",
"shortname": "E_Musk",
"age": "43",
"company": "Tesla Motors",
"role": "CEO"
}
]
},
{
"category": "Football",
"shortname": "foot",
"icon": "fa-futbol-o",
"cards": [
{
"id": "card-1",
"name": "Sir Alex Ferguson",
"shortname": "A_Fer",
"age": "73",
"company": "N/A",
"role": "Retired"
}
]
},
{
"category": "Law",
"shortname": "law",
"icon": "fa-gavel",
"cards": [
{
"id": "card-1",
"name": "Harvey Specter",
"shortname": "H_Spec",
"age": "43",
"company": "Pearson Specter Litt",
"role": "Name Partner"
}
]
}
]
HTML Code:
<!-- Slider Container -->
<div class="slider-container">
<!-- Search Content -->
<!-- controls: true -->
<div class="content-results bxslider"
bx-slider="mode: 'horizontal', pager: true, nextSelector: '#next', prevSelector: '#prev', nextText: '<i class=\'fa fa-chevron-right\'></i>', prevText: '<i class=\'fa fa-chevron-left\'></i>', minSlides: 1, maxSlides:1, infiniteLoop: true, adaptiveHeight: true, hideControlOnEnd: false">
<!-- Employee -->
<div class="cards-container"
ng-repeat="item in filtered = ( employees | filter: query | orderBy:empOrder:direction )"
notify-repeat-finished>
<div class="category" ng-animate="'animate'" >
<div class="category-title">
<h1 class="title-cat"><i class="fa {{item.icon}}"></i> {{ item.category }}</h1>
</div>
<div class="category-cards-container">
<div class="employee-card card" ng-repeat="employee in filtered = (item.cards | filter: query | orderBy:empOrder:direction )" dom-manipulation>
<!-- Front Card -->
<div class="front">
<div class="pic-container">
<img ng-src="../static/images/placeholders/{{ employee.shortname }}.jpg" class="emp-pic" alt="Photo of {{ employee.name }}">
<h3 class="emp-name">{{ employee.name }}</h3>
<div class="darken"></div>
</div>
<ul class="emp-details">
<li class="detail emp-age">
<h5>Age: <small>{{ employee.age }}</small></h5>
</li>
<li class="detail emp-role">
<h5>Role: <br><small>{{ employee.role }}</small></h5>
</li>
<li class="detail emp-company">
<h5>Company: <br><small>{{ employee.company }}</small></h5>
</li>
</ul>
</div>
<!-- END Front Card -->
<!-- Back Card -->
<div class="back">
<div id="map-load">
<i class="fa fa-map-marker"></i>
</div>
<div id="maps-container">
<div id="googleMap"></div>
</div>
<i class="fa fa-times"></i>
</div>
<!-- END Back Card -->
</div>
</div>
</div>
<!-- No Matches -->
<div class="no-match" ng-show="filtered.length == 0">
<h3 class="no-matchText">Your search provides no matches!</h3>
</div>
<!-- END No Matches -->
</div>
<!-- END Employee -->
</div>
<!-- END Search Content -->
<!-- Next & Previous Buttons -->
<div class="btn-nextprev">
<div class="next-container">
<a href="" class="btn btn-next" id="next">
</a>
</div>
<div class="prev-container">
<a href="" class="btn btn-prev" id="prev">
</a>
</div>
</div>
<!-- END Next & Previous Buttons -->
</div>
<!-- END Slider Container -->
AngularJS:
Controller
var personControllers = angular.module('personControllers', ['ngAnimate']);
//PersonSearch Controller
personControllers.controller('PersonList', ['$scope', '$http',
function($scope, $http) {
$http.get('../static/scripts/data2.json').
success(function(data) {
console.log("JSON file loaded");
console.log(data);
$scope.employees = data;
//$scope.empOrder = 'name';
}).
error(function(){
console.log("JSON file NOT loaded");
});
}]);
EDIT
Updated Controller
var personControllers = angular.module('personControllers', ['ngAnimate']);
//PersonSearch Controller
personControllers.controller('PersonList', ['$scope', '$http',
function($scope, $http) {
$http.get('../static/scripts/data2.json').
success(function(data) {
console.log("JSON file loaded");
console.log(data);
$scope.employees = data;
//$scope.empOrder = 'name';
//Next & Previous Button Category Label
$scope.getNextCategoryIndex = function(currentIndex){
var nextIndex = currentIndex+1;
if( nextIndex >= $scope.employees.length ){
//move to start if at list end
nextIndex = 0;
}
return nextIndex;
}
$scope.getPrevCategoryIndex = function(currentIndex){
var prevIndex = currentIndex+1;
if( prevIndex < 0 ){
//move to the last index, if already at the start
prevIndex = $scope.employees.length - 1;
}
return prevIndex;
}
}).
error(function(){
console.log("JSON file NOT loaded");
});
}]);
Updated Next/Previous Buttons
<!-- Next & Previous Buttons -->
<div class="btn-nextprev">
<div class="next-container">
<a href="" class="btn btn-next" id="next">
{{ employees[getNextCategoryIndex($index)].category }}
</a>
</div>
<div class="prev-container">
<a href="" class="btn btn-prev" id="prev">
{{ employees[getPrevCategoryIndex($index)].category }}
</a>
</div>
</div>
<!-- END Next & Previous Buttons -->
I would probably do something like this: create functions to your controller to get the previous and next indexes (to handle the index overflows):
$scope.getNextCategoryIndex = function(currentIndex) {
var nextIndex = currentIndex+1;
if (nextIndex >= $scope.employees.length) {
// move over to start if we already were at the end of the list
nextIndex = 0;
}
return nextIndex;
}
$scope.getPrevCategoryIndex = function(currentIndex) {
var prevIndex = currentIndex+1;
if (prevIndex < 0) {
// move over to the last index, if we already are at the start
prevIndex = $scope.employees.length - 1;
}
return prevIndex;
}
And then in the HTML call those functions using $index (the current index of ng-repeat, see AngularJS documentation for ngRepeat for more details) as parameter:
<!-- Next & Previous Buttons -->
<div class="btn-nextprev">
<div class="next-container">
<a href="" class="btn btn-next" id="next">
{{employees[getNextCategoryIndex($index)].category}}
</a>
</div>
<div class="prev-container">
<a href="" class="btn btn-prev" id="prev">
{{employees[getPrevCategoryIndex($index)].category}}
</a>
</div>
</div>
<!-- END Next & Previous Buttons -->
The code you need should be:
{{employees[$index - 1].category}} //For the prev
{{employees[$index + 1].category}} //For the next
Recent Update (09-Apr-2015):
I have now been able to achieve what I wanted, on click of the button the relevant function runs and loops through the category names. One more thing to add now is that the buttons run in sync.
Controller
//Next & Previous Button Category Label
$scope.i = 0;
$scope.j = $scope.employees.length;
$scope.nextCat = $scope.i + 1;
$scope.prevCat = $scope.j - 1;
$scope.getNext = function(){
//console.log($scope.nextCat);
$scope.nextCat++;
if( $scope.nextCat >= $scope.employees.length ){
$scope.nextCat = 0;
}
$scope.prevCat++;
if( $scope.prevCat >= $scope.employees.length ){
$scope.prevCat = 0;
}
};
$scope.getPrev = function(){
//console.log($scope.nextCat);
$scope.prevCat--;
if( $scope.prevCat < 0 ){
$scope.prevCat = $scope.employees.length - 1;
}
$scope.nextCat--;
if( $scope.nextCat < 0 ){
$scope.nextCat = $scope.employees.length - 1;
}
};
HTML
<!-- Next & Previous Buttons -->
<div class="btn-nextprev">
<div class="next-container">
<a href="" class="btn btn-next" id="next"
ng-click="getNext()">
</a>
{{ employees[nextCat].category }}
</div>
<div class="prev-container">
<a href="" class="btn btn-prev" id="prev"
ng-click="getPrev()">
</a>
{{ employees[prevCat].category }}
<!-- {{ employees[prevCat].category }} -->
</div>
</div>
<!-- END Next & Previous Buttons -->
Update:
This is still not going to be a viable solution. I am technically able to achieve what is required however I am still required to use position: fixed. This means that the Category label then disappears.
I am now going to try and achieve this without it being within the ng-repeat and using ng-click it will iterate to the next Category name. Hopefully this will be the solution, and I will update upon any success/failure.
Update:
I am yet to find my optimal solution however, my current workaround for this utilises #jmustonen's solution.
Outside of the bxSlider I have the custom arrow's (if I placed these inside there were issues with the arrows not duplicating across pages - I believe there's an issue with it when it has position:fixed).
Then within my ng-repeat I include...
{{ employees[getNextCategoryIndex($index)].category }}
I will then be required to do some CSS in order for this to appear as if it is displayed as part of the Next/Previous buttons. Again these become invisible if position: fixed is used.
I have a multidimensional array from an API. Is it possible to programatically loop through the array?
{
success: true,
categories: [{
cat_id: "2",
name: "This is category One",
description: null,
photo_url: "/img/test.png",
order: "1",
items: [{
item_id: "1",
title: "Desk",
item_url: "/690928460",
photo_url: "/desk.png",
}, {
item_id: "2",
title: "Chair",
item_url: "/18882823",
photo_url: "/chair.png",
},
}]
}]
}
My controller looks like this:
myApp.controller('items', function($scope, $http, $location, Data) {
var apiUrl = '/api/items';
$http.get(apiUrl).
success(function(data) {
$scope.data = Data;
$scope.allData = data;
});
$scope.changeView = function(view) {
$location.path(view);
}
});
Angular index file just has: <div ng-view=""></div>
View file
<div class="scrollable categories-container animated-fast slideInUp">
<div class="container categories">
<div class="row" ng-repeat="categories in allData">
<div class="col-xs-6" ng-repeat="category in categories">
<div class="items">
<div class="title">
{{ category.name }}
</div>
</div>
</div>
</div>
</div>
</div>
I can loop through the category names fine, but when trying to return items for EACH category I don't understand the logic behind it...
I would suggest some simple nested for loops, as for each gives rise to more complexity.
As I'm not sure what you want to do with the data let's just create an array of all item names and one of all category names:
Within your success function:
var items = [], categories = []
for(var i = 0; i < data.categories.length;i++){
categories.push(data.categories[i].name);
for(var j = 0; j < data.categories[i].items.length;j++){
items.push(data.categories[i].items[j].name);
}
}
console.log(categories);
console.log(items);
EDIT:
Completely missed your html code somehow, here is my solution:
<div class="scrollable categories-container animated-fast slideInUp">
<div class="container categories">
<div class="col-xs-6" ng-repeat="category in allData.categories">
<div class="items">
<div class="title">
{{ category.name }}
</div>
</div>
</div>
</div>
</div>
EDIT 2:
As to your comment:
If you want to select the secondary view's contents(ie the items) based on the selection of a category I would suggest a ng-click attribute. A directive could be used but isn't necessary:
<div class="scrollable categories-container animated-fast slideInUp">
<div class="container categories">
<div class="col-xs-6" ng-repeat="category in allData.categories">
<div class="title" ng_click="selected_category = category">
{{ category.name }}
</div>
</div>
<div class="col-xs-6" ng-repeat="item in selected_category.items">
<div class="title">
{{ item.name }}
</div>
</div>
</div>
</div>
So when your categories data is loaded the first ng-repeat is populated with the categories. Each div with class title will have a function called on click which will make the selected_category object equal the selected category.
This will then cause the second view to be populated with all the items in the selected category by Angular's two way bind.
I'm making a "members" page for a website, which has 3 columns of pictures and names for each member. I want to be able to click on the picture to get more information about that member (via Foundation's modal). I'm using a repeater to display the pictures, but I'm stuck on how to pass member data into the modal so that when I click on person A, the modal will have person A's data.
Here is what I have so far:
I store the members as a json list in members.json:
{
"current" : [
{
"name": "Bob",
"pic": "http://www.placehold.it/300x300",
"id": "blah",
"position": "position 1",
"bio": "Hi I am Bob"
},
{
"name": "Bobby",
"pic": "http://www.placehold.it/300x300",
"id": "blah",
"position": "position 2",
"bio": "Hi I am Bobby"
}
]
}
And here is my controller, uses the json file:
var app = angular.module('app').controller('memberCtrl', ['$scope', '$http', function ($scope, $http) {
'use strict';
$http.get('/data/members.json').success(function(data) {
$scope.members = data;
$scope.numColumns = 3;
$scope.current_rows = [];
$scope.current_rows.length = Math.ceil($scope.members.current.length / $scope.numColumns);
$scope.current_cols = [];
$scope.current_cols.length = $scope.numColumns;
});
}]);
And here is my html:
<!-- My attempt at the modal -->
<div ng-controller="memberCtrl" id="myModal" class="reveal-modal">
<div class="row">
<div class="large-3 columns">
<img src="http://www.placehold.it/300x300">
</div>
<div class="large-6 columns">
<center>
<!-- The following remains blank -->
<h2>{{members.current[$parent.$index * numColumns + $index].name}}</h2>
</center>
<p class="lead">Bio.</p>
<p>Hi</p>
</div>
<div class="large-3 columns">
<img src="http://www.placehold.it/300x300">
</div>
</div>
<a class="close-reveal-modal">×</a>
</div>
<!-- This creates a 3 column array of member profiles (it works) -->
<div ng-controller="memberCtrl">
<div class="row" data-ng-repeat="row in current_rows">
<div class="large-4 columns" data-ng-repeat="col in current_cols">
<img ng-src="{{members.current[$parent.$index * numColumns + $index].pic}}">
<center>
<small><h3>{{members.current[$parent.$index * numColumns + $index].name}}</h3></small>
<small><h4>{{members.current[$parent.$index * numColumns + $index].position}}</h4></small>
</center>
</div>
</div>
</div>
Add ng-click attr in the img:
<img ng-src="{{members.current[$parent.$index * numColumns + $index].pic}}"
ng-click="loadMember(members.current[$parent.$index * numColumns + $index]);"/>
And add the function in the controller:
$scope.loadMember = function (member) {
//you should be able to access the current member
console.log(member);
}
Demo on jsFiddle