django vue js & Highcharts asynchronously fetching data from JSON - javascript

I'm currently Using django,highcharts, and JQuery to build a simple data visualization web app. I just moved from JQuery to Vue Js and I'm confused on how vue js to fetch JSON data from certain url. Here is my code:
Template
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Django Highcharts Example</title>
</head>
<body>
<div id="container" data-url="{% url 'async_chart_data' %}"></div>
<script src="https://code.highcharts.com/highcharts.src.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
$.ajax({
url: $("#container").attr("data-url"),
dataType: 'json',
success: function (data) {
Highcharts.chart("container", data);
}
});
</script>
</body>
</html>
Views.py
def chart_view(request):
return render(request,'chart.html')
def chart_data(request):
dataset = Passenger.objects.values('embarked')\
.exclude(embarked='')\
.annotate(total=Count('embarked'))\
.order_by('embarked')
port_name = dict()
for choices_tuple in Passenger.PORT_CHOICES:
port_name[choices_tuple[0]] = choices_tuple[1]
#Hicharts visualization config
pie_chart = {
'chart' : {'type':'pie'},
'title' : {'text' : 'PELABUHAN'},
'series': [{
'name' : 'Tempat Berangkat',
'data' : list(map(lambda row: {'name' : port_name[row['embarked']],
'y' : row['total']},dataset))
}]
}
return JsonResponse(pie_chart)
Models.py
from django.db import models
class Passenger(models.Model):
MALE = 'M'
FEMALE = 'F'
SEX_CHOICES = (
(MALE, 'male'),
(FEMALE, 'female')
)
CHERBOURG = 'C'
QUEENSTOWN = 'Q'
SOUTHAMPTON = 'S'
PORT_CHOICES = (
(CHERBOURG, 'Cherbourg'),
(QUEENSTOWN, 'Queenstown'),
(SOUTHAMPTON, 'Southampton'),
)
name = models.CharField(max_length=100, blank=True)
sex = models.CharField(max_length=1, choices=SEX_CHOICES)
survived = models.BooleanField()
age = models.FloatField(null=True)
ticket_class = models.PositiveSmallIntegerField()
embarked = models.CharField(max_length=1, choices=PORT_CHOICES)
def __str__(self):
return self.name
I wanna change the JQuery usage to fetch the JSON data to Vue JS. How I can do it ?
EDIT: i'M already done with this issue. I'm run to another issue on Here

Case is closed. I'm able to achieve it by playing with vue js life cycle hooks. However it still slow enough to load the page. need(4 to 7 seconds) but it works. Here is my template.
<!DOCTYPE html>
<html>
<head>
<title>Using Vue Axios</title>
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://code.highcharts.com/highcharts.src.js"></script>
</head>
<body>
<div id="app">[[dataTitanic]]</div>
<h1>The Chart Is Shown Below : </h1>
<div id="container"></div>
<script type="text/javascript">
var url = "{% url 'async_chart_data' %}";
var app = new Vue({
delimiters : ['[[',']]'],
el : '#app',
data(){
return {
dataTitanic : null,
}
},
mounted(){
axios
.get(url)
.then(response => (this.dataTitanic = response['data']))
},
beforeUpdate(){
Highcharts.chart('container',this.dataTitanic)
}
})
</script>
</body>
</html>

Related

Why v-for won't render any DOMs? 'Property or method "data" is not defined on the instance but referenced during render.'

I would like to render several div containers depending on a returned API call from axios/vue. The axios call and callback work just fine, but vue won't render any divs.
Since I am using Django, I already changed the delimiters from curly brackets (which is Django default as well).
Error message in console:
Property or method "data" is not defined on the instance but referenced during render.
Make sure that this property is reactive, either in the data option,
or for class-based components, by initializing the property.
Please find a minimal code snippet as follows (if you remove the JS part the html will show up):
Thank you in advance for your help!
var app = new Vue({
delimiters: ['[[', ']]'],
el: '.EUR_Quotes',
data: {
info: []
},
created() {
axios
.get("http://data.fixer.io/api/latest?access_key=XXXd&base=EUR")
.then(response => {
this.info = response.data.rates;
console.log(response);
});
}
});
.EUR_Quotes {
font-size: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<html>
<head>
</head>
<body>
<div v-for="rates in info">
<div class="EUR_Quotes">[[ data ]]
</div>
</div>
</body>
<script src="https://unpkg.com/vue#2.5.13/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</html>
You are confusing your data variable name, it should be info in your template, (not data) the actual data object is the container for all your vuejs app's data.
Check the snippet, it works fine.
var app = new Vue({
delimiters: ['[[', ']]'],
el: '.EUR_Quotes',
data: {
info: []
},
created() {
axios
.get("http://data.fixer.io/api/latest?access_key=d&base=EUR")
.then(response => {
this.info = response.data.rates;
console.log(response);
});
}
});
.EUR_Quotes {
font-size: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<html>
<head>
</head>
<body>
<div v-for="rates in info">
<div class="EUR_Quotes">[[ info ]]
</div>
</div>
</body>
<script src="https://unpkg.com/vue#2.5.13/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</html>

Can't find any recursion in my file that causes Uncaught RangeError: Maximum call stack exceeded

Heres my HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../resources/js/jquery-3.2.0.min.js"></script>
<script src="../resources/select2-4.0.3/dist/js/select2.min.js"></script>
<link href="../resources/select2-4.0.3/dist/css/select2.min.css" type="text/css" rel="stylesheet">
<script src="../resources/d3/d3.min.js"></script>
<script src="../resources/d3/d3.button.js"></script>
<script src="js/script.js"></script>
<link href="css/style.css" type="text/css" rel="stylesheet">
<title>Database Heat Map</title>
</head>
<body>
<div id="head">
<h1>Database Heat Map</h1>
<div>
<div>
<h3>Schema</h3>
<select class="js-example-basic-single" name="schema" id="schema">
<option></option>
</select>
</div>
<div>
<h3>Table</h3>
<select class="js-example-basic-single" name="table" id="table">
</select>
</div>
</div>
</div>
</body>
</html>
The way that my select boxes are set up is that the second select box populates depending on what is selected in the first. Each Schema in the first drop down has their own sets of unique tables.
Here's my JavaScript/Jquery:
$(document).ready(function () {//Load in json file using d3
getSchema();
$("#schema").change(function() {
var e = document.getElementById("schema");
var selectedSchema = e.options[e.selectedIndex].value;
console.log(selectedSchema)
if (selectedSchema != "") {
getTable(schema);
}
})
function getSchema() {
$.ajax({
url: "heatmap.py",
dataType: "json",
data: {get: "schema"},
success: function(results) {
console.log(results);
populateSchemaDropDown(results);
},
error: function() {
console.log("schema error");
}
})
}
function getTable(schema) {
$.ajax({
url: "heatmap.py",
dataType: "json",
data: {findTables: schema},
success: function(results) {
console.log(results);
},
error: function() {
console.log("table error")
}
})
}
function populateSchemaDropDown(schema) {
$('#schema').select2({
placeholder: "--Select One--",
allowClear: true,
data: schema,
dropdownAutoWidth: true
})
}
function populateTableDropDown(table) {
$("#table").select2({
placeholder: "--Select One--",
allowClear: true,
disabled: true
})
}
The first dropdown box populates just fine, but whenever I click an option, it logs the name of the option like it's supposed to but I keep getting an Uncaught RangeError: Maximum call stack size exceeded error from jquery
Here is the python file as well (ignore indent syntax, it's not pasting correctly):
def getSchema():
historicalRefreshStats = json.load(open(os.path.join(scriptDir, "historicalRefreshStats.json")))
schemas = []
for server in historicalRefreshStats:
currentServer = unicodedata.normalize('NFKD', server).encode('ascii', 'ignore')
for schema in historicalRefreshStats[currentServer]:
currentSchema = unicodedata.normalize('NFKD', schema).encode('ascii', 'ignore')
schemas.append(currentSchema)
return sorted(list(set(schemas)))
def getTables(schemaToFind):
historicalRefreshStats = json.load(open(os.path.join(scriptDir, "historicalRefreshStats.json")))
tables = []
for server in historicalRefreshStats:
currentServer = unicodedata.normalize('NFKD', server).encode('ascii', 'ignore')
for schema in historicalRefreshStats[currentServer]:
currentSchema = unicodedata.normalize('NFKD', schema).encode('ascii', 'ignore')
if schemaToFind == currentSchema:
for table in historicalRefreshStats[currentServer][currentSchema]:
tables.append(table)
return sorted(list(set(tables)))
form = cgi.FieldStorage()
if "get" in form:
schemas = getSchema()
print "Content-Type: text/json; charset=ISO-8859-1\n"
print json.dumps(schemas)
elif "findTables" in form:
schema = form["findTables"]
tables = getTables(schema)
print "Content-Type: text/json; charset=ISO-8859-1\n"
print json.dumps(tables)
else:
print "Content-Type: text/json; charset=ISO-8859-1\n"
print json.dumps("error")
Any help is appreciated! I don't think it's doing anything recursively and I checked to make sure it wasn't the python response that was triggering the error. But it must be recursive if I'm getting the error, right?
Your calling getTable(schema) but schema is not defined, it should be selectedSchema, you also don't need that much code things could be a lot shorter, "less code = less problems"
like the change function for example: https://fiddle.jshell.net/____mmc/znqxaa2h/
$("#schema").change(function() {
let selectedItem = $('#schema').select2('data')[0]
....
})
and the ajax call, you could embed the call in select2 https://select2.org/data-sources/ajax

VueJS api call leaving data undefined

I am learning VueJS 2.0 and I am connecting to an API where I want the value of some data to change on input change. Here is what the output says using the dev tools:
canadianDollar:undefined
europeanEuro:undefined
europeanPound:undefined
usd:"1232"
Whenever I put 1232 in the USD input field it doesn't return anything and leaves those properties as undefined. Here is the code.
new Vue({
el: '#app',
data: {
usd: '',
canadianDollar: '',
europeanPound: '',
europeanEuro: ''
},
// Watch methods
watch: {
usd: function() {
this.convertCurrency()
}
},
// Logic Methods
methods: {
convertCurrency: _.debounce(function() {
var app = this;
if (app.usd.length !== 0) {
// Show that the things are loading in.
app.canadianDollar = 'Searching...'
app.europeanPound = 'Searching...'
app.europeanEuro = 'Searching...'
console.log(app.usd)
axios.get("http://api.fixer.io/latest?base=USD&" + app.usd)
.then(function(response) {
app.canadianDollar = response.data.CAD
app.europeanPound = response.data.GBP
app.europeanEuro = response.data.EUR
})
.catch(function(error){
app.canadianDollar = "ERROR"
app.europeanPound = "ERROR"
app.europeanEuro = "ERROR"
})
}
}, 500)
}
})
and the HTML:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Vue</title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" name="" value="" v-model="usd">
<ul>
<li>Canadian Dollar: {{canadianDollar}}</li>
<li>European Pound: {{europeanPound}}</li>
<li>European Euro: {{europeanEuro}}</li>
</ul>
</div>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js" charset="utf-8"></script>
<script src="index.js" charset="utf-8"></script>
</body>
</html>
When I type in a number it does give me the "Searching" part but disappears and nothing shows up.
I would recommend changing
then(function(response) {
app.canadianDollar = response.data.CAD
app.europeanPound = response.data.GBP
app.europeanEuro = response.data.EUR
})
to
then(function(response) {
console.log(response);
})
that was you can see what is being returned.
Also, axios.get("http://api.fixer.io/latest?base=USD&" + app.usd) should probably have a name like vulue:axios.get("http://api.fixer.io/latest?base=USD&VALUE=" + app.usd), but you'll have to check their api to see what it is meant to be called.
...
response.data.rates.CAD;
you have
response.data.CAD;
...
app.canadianDollar = response.data.rates.CAD * app.usd;

Selection in first drop down populates data in second dropdown but only on first click, why?

I have 2 drop downs where selection of first drop down effects the data content of the second drop down.
The problem I have is this functionality is occurring only on first click instead it should happen every time.
Here is my jsFiddle with my working code and here is my code on jsbin(jsbin gives some error which I am unable to understand, help appreciated here too, #newbieTorture).
Thanks in Advance :)
App = Ember.Application.create();
App.Router.map(function() {
// put your routes here
});
App.ArticleAdapter= DS.FixtureAdapter.extend({});
App.Article =DS.Model.extend({
title: DS.attr(),
body: DS.attr(),
shouldReloadAll:true,
comments: DS.hasMany('comment', {async : true})
//async tells compiler to load data from comment everytime this is rendered
});
App.Comment =DS.Model.extend({
text: DS.attr(),
shouldReloadAll:true,
article: DS.belongsTo('article', { async: true })
});
App.Article.FIXTURES=[
{
id:1,
title : 'Ember',
body:'Its a great technology but need lot of studying and practice',
comments:[1]
},{
id:2,
title : 'Angular',
body:'it takes less understanding but has more coding the ember',
comments:[2,3]
//this will be an aray coz it is has many relation
}
];
App.Comment.FIXTURES=[
{
id:1,
text : 'Yyyieee excited to learn ember',
aricle: 1
//its not an array coz it will be related to single object
},{
id:2,
text : 'I will start Angular once i have fininshed with ember',
article: 2
},{
id:3,
text : 'Angular can be interesting',
article: 2
}
];
App.CommentAdapter= DS.FixtureAdapter.extend();
App.IndexController = Ember.ArrayController.extend({
articleValue: null,
selected: null,
articleStore: Em.computed(function(){
console.log("data is : " + this.get('articleValue'));
console.log("data is : " + this.get('selected'));
return this.store.findAll("article");
}).property("selected"),
availableComment: Em.computed(function () {
var make = this.get('selected');
// the line below returns the id and not an object
console.log(make);
if (make === undefined || make === null)
return [];
return this.get('selected').get('comments');
}).property('articleValue'),
actions:{
callIndexController: function(){
var select= this.get("selected");
console.log("hi :" + select);
}
}
});
App.IndexRoute = Ember.Route.extend({
model: function() {
return [];
},
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ember Starter Kit</title>
</head>
<body>
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" id="index">
First drop down:
{{
view "select"
contentBinding=articleStore
optionLabelPath="content.title"
optionValuePath="content.id"
prompt="Pick a person:"
shouldReloadAll=true
selectionBinding=selected
valueBinding=articleValue
}}
<br>
<br>
Second drop down:
{{
view "select"
contentBinding=availableComment
optionLabelPath="content.text"
optionValuePath="content.id"
prompt="related task:"
shouldReloadAll=true
valueBinding=articleValue
}}
</script>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<script src="http://builds.emberjs.com/tags/v1.13.7/ember-template-compiler.js"></script>
<script src="http://builds.emberjs.com/tags/v1.13.7/ember.debug.js"></script>
<script src="http://builds.emberjs.com/tags/v1.13.7/ember-data.js"></script>
<script src="js/amit_dropdown.js"></script>
<!-- to activate the test runner, add the "?test" query string parameter -->
<script src="tests/runner.js"></script>
</body>
</html>

Rendering coordinates on leaflet map view using ajax in ember

[]I am trying to feed data (via an ajax call to a json file) to both a handlebars template and a leaflet map. With my current setup, the data reaches my handlebars template just fine, but doesn't render the coordinates data to the leaflet map. I suspect I am missing some basic piece of the ember.js puzzle. Would someone please advise me?
HTML/Handlebars Templates:
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, minimal-ui">
<title>sbk_3.0.8</title>
<link rel="stylesheet" href="css/leaflet.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<script type="text/x-handlebars" data-template-name="application">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
{{view App.MapView id="map" contentBinding="this"}}
<div id="blog">
<ul>
{{#each item in model}}
<li>{{item.headline}}</li>
{{/each}}
</ul>
</div>
</script>
<!--DEPENDENCIES-->
<script src="js/libs/jquery-1.10.2.min.js"></script>
<script src="js/libs/handlebars-1.0.0.js"></script>
<script src="js/libs/ember.js"></script>
<!--MAP-->
<script src="js/libs/leaflet-src.js"></script>
<script src="js/libs/ember-leaflet.min.js"></script>
<!--APP-->
<script src="js/application.js"></script>
</body>
</html>
Ember:
App = Ember.Application.create();
App.Router.map(function() {
// put your routes here
});
App.IndexRoute = Ember.Route.extend({
model: function(){
return App.Item.all();
}
});
App.Item = Ember.Object.extend();
App.Item.reopenClass({
all: function() {
return $.getJSON("js/data/test_e.json").then(function(response) {
var items = [];
response.features.forEach( function (data) {
items.push( App.Item.create(data) );
});
return items;
});
}
});
App.MapView = Ember.View.extend({
didInsertElement: function () {
var map = L.map('map', {zoomControl: false}).setView([40.685259, -73.977664], 14);
L.tileLayer('http://{s}.tile.cloudmade.com/[redacted key]/[redacted id]/256/{z}/{x}/{y}.png').addTo(map);
console.log(this.get('content'));
//HERE IS WHERE I GET STUCK. I CAN OUTPUT THE JSON TO THE CONSOLE...
//BUT HOW DO I DRILL DOWN, AND ULTIMATELY...
//HOW DO I SEND THE VALUE OF THE "CENTER" KEY TO LEAFLET, i.e. L.Marker([jsonObject.center]).addTo(map);
}
});
App.IndexController =
Ember.Controller.extend({});
JSON:
{
"features": [
{
"headline": "Docker, the Linux container runtime: now open-source",
"center" : [40.685259, -73.977664]
},
{
"headline": "What's Actually Wrong with Yahoo's Purchase of Summly",
"center" : [40.685259, -73.977664]
}
]
}
This is the same answer as the other question,
The view is backed by a controller, so you would do this.get('controller') to get the controller which is backed by your collection which if you wanted to get the collection (which isn't necessary since you can iterate the controller) you could do this.get('controller.model').
var controller = this.get('controller');
controller.forEach(function(item){
console.log(item.get('title'));
});
http://emberjs.jsbin.com/OxIDiVU/373/edit

Categories