I'm new with vue.js and have a problem,
I have a computed function that alerts a Word reversed,
I made this function working on clicking a button but it works on page loading so what is the problem.
this is the vue.js code,
new Vue({
el: '#computed',
data: {
word: 'welcome',
},
computed: {
alertRev: function() {
// get the word reversed
alert (this.word.split('').reverse().join(''));
},
}});
And this is HTML code:
<div id="computed">
<button #click="alertRev">reverse the word</button>
</div>
And this is jsFiddle link Link to code
As #BertEvans indicated, a method will achieve what you want to do.
My understanding is that a computed property would typically return a result from a function, as opposed to performing an action, such as an alert. Shamelessly modified example from Vuejs docs (https://v2.vuejs.org/v2/guide/computed.html):
new Vue({
el: '#computed',
data: {
word: 'welcome',
},
computed: {
reversedMessage: function() {
// get the word reversed, no alert
return this.word.split('').reverse().join('');
},
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.min.js"></script>
<div id="computed" style="font-family: arial;">
Type the word: <input type="text" v-model="word">
<br />
<br /> Reversed: {{ reversedMessage }}
</div>
The method example:
new Vue({
el: '#computed',
data: {
word: 'welcome',
},
methods: {
alertRev: function() {
// get the word reversed
alert(this.word.split('').reverse().join(''));
},
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.min.js"></script>
<div id="computed">
Word: {{ word }}
<br />
<br />
<button #click="alertRev">Reverse the word (alert)</button>
</div>
As an aside, computed properties aren't very handy with asynchronous operations.
Hope this doesn't highlight that you could write what I know about Vuejs on the back of a postage stamp with a wet mop.
Related
I'm new to Vue and have been trying to figure this out for days without finding a solution that works...
How do I add an external vue-component multiple times #click on button?
Hopefully my pseudo-code below will explain what i'm trying to do.
<template>
<div>
<Piece/>
<!-- HERE I WANT TO ADD MULTIPLE "<Piece/>" #click on below button -->
<button type="button" #click="addPiece">Add Piece</button>
</div>
</template>
<script>
import Piece from "#/components/Piece.vue";
export default {
name: "PiecesModal",
components: {
Piece,
},
methods: {
addPiece () {
this.components.push(Piece)
}
},
};
</script>
Vue is "data driven"
Instead of wasting time "figuring this out for days", just read the excellent docs, List Rendering in this case...
const piece = Vue.component('Piece', {
props: ['number'],
template: `<div> Piece {{ number }} </div>`
})
const app = new Vue({
el: "#app",
components: { piece },
data() {
return {
counter: 0,
pieces: []
}
},
methods: {
addPiece() {
this.pieces.push(this.counter)
this.counter++
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button type="button" #click="addPiece">Add Piece</button>
<hr>
<Piece v-for="piece in pieces" :key="piece" :number="piece"/>
</div>
I want to group my refs in to an object and access them by object notation. With that in mind, I now have this component:
new Vue({
el: '#app',
template: `
<div>
<input ref="input.name" type="text"/>
<input ref="input.email" type="email"/>
<input ref="input.password" type="password"/>
</div>
`,
created(){
console.log(this.$refs["input.name"]); // This works fine
console.log(this.$refs.input.name); // throws "TypeError: Cannot read property 'name' of undefined"
}
})
But it only shows this:
{
input.name: input,
input.email: input,
input.password: input,
}
What I want is something like this:
{
input: {
name: input,
email: input,
password: input,
},
}
Check fiddle here
Update:
I'm well aware of v-model but that's not what I need, I'll be doing something else with DOM.
new Vue({
el: '#app',
data() {
return {
inputs: {}
}
},
template: `
<div>
<input ref="input.name" type="text" value="123"/>
<input ref="input.email" type="email"/>
<input ref="input.password" type="password"/>
<button type="button" #click="clickMe">Click ME</button>
</div>
`,
mounted() {
this.setRefs();
console.log("this.inputs", this.inputs);
},
methods: {
setRefs() {
const INPUTS = {};
for (key in this.$refs) {
if (key.indexOf(".")) {
const KEYS_LIST = key.split(".");
INPUTS[KEYS_LIST[0]] = INPUTS[KEYS_LIST[0]] || {};
INPUTS[KEYS_LIST[0]][KEYS_LIST[1]] = this.$refs[key];
}
}
this.inputs = INPUTS;
},
clickMe() {
console.log("this.inputs.input.name.value", this.inputs.input.name.value);
},
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>
This cannot work: refs only support strings as keys (see the docs), so there is not way of using objects here.
Also, a string with "dot notation" does not magically transform into an object with a nested property -- it's just a string. You could work around this by manually parsing the ref strings into an object structure, as has been demonstrated by #Ilia Brykin's answer. But I honestly think that you are misunderstanding the purpose of the whole ref system if you really want to do that.
P.S.: If you drop the "dort notation" part, you could use keys like input_name and access them via this.$refs.input_name.
EDIT
Another idea: you can get all input refs by their common prefix.
Object.keys(this.$refs).filter(ref => ref.startsWith('input.')
This gives you an array of ref strings of input elements.
I have a button, for load files or add some text
After load it pushed in data() prop
How i can validate this prop, if them not have input
Im found only one solution - make watch for data props. and set validate in
Maybe exist more beautiful way?
I try validator.verify() - but it dont send error in main errorBag from validateAll
This is example
<div id="app">
<testc></testc>
</div>
<script type="text/x-template" id="test">
<div>
<input type="text" v-validate="'required'" name="test_vee">
{{errors.first('test_vee')}}
<hr>
<button #click="addRow">Add</button>
<input type="text" v-model="inputValue" name="test_input"/>
<hr>
{{rows}}
<hr>
{{errors.first('rows')}}
<button #click="validateForm">Validate</button>
</div>
</script>
and script
Vue.component('testc', {
template: '#test',
data() {
return {
inputValue: '',
rows: []
}
},
watch: {
rows: {
handler: function(newVal, oldVal) {
this.$validator.errors.remove('rows');
if (this.rows.length < 2) {
this.$validator.errors.add({
id: 'rows',
field: 'rows',
msg: 'Need 2 rows!',
});
}
}
}
},
methods: {
addRow: function() {
this.rows.push(this.inputValue);
this.inputValue = '';
},
validateForm: function(){
this.$validator.validateAll();
}
}
});
Vue.use(VeeValidate);
new Vue({
el: '#app'
})
https://codepen.io/gelid/pen/YBajER
First input in example: default validate - its ok
Second input: for add items - dont need validate or has self validate (not empty for example)
In data of component i have prop rows - it is need validate before ajax request to backend for save data
I'm trying to get two input values using one mounted function for the date picker. But not getting how do I do that?
Here is the code:
HTML:
<div id="app">
<form v-on:submit.prevent="saveFleetJob">
<input type="text" class="fleet-date" v-model="item.from">
<input type="text" class="fleet-date" v-model="item.to">
<button class="btn btn-primary">Click</button>
</form>
</div>
Vue code:
new Vue({
el: "#app",
data: {
item: {
from:'',
to:''
},
},
mounted() {
$(".fleet-date").datepicker().on(
"changeDate", () => {
this.item.from = $('.fleet-date').val()
}
);
},
methods: {
saveFleetJob() {
alert(JSON.stringify(this.item));
},
}
})
js fiddle demo link here
Any suggestions please?
As Sphinx pointed there is some context mess, but it's not the only issue.
See this updated fiddle: https://jsfiddle.net/pb91fk6o/
You have to add
elem.dispatchEvent(new Event('input'))
to make this work.
So mounted should look like:
mounted() {
$(".fleet-date")
.datepicker()
.on("changeDate", (e) => {
e.target.dispatchEvent(new Event('input'))
})
},
See this issue for more details: https://github.com/vuejs/vue/issues/2804
I have the following Popper.js popup in which I have a button on which I want to attach a Vue.js click event.
However, while the click event works outside the popup, it doesn't work instead the popup.
How can I get changeText() to work inside the popup as well?
https://jsfiddle.net/edwardtanguay/jxs5nmxs
HTML:
<div id="app">
<div>
Message: {{message}}
</div>
<div>
<button #click="changeText()">outside works</button>
</div>
<hr/>
<a href="#"
id="example"
class="btn btn-primary"
rel="popover"
data-original-title="Test Form"
data-content='
<div class="form-group">
<label for="exampleInputPassword1">Name</label>
<input type="text" class="form-control">
</div>
<button #click="changeText()" class="btn btn-success">Submit</button>
'>Fill out form</a>
</div>
JavaScript:
var vm = new Vue({
el: '#app',
data: function() {
return {
message: 'hello'
}
},
methods: {
changeText: function() {
alert('test');
}
}
});
$(function () {
$('#example').popover({html: true});
});
ADDENDUM:
Even if I load the popover as a mounted hook, it only works outside the popup but not inside: https://jsfiddle.net/edwardtanguay/3seu8Lbw
Nor does it work if I include the Vue.js HTML in a popper.js template parameter: https://jsfiddle.net/edwardtanguay/uaf5wjtn/
The reason it doesn't work is because popover injects it's own html dynamically and obviously Vue does not compile this template.
You'll have to use popover events to overcome this, it's a bit hacky but i don't see any other way:
var vm = new Vue({
el: '#app',
data: function() {
return {
message: 'hello'
}
},
methods: {
changeText: function() {
alert('test');
}
},
mounted: function() {
var self = this;
$('#example').popover({
html: true
})
.on('hidden.bs.popover', function() {
self.changeText()
}).parent().delegate('.btn-success', 'click', function() {
$('#example').popover('hide')
});
}
});
https://jsfiddle.net/vangj1uc/