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>
Related
In Vue.js 2 I would like to convert a string into a function call so that it can be set as an event handler.
I believe this would be very practical, specially when dynamically creating lots of elements (e.g. buttons) based on a list of objects.
new Vue({
el: "#app",
data: {
myArray: [
{ value: 1, fn: "firstMethod" },
{ value: 2, fn: "secondMethod" },
],
},
methods: {
firstMethod() {
console.log("'firstMethod' was executed.");
},
secondMethod() {
console.log("'secondMethod' was executed.");
},
},
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<template v-for="elem in myArray">
<button #click="elem.fn"> <!-- Here is where I am stucked. -->
<!-- <button> -->
{{elem.value}}
</button>
</template>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js"></script>
<script src="script.js"></script>
</body>
</html>
My first attempt at doing this was setting the fn properties in myArray as sort of pointers to the corresponding functions with this (e.g. fn: this.firstMethod). The problem is, I believe, that at the time of the definition, these functions are still unkown, as I get: [Vue warn]: Invalid handler for event "click": got undefined.
Is what I am trying to achieve even possible? Is there a downside with this strategy that I am overlooking?
Try to create one method, which will be working with all buttons
new Vue({
el: "#app",
data: {
myArray: [
{ value: 1, fn: "firstMethod" },
{ value: 2, fn: "secondMethod" },
],
},
methods: {
basicMethod(name) {
console.log(`'${name}' was executed.`);
if(name === 'firstMethod') {
//some logic, and so on for other methods if u need
}
},
},
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<template v-for="elem in myArray">
<button #click="basicMethod(elem.fn)"> <!-- Here is where I am stucked. -->
<!-- <button> -->
{{elem.value}}
</button>
</template>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js"></script>
<script src="script.js"></script>
</body>
</html>
You can use a generic method provided with the function name the call this[ fn ]();.
But for security reasons, you might want these custom methods to be in an object, not just on the main this, so other methods can't be called.
Also, you want to check if the method exists before calling it.
It would look something like this:
new Vue({
el: "#app",
data: {
myArray: [
{ value: 1, fn: "firstMethod" },
{ value: 2, fn: "secondMethod" },
{ value: 3, fn: "nonExistingMethod" }, // Won't throw an error
{ value: 4, fn: "someImportantSecureMethod" }, // Won't be called
],
customMethods: {
firstMethod: function() {
console.log("'firstMethod' was executed.");
},
secondMethod: function() {
console.log("'secondMethod' was executed.");
},
},
},
methods: {
callCustomMethod(fn) {
// Make sure it exists
if (typeof this.customMethods[fn] === "function") {
// Only methods inside the customMethods object are available
this.customMethods[fn]();
}
},
someImportantSecureMethod() {
console.log('The method may not be exposed to dynamic calling!');
},
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<template v-for="elem in myArray">
<button #click="callCustomMethod(elem.fn)">
<!-- <button> -->
{{elem.value}}
</button>
</template>
</div>
As a side note:
You might also considering using custom events (see docs) for this. Using $emit('custom-event-name') as the v-on:click handler and have your custom methods as event listeners. (Makes it easy when you later might want to make the items into separate components.)
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>
I need a mask for input that needs to have the format of dddd-ddd (Portuguse zip code), I don't feel like importing a library just for this input.
This is what I have right now:
new Vue({
el: '#app',
data: {
zip_code: '2770-315'
},
computed: {
mask_zip_code: {
get: function() {
return this.zip_code;
},
set: function(input) {
input = input.replace(/[^0-9-]/g, "");
if(input.length >= 4) {
input = input.substr(0, 4)+'-'+input.substr(5); // in case people type "-"
}
this.zip_code = input;
}
}
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<input v-model="mask_zip_code" maxlength="8">
</div>
Has you can see the behavior is a little wierd and it allows to type letters as well.
I've updated your snippet to work as you intended it. The computed value works but it will not be reflected in the input, instead a method is more appropriate here
new Vue({
el: '#app',
data: {
zip_code: '2770-315'
},
methods: {
mask_zip: function(event) {
if (event.key && event.key.match(/[a-zA-Z]/)) {
event.preventDefault()
} else {
if(this.zip_code.length >= 4) {
this.zip_code = this.zip_code.substr(0, 4)+'-'+this.zip_code.substr(5); // in case people type "-"
}
}
return this.zip_code;
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<input v-model="mask_zip_code" maxlength="8" #keypress="inputValidation">
{{mask_zip_code}}
</div>
Try using the pattern attribute with a regex:
<script src="https://unpkg.com/vue"></script>
<form>
<input v-model="mask_zip_code" pattern="[0-9]{4}-[0-9]{3}">
<button>Submit</button>
</form>
This should prevent users from submitting the form with anything other than a valid Portuguese zip code.
I have been trying to figure out how to use VueJS, Axios and Python together. I can make a post request to the python file just fine. When I click the submit button, the response data shows correctly, but only for a second and then disappears. Why is this?
insert.py
#!/usr/bin/python3.6
import os
import sys
import json
parsed_json = json.loads(sys.stdin.read())
print ("Content-type: text/html\n")
print(parsed_json['firstName'])
print(parsed_json['lastName'])
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>index.html</title>
</head>
<body>
<form id="example-1">
<input type="text" ref="firstName">
<input type="text" ref="lastName">
<button v-on:click="submit">Submit</button>
{{ output }}
</form>
<script src="https://unpkg.com/vue#2.4.2/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
var example1 = new Vue({
el: '#example-1',
data: {
output: ''
},
methods: {
submit: function () {
axios.post('/cgi-bin/insert.py', {
firstName: this.$refs.firstName.value,
lastName: this.$refs.lastName.value
})
.then(response => {
this.output = response.data;
})
.catch(function (error) {
console.log(error);
});
}
}
})
</script>
</body>
</html>
Change your button to type="button".
<button type="button" v-on:click="submit">Submit</button>
The default button type is "submit" which results in a refresh of your page.
Alternatively you can use the .prevent modifier.
<button v-on:click.prevent="submit">Submit</button>
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;