I have JSON data hundreds of entries like this:
{
"product":"Protec",
"type":"Central Opening",
"attribute":"Triple Lock",
"height":"2100",
"width":"1600",
"price":"3000"
},
{
"product":"Protec",
"type":"Sliding Door",
"attribute":"Single Lock",
"height":"2100",
"width":"1600",
"price":"3000"
},
{
"product":"ForceField",
"type":"Hinge Door",
"attribute":"Triple Lock",
"height":"2300",
"width":"1200",
"price":"100"
},
my vue component
var distinct_product = new Vue({
el: '#distinct',
data:{
distinct_product: [],
all_products: []
},
I fetch it and store it in my vue component and store it in a second data so when I render it to the ui the user only sees distinct elements.
mounted: async function(){
fetch("/Data/products.json")
.then(res => res.json())
.then(res => {
this.all_products = res
this.distinct_product = res
var disProduct = [...new Set(this.distinct_product.map(x => x.product))]
var disType = [...new Set(this.distinct_product.map(x => x.type))]
var disAttribute = [...new Set(this.distinct_product.map(x => x.attribute))]
this.distinct_product.productArray = disProduct;
this.distinct_product.typeArray = disType;
this.distinct_product.attributeArray = disAttribute;
My problem is, it also renders elements that aren't available to certain products.
for example a product : 'Window' can't have the attribute : 'triple locks'
I was wondering if I could filter/map the all_products array as the user selects a product.
I looked into computed properties mainly but I'm not sure of a good way to do it. this is my first attempt at a web app and I'm fairly new to JS too.
I aimed to iterate through the array pushing only objects containing the product selected in the UI
atm this is what I've attempted with no luck:
this.distinct_product.product which is bound to the UI
for (var i = 0; i < this.all_products.length; i++){
if (this.all_products[i] === this.distinct_product.product){
this.product.push(i);
return this.product;
}
}
so it would iterate over all_products looking for objects containing this.distinct_product.product which would contain 'Protec' or another product
Am I going at this the wrong way? should I step back in general and try and work with that data a different way?
Sorry if the question is structured poorly it's a skill I'm trying to work on, criticism is welcomed.
You are on the right track. I'll share a simple example so you can understand and make changes to your code accordingly.
var productdata = [
{
"product": "Protec",
"type": "Central Opening",
"attribute": "Triple Lock",
"height": "2100",
"width": "1600",
"price": "3000"
},
{
"product": "Protec",
"type": "Sliding Door",
"attribute": "Single Lock",
"height": "2100",
"width": "1600",
"price": "3000"
},
{
"product": "ForceField",
"type": "Hinge Door",
"attribute": "Triple Lock",
"height": "2300",
"width": "1200",
"price": "100"
},
];
//setTimeout(function () {
distinct_productVue = new Vue({
el: '#distinct',
data: {
//selected: {},
distinct_products: [],
all_products: productdata.map(function (x, index) {
return { text: x.product, value: index + 1 };
}),
selected: '0'
},
computed: {
},
mounted: function () {
this.all_products.unshift({ text: 'Please select a product', value: 0 });
},
methods: {
getDistinctProduct: function () {
var self = this;
self.distinct_products = productdata.filter(function (x, index) {
if (x.product === self.all_products[self.selected].text) {
return { text: x.product, value: index };
}
else { return false; }
});
}
}
});
<html>
<head>
<script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.0/vue.min.js'></script>
</head>
<body>
<div id="distinct">
<select v-model="selected" v-on:change="getDistinctProduct">
<option v-for="option in all_products" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<!--<span>Selected: {{ selected }}</span>-->
<div v-show="selected != 0" style="margin-top:15px;">
<b>Available products</b>
<div v-for="pro in distinct_products" style="margin-top:15px;">
<div>product: {{pro.product}}</div>
<div>type: {{pro.type}}</div>
<div>attribute: {{pro.attribute}}</div>
<div>height: {{pro.height}}</div>
<div>width: {{pro.width}}</div>
<div>price: {{pro.price}}</div>
</div>
</div>
</div>
</body>
</html>
You will get results on the fusioncharts website if you search up what I asked, but it is not exactly what I am looking for.
I am querying data from a MySQL database, and putting this data into a fusion chart to display on my webpage. I want there to be 2 graphs on the same page, and when you click on one of the datapoints on the parent graph, the child graph will display the "drilled down" graph. How can I do this? As of right now I can press on the parent graph and it will open the child graph on a new webpage. This is the code for the home page with the parent graph. The file is named "dept.php".
<?php
/*Include the `fusioncharts.php` file that contains functions
to embed the charts.
*/
include("includes/fusioncharts.php");
// Establish a connection to the database. Variables defined before
$dbhandle = new mysqli($hostdb, $userdb, $passdb, $namedb);
// Render an error message, to avoid abrupt failure, if the database connection parameters are incorrect
if ($dbhandle->connect_error) {
exit("There was an error with your connection: ".$dbhandle->connect_error);
}
?>
<html>
<head>
<title>FusionCharts XT - Column 2D Chart - Data from a database</title>
<link rel="stylesheet" type="text/css" href="css/style.css" />
<!-- Include the `fusioncharts.js` file. This file is needed to render the chart. Ensure that the path to this JS file is correct. Otherwise, it may lead to JavaScript errors. -->
<script src="fusioncharts/js/fusioncharts.js"></script>
</head>
<body>
<?php
// Form the SQL query that returns the top 10 most populous countries
$strQuery = "SELECT Department, SUM(Quantity) AS Quantity FROM Scrap GROUP BY Department ORDER BY Department";
// Execute the query, or else return the error message.
$result = $dbhandle->query($strQuery) or exit("Error code ({$dbhandle->errno}): {$dbhandle->error}");
// If the query returns a valid response, prepare the JSON string
if ($result) {
// The `$arrData` array holds the chart attributes and data
$arrData = array(
"chart" => array(
"caption" => "Sample Chart",
"paletteColors" => "#0075c2",
"bgColor" => "#ffffff",
"borderAlpha"=> "20",
"canvasBorderAlpha"=> "0",
"usePlotGradientColor"=> "0",
"plotBorderAlpha"=> "10",
"showXAxisLine"=> "1",
"xAxisLineColor" => "#999999",
"showValues"=> "0",
"divlineColor" => "#999999",
"divLineIsDashed" => "1",
"showAlternateHGridColor" => "0"
)
);
$arrData["data"] = array();
// Push the data into the array
while($row = mysqli_fetch_array($result)) {
array_push($arrData["data"], array(
"label" => $row["Department"],
"value" => $row["Quantity"],
"link" => "deptDrillDown.php?Department=".$row["Department"]
)
);
}
/*JSON Encode the data to retrieve the string containing the JSON representation of the data in the array. */
$jsonEncodedData = json_encode($arrData);
/*Create an object for the column chart. Initialize this object using the FusionCharts PHP class constructor. The constructor is used to initialize
the chart type, chart id, width, height, the div id of the chart container, the data format, and the data source. */
$columnChart = new FusionCharts("column2D", "myFirstChart" , 600, 300, "chart-1", "json", $jsonEncodedData);
// Render the chart
$columnChart->render();
// Close the database connection
$dbhandle->close();
}
?>
<div id="chart-1"><!-- Fusion Charts will render here--></div>
</body>
</html>
And then here is the other page that contains the child graph. The file is named "deptDrillDown.php".
<?php
/* Include the `includes/fusioncharts.php` file that contains functions to embed the charts.*/
include("includes/fusioncharts.php");
// Establish a connection to the database. Variables defined earlier
$dbhandle = new mysqli($hostdb, $userdb, $passdb, $namedb);
/*Render an error message, to avoid abrupt failure, if the database connection parameters are incorrect */
if ($dbhandle->connect_error) {
exit("There was an error with your connection: ".$dbhandle->connect_error);
}
?>
<html>
<head>
<title>FusionCharts XT - Column 2D Chart</title>
<link rel="stylesheet" type="text/css" href="css/style.css" />
<!-- Include the `fusioncharts.js` file. This file is needed to render the chart. Ensure that the path to this JS file is correct. Otherwise, it may lead to JavaScript errors. -->
<script src="fusioncharts/js/fusioncharts.js"></script>
</head>
<body>
<?php
// Get the country code from the GET parameter
$countryCode = $_GET["Department"];
// Form the SQL query that returns the top 10 most populous cities in the selected country
$cityQuery = "SELECT ScrapDate, SUM(Quantity) AS Quantity FROM Scrap WHERE Department = ? GROUP BY ScrapDate ORDER BY ScrapDate";
// Prepare the query statement
$cityPrepStmt = $dbhandle->prepare($cityQuery);
// If there is an error in the statement, exit with an error message
if($cityPrepStmt === false) {
exit("Error while preparing the query to fetch data from City Table. ".$dbhandle->error);
}
// Bind the parameters to the query prepared
$cityPrepStmt->bind_param("s", $countryCode);
// Execute the query
$cityPrepStmt->execute();
// Get the results from the query executed
$cityResult = $cityPrepStmt->get_result();
// If the query returns a valid response, prepare the JSON string
if ($cityResult) {
/* Form the SQL query that will return the country name based on the country code. The result of the above query contains only the country code.
The country name is needed to be rendered as a caption for the chart that shows the 10 most populous cities */
$countryNameQuery = "SELECT ScrapDate FROM Scrap WHERE Department = ?";
// Prepare the query statement
$countryPrepStmt = $dbhandle->prepare($countryNameQuery);
// If there is an error in the statement, exit with an error message
if($countryPrepStmt === false) {
exit("Error while preparing the query to fetch data from Country Table. ".$dbhandle->error);
}
// Bind the parameters to the query prepared
$countryPrepStmt->bind_param("s", $countryCode);
// Execute the query
$countryPrepStmt->execute();
// Bind the country name to the variable `$countryName`
$countryPrepStmt->bind_result($countryName);
// Fetch the result from prepared statement
$countryPrepStmt->fetch();
// The `$arrData` array holds the chart attributes and data
$arrData = array(
"chart" => array(
"caption" => "Top 10 Most Populous Cities in ".$countryName,
"paletteColors" => "#0075c2",
"bgColor" => "#ffffff",
"borderAlpha"=> "20",
"canvasBorderAlpha"=> "0",
"usePlotGradientColor"=> "0",
"plotBorderAlpha"=> "10",
"showXAxisLine"=> "1",
"xAxisLineColor" => "#999999",
"showValues"=> "0",
"divlineColor" => "#999999",
"divLineIsDashed" => "1",
"showAlternateHGridColor" => "0"
)
);
$arrData["data"] = array();
// Push the data into the array
while($row = $cityResult->fetch_array()) {
array_push($arrData["data"], array(
"label" => $row["ScrapDate"],
"value" => $row["Quantity"]
)
);
}
/*JSON Encode the data to retrieve the string containing the JSON representation of the data in the array. */
$jsonEncodedData = json_encode($arrData);
/*Create an object for the column chart using the FusionCharts PHP class constructor. Syntax for the constructor is `FusionCharts("type of chart",
"unique chart id", "width of chart", "height of chart", "div id to render the chart", "data format", "data source")`.*/
$columnChart = new FusionCharts("column2D", "myFirstChart" , 600, 300, "chart-1", "json", $jsonEncodedData);
// Render the chart
$columnChart->render();
// Close the database connection
$dbhandle->close();
}
?>
Back
<div id="chart-1"><!-- Fusion Charts will render here--></div>
</body>
</html>
n number of charts can be rendered in a single page using FusionCharts.
Store their chart references, e.g. in an associative array.
Use the dataplotClick event to capture the event being generated by clicking on a data.
Inside the callback, use the setJSONData to update the child chart, one wanna update.
A dummy code for this would be:
FusionCharts.ready(function () {
var chart1 = new FusionCharts({
type: 'msstackedcolumn2d',
renderAt: 'chart-container1',
width: '550',
height: '350',
dataFormat: 'json',
dataSource: {
// enter the json data here
},
"events": {
"dataplotClick": function(eventObj, dataObj) {
/* so every time a dataClickEvent is being triggered from the data plot,
a new json `json2` is fetched from a sql query and
chart2 is updated with it.*/
chart2.setJSONData(json2);
}
}
}
}).render();
});
Couple of days back I created this fiddle, hope this becomes useful here too. Instead of doing a SQL query, here we have a generalised data, every time a click is made, it internally makes a function call, and creates a data dynamically out of it. Lot of function calls for making it entirely dynamic might make the code look complex. But the basic philosophy I shared in the dummy code avobe is the same here.
The snippet version for the code for a quick reference.Better to run the result in full page to check whats exactly happening.
function getData() {
var arr = [{
seriesname: "Book A",
data: [{
"label": "Paper",
"value": 100
}, {
"label": "Promotion",
"value": 150
}, {
"label": "Transportation",
"value": 175
}, {
"label": "Royality",
"value": 200
}, {
"label": "Printing",
"value": 250
}, {
"label": "Binding",
"value": 275
}]
}, {
seriesname: "Book B",
data: [{
"label": "Paper",
"value": 130
}, {
"label": "Promotion",
"value": 110
}, {
"label": "Transportation",
"value": 155
}, {
"label": "Royality",
"value": 250
}, {
"label": "Printing",
"value": 210
}, {
"label": "Binding",
"value": 215
}]
}, {
seriesname: "Book C",
data: [{
"label": "Paper",
"value": 70
}, {
"label": "Promotion",
"value": 180
}, {
"label": "Transportation",
"value": 125
}, {
"label": "Royality",
"value": 150
}, {
"label": "Printing",
"value": 290
}, {
"label": "Binding",
"value": 245
}]
}, {
seriesname: "Book D",
data: [{
"label": "Paper",
"value": 150
}, {
"label": "Promotion",
"value": 100
}, {
"label": "Transportation",
"value": 105
}, {
"label": "Royality",
"value": 125
}, {
"label": "Printing",
"value": 278
}, {
"label": "Binding",
"value": 235
}]
}, {
seriesname: "Book E",
data: [{
"label": "Paper",
"value": 60
}, {
"label": "Promotion",
"value": 250
}, {
"label": "Transportation",
"value": 115
}, {
"label": "Royality",
"value": 189
}, {
"label": "Printing",
"value": 190
}, {
"label": "Binding",
"value": 285
}]
}, {
seriesname: "Book F",
data: [{
"label": "Paper",
"value": 190
}, {
"label": "Promotion",
"value": 200
}, {
"label": "Transportation",
"value": 160
}, {
"label": "Royality",
"value": 148
}, {
"label": "Printing",
"value": 178
}, {
"label": "Binding",
"value": 295
}]
}];
return arr;
}
function getValues(componentName) {
var i,
j,
arr = getData(),
valueArr = [],
len1;
for (i = 0, len = arr.length; i < len; i += 1) {
for (j = 0, len1 = arr[i].data.length; j < len1; j += 1) {
if (arr[i].data[j].label === componentName) {
valueArr.push({
value: arr[i].data[j].value
});
break;
}
}
}
return [{
seriesname: componentName,
data: valueArr
}];
}
function getProducts(componentName) {
var arr = getData(),
productArr = [];
for (i = 0, len = arr.length; i < len; i += 1) {
for (j = 0; j < arr[i].data.length; j += 1) {
if (arr[i].data[j].label === componentName) {
productArr.push({
"label": arr[i].seriesname,
"value": arr[i].data[j].value
});
break;
}
}
}
return productArr;
}
function getComponents(label, value) {
var arr = getData(),
sum,
i,
j,
len,
len1,
obj =
componentArr = [];
if (label === undefined) {
label = true;
}
if (value === undefined) {
value = true;
}
for (i = 0, len = arr[0].data.length; i < len; i += 1) {
sum = 0;
obj = {};
for (j = 0, len1 = arr.length; j < len1; j += 1) {
sum += arr[j].data[i].value;
}
if (label) {
obj.label = arr[0].data[i].label;
}
if (value) {
obj.value = sum;
}
componentArr.push(obj);
}
return componentArr;
}
function getSeriesNames() {
var arr = getData(),
seriesName = [];
for (i = 0, len = arr.length; i < len; i += 1) {
seriesName.push({
"label": arr[i].seriesname
});
}
return seriesName;
}
function getMode() {
var e = document.getElementById("interaction");
return e.options[e.selectedIndex].value;
}
FusionCharts.ready(function() {
var lastClickedId = true;
var pieChart = new FusionCharts({
type: 'pie2d',
renderAt: 'pieContainer',
width: '600',
height: '400',
dataFormat: 'json',
dataSource: {
"chart": {
"caption": "Expenditures Incurred in Publishing a Book",
"subCaption": "Component-wise BreakUp",
"enableMultiSlicing": "0",
"bgcolor": "FFFFFF",
"showvalues": "1",
"showpercentvalues": "1",
"showborder": "0",
"showplotborder": "0",
"showlegend": "1",
"legendborder": "0",
"legendposition": "bottom",
"enablesmartlabels": "1",
"use3dlighting": "0",
"showshadow": "0",
"legendbgcolor": "#CCCCCC",
"legendbgalpha": "20",
"legendborderalpha": "0",
"legendshadow": "0",
"legendnumcolumns": "3",
"palettecolors": "#f8bd19,#e44a00,#008ee4,#33bdda,#6baa01,#583e78"
},
"data": getComponents()
},
"events": {
"dataplotClick": function(eventObj, dataObj) {
if (getMode() === 'pie') {
var json = stackedChart.getJSONData(),
categoryLabel = dataObj.categoryLabel;
json.chart.subCaption = "BreakUp of " + categoryLabel + " in different product";
json.categories[0].category = getSeriesNames();
json.dataset = getValues(dataObj.categoryLabel);
stackedChart.setJSONData(json);
}
}
}
}).render();
var stackedChart = new FusionCharts({
type: 'stackedBar2D',
renderAt: 'barContainer',
width: '600',
height: '400',
dataFormat: 'json',
dataSource: {
"chart": {
"bgcolor": "FFFFFF",
"outcnvbasefontcolor": "666666",
"caption": "Expenditures Incurred in Publishing a Book",
"subCaption": "Product-wise BreakUp",
"xaxisname": "Expenditures Cost",
"yaxisname": "Cost",
"numberprefix": "$",
"showvalues": "0",
"numvdivlines": "10",
"showalternatevgridcolor": "1",
"alternatevgridcolor": "e1f5ff",
"divlinecolor": "e1f5ff",
"vdivlinecolor": "e1f5ff",
"basefontcolor": "666666",
"tooltipbgcolor": "F3F3F3",
"tooltipbordercolor": "666666",
"canvasbordercolor": "666666",
"canvasborderthickness": "1",
"showplotborder": "1",
"plotfillalpha": "80",
"showborder": "0",
"legendbgcolor": "#CCCCCC",
"legendbgalpha": "20",
"legendborderalpha": "0",
"legendshadow": "0",
"legendnumcolumns": "3"
},
"categories": [{
"category": getComponents(true, false)
}],
"dataset": getData()
},
"events": {
"dataplotClick": function(eventObj, dataObj) {
if (getMode() === 'stackedBar') {
var JSON = pieChart.getJSONData(),
categoryLabel = dataObj.categoryLabel;
JSON.chart.subCaption = "BreakUp of " + categoryLabel + " in different product";
JSON.data = getProducts(categoryLabel);
pieChart.setJSONData(JSON);
pieChart.slicePlotItem(dataObj.datasetIndex);
}
}
}
}).render();
function resetFN() {
var json = pieChart.getJSONData();
json.chart.subCaption = "Component-wise BreakUp";
json.data = getComponents();
pieChart.setJSONData(json);
json = stackedChart.getJSONData();
json.chart.subCaption = "Product-wise BreakUp";
json.categories[0].category = getComponents(true, false);
json.dataset = getData();
stackedChart.setJSONData(json);
}
document.getElementById('reset').addEventListener('click', resetFN);
document.getElementById('interaction').addEventListener('change', resetFN);
});
h4 {
font-size: 20px;
margin-bottom: 10px
}
.intro {
margin: 0 auto;
background-color: #fff280;
padding: 15px
}
em {
font-style: italic
}
#interactionWrapper {
margin: 5px 10px;
}
button {
border: 1px solid #0b77bc;
background-color: #0d83ce;
color: #ffffff;
margin: 10px 0 0 15px;
padding: 5px 10px;
font-size: 14px;
cursor: pointer
}
.centerAlign {
text-align: center;
}
<script src="http://static.fusioncharts.com/code/latest/fusioncharts.js"></script>
<script src="http://static.fusioncharts.com/code/latest/themes/fusioncharts.theme.fint.js"></script>
<div class="intro">
<h4>Expenditures incurred while publishing books</h4>
<p><em>A company has 6 books to publish for this quater. The stacked chart shows component prices stacked as per different books. While the pie chart, shows the cumilative component price.</em></p>
<p>
<em>There are two interaction modes - namely "Interact in stacked chart" and "Interact in pie chart".On clicking in any plot on stacked chart, it shows the book-wise distribution of that component in the pie chart. Whereas on clicking the pie chart, for a component being clicked, it shows the book-wise distribution in the bar chart</em>
</p>
</div>
<div id="interactionWrapper">
<span>Interaction Mode:</span>
<span>
<select id="interaction">
<option value="stackedBar">Interact in stacked bar</option>
<option value="pie">Interact in the pie chart</option>
</select>
</span>
</div>
<div class="centerAlign">
<span id="barContainer">FusionCharts XT will load here!</span>
<span id="pieContainer">FusionCharts XT will load here!</span>
</div>
<button id="reset">Reset</button>
I am using KendoUI Scheduler control and here is initialization code
$("#Scheduler").kendoScheduler({
dataSource: [],
selectable: true,
height: 500,
editable: false,
eventTemplate: $("#event-template").html(),
views: [
"day",
{ type: "week", selected: true },
"month",
"agenda"
],
resources: [
{
field: "resourceviewid",
name: "ResourceViews",
dataColorField: "key",
dataSource: [
{ text: "Appointments", value: 1, key: "orange" },
{ text: "Delivery Specialist", value: 2, key: "blue" },
{ text: "Orientation Specialist", value: 3, key: "green" }
]
}
],
group: {
resources: ["ResourceViews"],
orientation: "horizontal"
}
});
Here "Appointments" group is default, it will be available always
I have check box in my screen
<div id="divResourceView">
<label><input checked type="checkbox" value="1" />Delivery Specialist</label>
<label><input checked type="checkbox" value="2" />Orientation Specialist</label>
</div>
On change event I wrote below code to get selected values from checkbox and updating GROUP datasource of KendoUI scheduler as below
$("#divResourceView :checkbox").change(function (e) {
var checked = $.map($("#divResourceView :checked"), function (checkbox) {
return parseInt($(checkbox).val());
});
});
var scheduler = $("#Scheduler").data("kendoScheduler");
var arrayOfStrings = checked.toString().split(",");
for (var i = 0; i < arrayOfStrings.length; i++)
{
if(arrayOfStrings[i] == 1)
{
var data = [{ text: "Delivery Specialist", value: 2, color: "blue" }];
scheduler.resources[1].dataSource.data(data);
}
if (arrayOfStrings[i] == 2) {
var data = [{ text: "Orientation Specialist", value: 3, color: "green" }];
scheduler.resources[2].dataSource.data(data);
}
}
scheduler.refresh();
But it removes all groups and add only one. I want to see both groups when arrayOfStrings has values "1,2",
I can see all groups during initialization But it disappears when i check the check box.
Images for reference
During Initialization
After
As you can see clearly, Delivery Specialist is missing in scheduler control
Found some link: http://www.telerik.com/forums/add-filter-to-resource-datasource
But not sure what they talking about? seems like refresh issue.
I have done this I believe you're right and your issue is to do with refreshing, I use the following to refresh it.
var scheduler = $("#scheduler").data("kendoScheduler");
scheduler.view(scheduler.view().name);
hope this helps through it is stupidly late (I'm currently looking up how to do this lazerly
I am trying to populate a JQM ListView with a local JSON information. However, no list items are created. Any help would be appreciated. Here is my code:
JSON File Structure:
[
{
"name" : "test"
"calories" : "1000"
"fat" : "100"
"protein" : "100"
"carbohydrates" : "800"
},
{
"name" : "test2"
"calories" : "10000"
"fat" : "343"
"protein" : "3434"
"carbohydrates" : "4343"
}
]
HTML:
<div data-role="page" data-title="Search" id="searchPage">
<ul data-role="listview" data-inset="true" id="searchFood">
</ul>
</div>
JS:
(Updated)
$(document).on("pageinit", "#searchPage", function(){
$.getJSON("../JS/food.json", function(data){
var output = '';
$.each(data, function(index, value){
output += '<li>' +data.name+ '</li>';
});
$('#searchFood').html(output).listview("refresh");
});
});
First of all, the return JSON array is wrong, values (properties) should be separated by commas.
var data = [{
"name": "test",
"calories": "1000",
"fat": "100",
"protein": "100",
"carbohydrates": "800",
}, {
"name": "test2",
"calories": "10000",
"fat": "343",
"protein": "3434",
"carbohydrates": "4343",
}];
Second mistake, you should read value object returned by $.each() function not data array.
$.each(data, function (index, value) {
output += '<li>' + value.name + '</li>';
});
jQueryMobile only enhances the page once when it is loaded. When new data is added dynamically to the page, jQueryMobile must be made aware of the data for the data to be enhanced.
After extracting data from JSON array, append them then refresh listview to restyle newly added elements.
$('#searchFood').html(output).listview("refresh");
Demo
I have this problem with my JSON file.
{"results" :[{
"name" : "name1",
"type" :[{
"id" : '2',
},{
"id" : '1',
},{
"id" : '4',
},{
"id" : '6',
}],
}],
"images" :[{
"url" : "url0",
},{
"url" : "url1",
},{
"url" : "url2",
},{
"url" : "url3",
},{
"url" : "url4",
}],
},{
"name" : "name2",
"type" :[{
{
"id" : '25',
},{
"id" : '123',
},{
"id" : '423',
},{
"id" : '346',
}],
"images" :[{
"url" : "url0",
},{
"url" : "url1",
},
{
"url" : "url2",
},
{
"url" : "url3",
},{
"url" : "url4",
}],
},
},{
"name" : "name3",
"type" : null,
"images" :null,
},.....
]}
the JSON object looks like this
When i loop through the it kicks me out when it comes to the null
for(var i = 0; i < results.length; i++){
$('.results')append('<p class="liste">'+results[i].name+'</p><ul></ul>');
$('.liste').prepend('<img src="'+results[i].images[1].url+'"');
for(var j = 0; j < results[i].type.length; j++){
$('.results ul').append('<li>'+results[i].type[j].id+'</li>');
}
}
the result should look somewhat like this
<div class="results">
<img src="url1"><p>name1</p>
<ul>
<li>2</li>
<li>1</li>
<li>4</li>
<li>6</li>
</ul>
<img src="url1"><p>name2</p>
<ul>
</ul>
<img src="url1"><p>name3</p>
<ul>
<li>25</li>
<li>123</li>
<li>423</li>
<li>346</li>
</ul>
</div>
i tryed
if(results[i].images != null){
$('.liste').prepend('<img src="'+results[i].images[1].url+'">');
}else{
$('.liste').prepend('<img src="some default image" width="170" height="170">');
}
if(results[i].type != null){
for (var j = 0; j < results[i].type.length.length; j++) {
$('.album').append('<li>'+[i]+'-'+[j]+'-'+results[i].type.length[j].id+'</li>');
};
it gehts really messy the image comes for every [i] and the first [k] appears as it suppose to be as well as last [k] in in the pre. [i]
[i][j]
name1
[0][0]
[0][1]
[0][2]
[0][3]
[1][0]
name2
[1][0]
......
I hope some one can help me with that
EDIT
I forgot every "type" is listed under each name.
The JSON you provided is invalid, but, assuming the JSON looks like this (based on your current iteration code):
var results = [{
"name": "name1",
"type": [{ "id": '2'},
{ "id": '1'},
{ "id": '4'},
{ "id": '6'}],
"images": [{ "url": "url0" },
{ "url": "url1" },
{ "url": "url2" },
{ "url": "url3" },
{ "url": "url4" }],
}, {
"name": "name2",
"type": [{ "id": '25' },
{ "id": '123' },
{ "id": '423' },
{ "id": '346' }],
"images": [{ "url": "url0" },
{ "url": "url1" },
{ "url": "url2" },
{ "url": "url3" },
{ "url": "url4" }],
}, {
"name": "name3",
"type": null,
"images": null
}];
You have several problems with this statement:
for(var i = 0; i < results.length; i++){
$('.results')append('<p class="liste">'+results[i].name+'</p><ul></ul>');
$('.liste').prepend('<img src="'+results[i].images[1].url+'"');
for(var j = 0; j < results[i].type.length; j++){
$('.results ul').append('<li>'+results[i].type[j].id+'</li>');
}
}
$('.liste').prepend will append the provided element to ALL elements with a class of .liste. Each time you prepend a new image, all existing <p> elements will get it.
$('.results ul').append - see above comment. Each time you append, all existing elements that match will get additional, unwanted values attached
Both the type and images values can be null and you haven't provided any guards against this in your loop.
Something like this given the assumption above will work better for you:
Demo Fiddle
Code:
// Use a document fragment to avoid DOM updates in the loop
var $fragment = $(document.createDocumentFragment());
for (var i = 0; i < results.length; i++) {
// If there is an image, add it
if(results[i].images) {
$fragment.append($('<img src="' + results[i].images[1].url + '"/>'));
}
$fragment.append($('<p class="liste">' + results[i].name + '</p>'));
// Keep track of the current UL so it can be appended to directly
var $curULTag = $('<ul></ul>').appendTo($fragment);
if(results[i].images && results[i].type) {
for (var j = 0; j < results[i].type.length; j++) {
// add the li to the current UL
$curULTag.append('<li>' + results[i].type[j].id + '</li>');
}
}
}
// Append the full results
$('.results').append($fragment);
Results:
<div class="results">
<img src="url1">
<p class="liste">name1</p>
<ul>
<li>2</li>
<li>1</li>
<li>4</li>
<li>6</li>
</ul>
<img src="url1">
<p class="liste">name2</p>
<ul>
<li>25</li>
<li>123</li>
<li>423</li>
<li>346</li>
</ul>
<p class="liste">name3</p>
<ul></ul>
</div>
If my assumption about the JSON structure you provided isn't correct, you can adjust the above code to provide the results you need.
Start off with a more clear code structure so you don't get lost too fast...
if (jsonData.results)
{
$.each(jsonData.results, function(obj)
{
// process obj.name if exists
// process obj.type if exists
});
}
Do you see any error messages in the console?