VueJS api call leaving data undefined - javascript

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;

Related

how to add vue output inside input value=""

I have this code which output some values according to my users location and I want to display this values, On input but when I use <input value="{{useragent}}" /> it is just displaying {{useragent}} not the output.
<!DOCTYPE html>
<html lang="en">
<head> </head>
<body translate="no">
<div id="app">
<p>{{useragent}}</p>
<p>{{tsFormatted}}</p>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>
<script id="rendered-js">
new Vue({
el: "#app",
data() {
return {
response: null,
ip: null,
useragent: null,
ts: null,
};
},
watch: {
// This should do a substring of the result returned by CloudFlare
response: function () {
this.ip = this.response.substring(this.response.search("ip=") + 3, this.response.search("ts="));
this.ts = this.response.substring(this.response.search("ts=") + 3, this.response.search("visit_scheme="));
this.useragent = this.response.substring(this.response.search("uag=") + 4, this.response.search("colo="));
},
},
computed: {
tsFormatted() {
return new Date(this.ts * 1000);
},
},
mounted() {
// Get the user's states from the cloudflare service
axios.get("https://www.cloudflare.com/cdn-cgi/trace").then((response) => (this.response = response.data));
},
});
//# sourceURL=pen.js
</script>
</body>
</html>
how can I display this {{values}} inside HTML <input> tag ?
When dealing with inputs, if you want useragent to fill the input field then use v-model instead of value
<input v-model="useragent" />
You can read more about it from Vue 2 DOCs: https://v2.vuejs.org/v2/guide/forms.html
You need to bind values :value or v-bind:value:
<!DOCTYPE html>
<html lang="en">
<head> </head>
<body translate="no">
<div id="app">
<input :value="useragent" />
<input v-bind:value="tsFormatted" />
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>
<script id="rendered-js">
new Vue({
el: "#app",
data() {
return {
response: null,
ip: null,
useragent: null,
ts: null,
};
},
watch: {
// This should do a substring of the result returned by CloudFlare
response: function () {
this.ip = this.response.substring(this.response.search("ip=") + 3, this.response.search("ts="));
this.ts = this.response.substring(this.response.search("ts=") + 3, this.response.search("visit_scheme="));
this.useragent = this.response.substring(this.response.search("uag=") + 4, this.response.search("colo="));
},
},
computed: {
tsFormatted() {
return new Date(this.ts * 1000);
},
},
mounted() {
// Get the user's states from the cloudflare service
axios.get("https://www.cloudflare.com/cdn-cgi/trace").then((response) => (this.response = response.data));
},
});
//# sourceURL=pen.js
</script>
</body>
</html>
<input type="text" :value="useragent" />
or
<input type="text" v-model="useragent" />
vue Form Input Bindings doc
Before went to the solution, I have a question to you - Do you want one-way or two-way data binding for your input ?
If you will use :value, It will work as a one-way data binding and will just update the input value but if you will make any changes in your input it will not modify the model/variable.
If you will use v-model, It will work as a two way data binding and will update both input as well as model/variable if any changes happen at any end.
Live Demo :
new Vue({
el:'#app',
data:{
name:'Alpha'
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.4/vue.js"></script>
<div id="app">
<div>One Way binding <input type="text" :value="name"/></div>
<div>Two way binding : <input type="text" v-model="name"/> </div>
<div>Result : {{name}}</div>
</div>

Mixpanel mock continuously comes back as undefined

I have a very basic static app that has business logic to redirect a user based on what element they click in the UI. I added Mixpanel, and track an event before the user is redirected. I'm trying to create tests using the Jest testing framework, but am having difficulties mocking the track method invocation on mixpanel.
The crux of the issue is I'm unable to mock mixpanel while running tests. I've read the Jest documentation and searched the community for answers, but every time I run tests, it fails with TypeError: Cannot read property 'track' of undefined. You'll have to forgive me if it is something obvious, JavaScript is not my native programming language, so when it comes time to build tests, I'm rusty at it. :)
index.html
<!doctype html>
<html class="no-js" lang="">
<head>
<!-- start Mixpanel -->
<script type="text/javascript">...Mixpanel script</script>
<script src="js/scripts.js"></script>
<script type="text/javascript">
const { sources } = window.parseSourcesFromURL(window.location.href)
const sourceObj = window.convertToObj(sources)
mixpanel.track("Page View", sourceObj)
</script>
<!-- end Mixpanel -->
</head>
<body>
<div>
<div class="age-links">
<button onClick=redirectFunc(true)>YES</button>
<button onClick=redirectFunc(false)>NO</button>
</div>
</div>
</body>
</html>
js/scripts.js
(function() {
const convertToObj = () => ...
const getTrackingData = () => ...
const parseSourcesFromURL = () => ...
const redirectFunc = (p) => {
const { sources, link1, link2 } = parseSourcesFromURL(window.location.href)
const redirect = `${p ? link1 : link2}?${sources.join('&')}`
const mixpanelTrackingData = getTrackingData(sources, p, redirect)
mixpanel.track('Button Clicked', mixpanelTrackingData, () => {
window.location.href = redirect;
})
}
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined')
module.exports = {
....
};
else
window.utmSourcesToObject = utmSourcesToObject;
window.parseReferrerForLinksAndUTM = parseReferrerForLinksAndUTM;
window.redirectBasedOnAge = redirectBasedOnAge;
})();
js/scripts.test.js
const { redirectFunc, parseSourcesFromURL } = require('./js/scripts')
const testURL = 'https://test.com/'
describe('parseReferrerForLinksAndUTM', () => {
beforeEach(() => {
global.window = Object.create(window)
Object.defineProperty(window, 'location', {
value: { href: testURL },
writable: true
})
### THIS DOESNT WORK ###
Object.defineProperty(window, 'mixpanel', {
track: jest.fn()
})
})
const { sources, link1, link2 } = parseSourcesFromURL(testURL)
test('redirect link is correct', () => {
### THIS DOESNT WORK ###
global.mixpanel = Object.create({})
global.mixpanel.track = jest.fn()
expect(link1).toBe('https://link1.com')
})
})

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>

django vue js & Highcharts asynchronously fetching data from JSON

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>

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

Categories