How do I access JSON objects using Handlebars.js? - javascript

I'm creating a basic web app using the Echo Nest API to get used to templating and fetching data from APIs. I was just wondering how I would access the 'artist_name' & 'title' objects inside 'song' from the JSON object and use Handlebars.js to insert this data inside my template? When I do the {{#each songs}} as I've written below, it doesn't work.
Thanks in advance!
PS. Jeanie Tracy does not reflect my music taste. It's just the JSON object that came up when I was testing it!
<main>
<section>
<input type="text" id="genre-name" placeholder="Enter the Genre Here." />
<input type="number" id="bpm" placeholder="Enter the BPM here." id="bpm">
Fetch
</section>
<section id="results">
</section>
</main>
<template id="results-template">
<article>
<header>
{{#each songs}}
<h1>{{ this.artist_name }}</h1> {{/each}}
</template>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="handlebars.js"></script>
<script type="text/javascript">
$('#fetch-albums').on('click', function() {
var genre = $('#genre-name').val();
var bpm = $('#bpm').val();
var source = $('#results-template').html();
var template = Handlebars.compile(source);
$.get('http://developer.echonest.com/api/v4/song/search?api_key=[hidden]&style=' + genre + '&min_danceability=0.65&min_tempo=' + bpm + '&results=5', function(data) {
$('#results').append(template(data));
});
});
</script>
JSON OBJECT
{
"response": {
"status": {
"version": "4.2",
"code": 0,
"message": "Success"
},
"songs": [{
"artist_id": "AR8COOH1187B990D7D",
"id": "SOGMVZZ1393A2A9142",
"artist_name": "Jeanie Tracy",
"title": "I'm Gonna Get You"
}, {
"artist_id": "AR8COOH1187B990D7D",
"id": "SOGMIVN14248BD9E88",
"artist_name": "Jeanie Tracy",
"title": "Feel Like Dancing [Joey Negro Dubbed Out]"
}, {
"artist_id": "AR8COOH1187B990D7D",
"id": "SOIMUFZ1315CD4CDEC",
"artist_name": "Jeanie Tracy",
"title": "Do You Believe In Wonder (Stone & Nick Late Nite Diner Mix)"
}, {
"artist_id": "AR8COOH1187B990D7D",
"id": "SOEQTUW1315CD4FAB2",
"artist_name": "Jeanie Tracy",
"title": "Intro"
}, {
"artist_id": "AR8COOH1187B990D7D",
"id": "SOENYBA12A6D4F46C0",
"artist_name": "Jeanie Tracy",
"title": "Rosabel's Disco Diva Mix"
}]
}
}

Your <article> and <header> don't have closing tags. While the HTML specifications may allow some tags to omit closing (like <td>, afaik), and while some browsers are forgiving enough, I don't know if the Handlebars compiler is the same.
Your songs is still under response. I think it should be {{#each response.songs}}. Also, I think you can go with {{ artist_name }} too.

Related

v-for loop not returning data Vue.js

I'm new to Vue.js and following a tutorial. I'm trying out the v-for loop using the data in the json below. However nothing is being rendered in the div and therefore the page. I can't spot any syntax errors. Can anyone help?
<body>
<div id="app" v-for="item in products">
<img :src="item.img" :alt="item.img" style="width: 250px; height:250px">
<h1>{{item.name}}</h1>
<p>{{item.description}}</p>
<p>${{item.price}}.00</p>
</div>
<script>
var data = {
products: [
{
"name": "Bamboo Thermal Ski Coat",
"description": "You'll be the most environmentally friendly skier in this!",
"img": "https://hplussport.com/wp-content/uploads/2016/12/ski-coat_LYNDA_29940.jpg",
"price": 99
},
{
"name": "#jenlooper",
"img": "https://user-images.githubusercontent.com/41929050/61567048-13938600-aa33-11e9-9cfd-712191013192.jpeg",
"description": "This project is a good learning project to get comfortable with soldering and programming an Arduino.",
"price": 5
},
{
"name": "jenlooper",
"img": "https://user-images.githubusercontent.com/41929050/61567049-13938600-aa33-11e9-9c69-a4184bf8e524.jpeg",
"description": "Use craft items you have around the house, plus two LEDs and a LilyPad battery holder, to create a useful book light for reading in the dark.",
"price": 63
},
{
"name": "#jenlooper",
"img": "https://user-images.githubusercontent.com/41929050/61567053-13938600-aa33-11e9-9780-104fe4019659.png",
"description": "Create a web-connected light-strip API controllable from your website, using the Particle.io.",
"price": 867
},
{
"name": "sailorhg",
"img": "https://user-images.githubusercontent.com/41929050/61567054-13938600-aa33-11e9-9163-eec98e239b7a.png",
"description": "Visualization of sailor scouts sorted by bubblesort algorithm by their planet\u0027s distance from the sun",
"price": 71
},
{
"name": "sailorhg",
"img": "https://user-images.githubusercontent.com/41929050/61567055-142c1c80-aa33-11e9-96ff-9fbac6413625.png",
"description": "Light-up corsage I made with my summer intern.",
"price": 456
},
],
};
new Vue({
el: '#app',
data: data
})
</script>
</body>
try it this way, with a container div#app and data as a function, you can verify here: https://jsfiddle.net/boilerplate/vue
<body>
<div id="app">
<div v-for="(item, i) in products" :key="i">
<img :src="item.img" :alt="item.img" style="width: 250px; height:250px">
<h1>{{item.name}}</h1>
<p>{{item.description}}</p>
<p>${{item.price}}.00</p>
</div>
</div>
<script>
var data = {
products: [
{
"name": "Bamboo Thermal Ski Coat",
"description": "You'll be the most environmentally friendly skier in this!",
"img": "https://hplussport.com/wp-content/uploads/2016/12/ski-coat_LYNDA_29940.jpg",
"price": 99
},
{
"name": "#jenlooper",
"img": "https://user-images.githubusercontent.com/41929050/61567048-13938600-aa33-11e9-9cfd-712191013192.jpeg",
"description": "This project is a good learning project to get comfortable with soldering and programming an Arduino.",
"price": 5
},
{
"name": "jenlooper",
"img": "https://user-images.githubusercontent.com/41929050/61567049-13938600-aa33-11e9-9c69-a4184bf8e524.jpeg",
"description": "Use craft items you have around the house, plus two LEDs and a LilyPad battery holder, to create a useful book light for reading in the dark.",
"price": 63
},
{
"name": "#jenlooper",
"img": "https://user-images.githubusercontent.com/41929050/61567053-13938600-aa33-11e9-9780-104fe4019659.png",
"description": "Create a web-connected light-strip API controllable from your website, using the Particle.io.",
"price": 867
},
{
"name": "sailorhg",
"img": "https://user-images.githubusercontent.com/41929050/61567054-13938600-aa33-11e9-9163-eec98e239b7a.png",
"description": "Visualization of sailor scouts sorted by bubblesort algorithm by their planet\u0027s distance from the sun",
"price": 71
},
{
"name": "sailorhg",
"img": "https://user-images.githubusercontent.com/41929050/61567055-142c1c80-aa33-11e9-96ff-9fbac6413625.png",
"description": "Light-up corsage I made with my summer intern.",
"price": 456
},
],
};
new Vue({
el: '#app',
data() { return data }
})
</script>
</body>
just change you code
var data = { ... }
To
data() { return { product: [...] } }
and it will work.
in recent vue.js it is recommended to put 'v-key' when you use v-for, but it still works (no v-key is also ok when you run the program)
Creating a separate #app div and returning the data within a function works.
<div id="app">
<div v-for="(item, i) in products" :key="i">
<img :src="item.img" :alt="item.img" style="width: 250px; height:250px">
<h1>{{item.name}}</h1>
<p>{{item.description}}</p>
<p>${{item.price}}.00</p>
</div>
</div>
<script>
var data = {
products: [
{
"name": "Bamboo Thermal Ski Coat",
"description": "You'll be the most environmentally friendly skier in this!",
"img": "https://hplussport.com/wp-content/uploads/2016/12/ski-coat_LYNDA_29940.jpg",
"price": 99
},
{
"name": "#jenlooper",
"img": "https://user-images.githubusercontent.com/41929050/61567048-13938600-aa33-11e9-9cfd-712191013192.jpeg",
"description": "This project is a good learning project to get comfortable with soldering and programming an Arduino.",
"price": 5
},
{
"name": "jenlooper",
"img": "https://user-images.githubusercontent.com/41929050/61567049-13938600-aa33-11e9-9c69-a4184bf8e524.jpeg",
"description": "Use craft items you have around the house, plus two LEDs and a LilyPad battery holder, to create a useful book light for reading in the dark.",
"price": 63
},
{
"name": "#jenlooper",
"img": "https://user-images.githubusercontent.com/41929050/61567053-13938600-aa33-11e9-9780-104fe4019659.png",
"description": "Create a web-connected light-strip API controllable from your website, using the Particle.io.",
"price": 867
},
{
"name": "sailorhg",
"img": "https://user-images.githubusercontent.com/41929050/61567054-13938600-aa33-11e9-9163-eec98e239b7a.png",
"description": "Visualization of sailor scouts sorted by bubblesort algorithm by their planet\u0027s distance from the sun",
"price": 71
},
{
"name": "sailorhg",
"img": "https://user-images.githubusercontent.com/41929050/61567055-142c1c80-aa33-11e9-96ff-9fbac6413625.png",
"description": "Light-up corsage I made with my summer intern.",
"price": 456
},
],
};
new Vue({
el: '#app',
data() { return data }
})
</script>

Array still mapping even with no data

I have a website that is mapping the products it is displaying from a JSON file. The JSON looks like this.
"litter3": [
{
"name": "Bates",
"description": "Cute",
"image": "./puppies/boo/bates.jpg"
},
{
"name": "Blade",
"description": "This one is fiesty",
"image": "./puppies/boo/blade.jpg"
},
{
"name": "Blair",
"description": "Cute",
"image": "./puppies/boo/blair.jpg"
},
And so on.
The page is mapping in the following way:
{litter1.map((litter1) => (
<div className="col-sm-4" key={litter1.name}>
<img
className="homecard frame"
src={litter1.image}
alt={litter1.name}
/>
<h1 className="puppyname">{litter1.name}</h1>
<p className="puppysubtitle">{litter1.description}</p>
</div>
))}
This is working as intended. However when the JSON data is empty there is an issue.
"litter4": [
{
"name": "",
"description": "",
"image": ""
},
{
"name": "",
"description": "",
"image": ""
},
Ideally I want my client to be able to have these already formatted pieces of code that she can fill in when necessary, and leave blank when not necessary.
The issue is when the data is not there the page will still map the images.
How do I prevent this from happening when the data is not provided?
Is this possible, or is there another way to accomplish this?
Link to github repo
Thank you in advance for your help.
You can simply do a filter to the array before doing the map
litter1.filter(x=>x.title!=='').map((litter1) => (
You can have other conditions as well.

How to show a specific object in object array (Angular 5, TypeScript)

I have a data provider in Angular 5.
export class DataProvider {
location: any;
private locations: any[] = [
{
"name": "restaurant",
"location": "downtown",
"category": "restaurant",
"id": "1"
},
{
"name": "law firm",
"location": "center city",
"category": "office",
"id": "2"
},
{
"name": "public library",
"location": "suburb",
"category": "library",
"id": "3"
} ]
and here's my HTML file.
<div *ngFor="let location of locations">
<h1></h1>
<h2></h2>
</div>
In this scenario, how can I load a specific object (item) in data array with certain attributes?
For instance, If I want to load an object with "category" :"restaurant", what should I do on my HTML file? so the two others should not show up. I just want to load one out of three by using this specific attribute.
Thanks.
You need to access the attribute. You can use the following example
<div *ngFor="let location of locations">
<h1>{{location.name}}</h1>
<h2>{{location.category}}</h2>
</div>
EDIT
To filter depending on a category:
locationsFiltered = this.locations.filter(location =>location.category=="restaurant");
Now to make this example practical I will create a method to do it
filter(category : string) : any[] {
return this.locations.filter(location =>location.category==category);
}
then in html
<div *ngFor="let location of locationsFiltered">
<h1>{{location.name}}</h1>
<h2>{{location.category}}</h2>
</div>

Angular radio selection not checked correctly

In my Angular1.x app, my models maps to my radio selection correctly, however the radio button itself is not selected except for the very last one. Not really sure what the problem is. I created a very small example below to illustrate this behaviour. Any help is greatly appreciated.
http://plnkr.co/edit/dgGCvtOEb9WKTNtQHjqd?p=preview
angular.module('todoApp', [])
.controller('TodoListController', function() {
var todoList = this;
todoList.questions = [{
"category": "Movies",
"questions": [{
"title": "M1",
"score": "4",
},
{
"title": "M2",
"score": "2",
}
]
},
{
"category": "Foods",
"questions": [{
"title": "F1",
"score": "3",
},
{
"title": "F2",
"score": "4",
}
]
},
{
"category": "Sports",
"questions": [{
"title": "S1",
"score": "5",
}]
}
];
});
<!doctype html>
<html ng-app="todoApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<script src="todo.js"></script>
<link rel="stylesheet" href="todo.css">
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.0.4/css/bootstrap-combined.min.css">
</head>
<body>
<h2>Todo</h2>
<div ng-controller="TodoListController as todoList">
<div ng-repeat="(ccKey, cc) in todoList.questions">
<hr/>
<div>
<b style="color: red;">Category</b> : {{cc.category}}
</div>
<div ng-repeat="(qqKey, qq) in cc.questions">
<br/>
{{qq.title}} : Selected Score: {{qq.score}}
<br/>
<div ng-repeat="n in [].constructor(5) track by $index">
<input type="radio" ng-model="qq.score" name="q-{{ccKey}}-{{qqKey}}" value="{{$index+1}}"><br/>Score: {{$index+1}} : Group: q-{{ccKey}}-{{qqKey}}
</div>
</div>
</div>
</div>
</body>
</html>
Try removing the name attribute from your <input type="radio"> tag. This seems to be causing a conflict with what Angular is doing to manage your radio tags. I am able to see all categories selected, and the selections are still grouped within a given question.
In the Angular input[radio] docs, they do not show using a name attribute: https://docs.angularjs.org/api/ng/input/input%5Bradio%5D
If what you want is the initial selection of the values when the page first loads,then use
ng-value="($index+1).toString()"
Since your scores are given as strings, you need to convert the number to string to match the score when you use "ng-value". Or better, you can just set your scores as integers and leave the rest of the code unchanged:
todoList.questions = [{
"category": "Movies",
"questions": [{
"title": "M1",
"score": 4,
},
{
"title": "M2",
"score": 2,
}
]
}, ....
Here is a modified plunker

Output page blank while fetching data from JSON file in AngularJS

I have just started learning angularjs, I'm trying to load data from my json file on view. json file has a list of houses. But does not get showed on my view when I load the index.html file.
Data.json
[
{
"type": "Condo",
"price": 220000,
"address": "213 Grove Street",
"description": "Excellent place! Really nice view!"
},
{
"type": "House",
"price": 410500,
"address": "7823 Winding Way",
"description": "Beautiful home with lots of space for large family."
},
{
"type": "Duplex",
"price": 395000,
"address": "834 River Lane",
"description": "Great neighourhood and lot's of nice green space."
},
]
cribsFactory.js
angular
.module('ngCribs')
.factory('cribsFactory', function($http) {
function getCribs() {
return $http.get('data/data.json');
}
return {
getCribs: getCribs
}
});
cribsController.js
angular
.module('ngCribs')
.controller('cribsController', function($scope, cribsFactory) {
$scope.cribs;
cribsFactory.getCribs().success(function(data) {
$scope.cribs = data;
}).error(function(error) {
console.log(error);
});
});
index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>ng-cribbs</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
</head>
<body ng-app="ngCribs" ng-controller="cribsController">
<div class="well" ng-repeat="crib in cribs">
<h3>{{ crib.address }}</h3>
<p>
<strong>Type: </strong>{{ crib.type }}</p>
<p>
<strong>Description: </strong>{{ crib.description }}</p>
<p>
<strong>Price: </strong>{{ crib.price | currency }}</p>
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"/>
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.14.3/ui-bootstrap.min.js"/>
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.14.3/ui-bootstrap-tpls.min.js"/>
</script>
<script src="app.js"/>
</script>
<script src="scripts/cribsController.js"/>
</script>
<script src="scripts/cribsFactory.js"/>
</script>
</html>
I'm trying to run the above code in htdocs folder of XAMPP. The folder structure is in the screen shot below.
The json file is inside the data folder and the files cribsFactory.js & cribsController.js are in scripts folder. When i type the URL "http://localhost/ng-cribbs/" in Firefox the output is a completely blank page with no error message of any sort hence the difficulty in debugging.
I was able to load data using an array but facing problem while using JSON file.. Can't understand what I'm doing wrong. Please help!!
Your json data was not valid, validate any json data before and you can use the below corrected json. Hope it helps! validate json here
[{
"type": "Condo",
"price": 220000,
"address": "213 Grove Street",
"description": "Excellent place! Really nice view!"
}, {
"type": "House",
"price": 410500,
"address": "7823 Winding Way",
"description": "Beautiful home with lots of space for large family."
}, {
"type": "Duplex",
"price": 395000,
"address": "834 River Lane",
"description": "Great neighourhood and lot's of nice green space."
}]
Your http call gives you a json string, you should convert it to a javascript array like so: $scope.cribs = JSON.parse(data)

Categories