Vue v-model and #keydown in one element - javascript

<input
v-model="ticker"
#keydown.enter="addClick($event)"
#keydown="getNames"
I need to solve 1 problem, my v-model ticker I guess works after keydown, therefore when function is called I have into it ticker without 1 symbol, can anyone explain how it works?
getNames() {
console.log(this.ticker);
let filtred = this.coinNames.filter(filtered => filtered.toUpperCase().startsWith(this.ticker.toUpperCase()))
console.log(filtred);
return filtred;
}
Examle:
input: something
output: somethin

You should use #input event to get the current input value :
new Vue({
el: '#app',
data() {
return {
ticker: ''
}
},
methods: {
getNames() {
console.log(this.ticker);
},
addClick(e) {
console.log('enter')
}
}
})
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app" class="container">
<input v-model="ticker" #keydown.enter="addClick($event)" #input="getNames" />
</div>

Related

Get an element by its ref in vue and give it focus

I'd like to give focus to a vue input when a button is pressed. My understanding is that I need the html element, which I get by setting a ref value, then saying:
this.$refs.theRefName.$el.focus();
But I'm getting tripped up on the refs part of that expression. See the MRE below where refs contains the correct keys, but the values are empty. As a result .$el is undefined and the expression errs.
I've seen SO articles that deal with this being undefined (not a problem for me) or $refs being empty because the element was conditionally rendered (also, not a problem for me). I've got $refs, but why does it contain empty objects?
Vue.config.productionTip = false;
Vue.config.devtools = false;
var app = new Vue({
el: '#app',
data: {
message: 'World'
},
methods: {
click() {
alert(JSON.stringify(this.$refs))
// here's what I want to do, but I can't because inp2 is empty
// this.$refs.inp2.$el.focus();
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h1>Why are refs empty objects?</h1>
<input ref="inp1"></input><br/><br/>
<input ref="inp2" placeholder="i want focus on click"></input><br/><br/>
<button #click="click">Click me</button>
</div>
If you can help me get to the html element and give it focus, I'd be much obliged.
Try without $el :
Vue.config.productionTip = false;
Vue.config.devtools = false;
var app = new Vue({
el: '#app',
data: {
message: 'World'
},
methods: {
click() {
this.$refs.inp2.focus();
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.css" />
<script src="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue-icons.min.js"></script>
<div id="app">
<h1>Why are refs empty objects?</h1>
<input ref="inp1" /><br/><br/>
<b-form-input ref="inp2" placeholder="i want focus on click"></b-form-input>
<button #click="click">Click me</button>
</div>

Bind a vue input that doesn't exist yet to a data property

We are using Vex in our application for all the dialog messages. I have an input in one of the dialogs that is used to filter a list of items.
In my Vue instance, I want to listen for the changes on a data property.
The problem is that Vue doesn't get the changes as I type them in the input box. I am thinking this is due to the fact that the input is added to the DOM after the Vue initialization.
How would I approach this so my Vue instance can listen to the input changes? I've done my best to recreate the scenario in it's most simple form in the snippet below.
new Vue({
el: '#app',
data: {
filter: ''
},
methods: {
openModal: function() {
vex.dialog.open({
input: [
'<h2>Filter</h2>',
'<input v-model="filter" />',
'<p>{{filter}}</p>'
].join('')
})
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vex-js/4.0.0/js/vex.combined.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/vex-js/4.0.0/css/vex.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button v-on:click="openModal">Open Modal</button>
</div>
The issue is that you are providing plain html in strings to the vex.dialog.open method. Vue won't have any idea that you have done this and so none of the Vue syntax that you've included in those strings will be interpreted as it would in a Vue component definition.
What you should do is make a Vue component for that input, and then pass that input's element via a ref to the vex.dialog.open method. That way, Vue will have compiled the template before it's used in the dialog.
Here's a simple example:
Vue.component('my-input', {
template: `
<div>
<h2>Filter</h2>
<input v-model="filter"/>
<p>{{filter}}</p>
</div>
`,
data() {
return {
filter: ''
}
}
});
new Vue({
el: '#app',
data() {
return {
modalOpened: false
}
},
methods: {
openModal() {
vex.dialog.open({
input: this.$refs.input.$el
});
this.modalOpened = true;
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vex-js/4.0.0/js/vex.combined.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/vex-js/4.0.0/css/vex.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button #click="openModal">Open Modal</button>
<my-input v-show="modalOpened" ref="input"/>
</div>

Vue - How to get document/window properties bound to a computed property?

I would like to listen to all focus events on inputs accross my Vue application.
To get the currently focused input, I thought about binding the document.activeElement property to a computed property in my app component, but this is not reactive, why ?
Declaring the activeElement in the data is not reactive either.
Same thing for watchers !
The only way to get it working is by simply returning the value after a focus/blur event on the input itself, but that doesn't suit my needs here.
new Vue({
el: "#app",
data: {
activeElem: document.activeElement.tagName,
realActiveElem: document.activeElement.tagName,
},
methods: {
getActiveElem() {
this.realActiveElem = document.activeElement.tagName;
}
},
computed: {
focused() {
return document.activeElement.tagName;
}
},
watch: {
activeElem(val, oldVal) {
console.log(val !== oldVal);
},
focused(val, oldVal) {
console.log(val !== oldVal);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2 #focus="getActiveElem()">
Data: {{activeElem}}
</h2>
<h2>
Computed: {{focused}}
</h2>
<h2>
From function to data: {{realActiveElem}}
</h2>
<input placeholder="Focus/Blur me" id="test" #focus="getActiveElem()" #blur="getActiveElem()" />
</div>
Is there any way to bind document or window properties as reactive ?
Vue can only react to changes made to data, not to the DOM. The change in document.activeElement is a DOM change.
You could use use an event to fire a method to update data. For example:
new Vue({
el: "#app",
data: {
element: ""
},
created() {
document.addEventListener("focusin", this.focusChanged);
},
beforeDestroy() {
document.removeEventListener("focusin", this.focusChanged);
},
methods: {
focusChanged(event) {
this.element = event.target.tagName;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input id="mine">
<p>{{ element }}</p>
</div>

How to bind input value to the return output of a method in Vue.js?

I am using a Vuetify checkbox component and I am trying to bind it's value to the output of my method but it is not working at all. I have tried it with a computed property but I could not pass and argument to it. And it is also not working if I use a method. Is there a way to dynamically assign a value to an input like this?
<div v-for="row in rows">
<v-checkbox :value="isSelected(row.id)"></v-checkbox>
</div>
data()
{
return {
rows: [{id: 22546}, {id: 3521}, {id: 15698}],
selected: [1259, 1898, 3521]
}
},
methods:
{
isSelected(id)
{
if (this.selected.indexOf(id) > -1) {
return true
} else {
return false
}
}
}
When I tried with v-model instead if :value it gave me this error:
<v-checkbox v-model="isSelected(row.id)"></v-checkbox>
isSelected(id)
{
return true
},
error
[Vue warn]: Failed to generate render function:
SyntaxError: missing ) after argument list in
Try with:
<v-checkbox :input-value="isSelected(row.id)"></v-checkbox>
You can use v-model with getter that encapsulates the logic that decides if checkbox needs to be checked:
let id = 1898;
new Vue({
el: '#app',
data() {
return {
rows: [{id: 22546}, {id: 3521}, {id: 15698}],
selected: [1259, 1898, 3521]
}
},
computed: {
val: {
get: function() {
return this.selected.indexOf(id) > -1;
},
set: function(newValue) {
console.log(newValue);
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet">
<div id='app'>
<div v-for="row in rows">
<v-checkbox v-model="val"></v-checkbox>
</div>
</div>
It works fine with v-model make sure your app is nested inside v-app tag :
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({ el: '#app',
data()
{
return {
rows: [{id: 22546}, {id: 3521}, {id: 15698}],
selected: [1259, 1898, 3521]
}
},
})
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
</head>
<body>
<div id="app">
<v-app>
<div v-for="(row,i) in rows">
<v-checkbox
v-model="selected[i]"
:label="`${selected[i] > -1 ? true : false} `"
></v-checkbox>
</div>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js"></script>
</body>
</html>
Ok, I figure it out,
v-model is 2-way binding, you can only bind it to variable or computed property with getter and setter.
value provided by vue-checkbox component is not the value of checkbox checked/unchecked state. You can set initial state with :input-value.

v-model in icheck-box component not working in vue

I'm trying to create a checkbox component but I am unable to do it. How can I create three checkboxs (using ichecks and inputs) and get all the selected ones using v-model in an array? The problem is that I can get the value of the clicked checkbox separately but I can not get all the values in array as it is suppose happen with vue's v-model. It seems that, they are getting lost somewhere. here my code
<html>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/iCheck/1.0.2/icheck.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/iCheck/1.0.2/skins/all.css" rel="stylesheet">
<div id='app'>
<icheck :value="'Jack'" id="jack" v-model="checkedNames" > </icheck>
<icheck :value="'John'" id="john" v-model="checkedNames" > </icheck>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
</div>
</html>
<script>
Vue.component('icheck', {
props: {
value:{ required: false }
},
template: `
<input type="checkbox" >
`,
mounted: function () {
var vm = this
$(this.$el).iCheck({
//checkboxClass: 'icheckbox_minimal',
checkboxClass: 'icheckbox_square-red',
//radioClass: 'iradio_minimal',
radioClass: 'iradio_square',
increaseArea: '20%' // optional
})
.val(this.value)
.trigger('ifChanged')
// emit event on change. here the problem
.on('ifChanged', (event)=>{
let isChecked = event.target.checked
let val = event.target.value
// here the problem need an array
vm.$emit('input',isChecked ? [val]:[])
});
},
watch: {
value: function (value) {
// update value
$(this.$el).val(value)
}
}
})
new Vue({
el: '#app',
data: {
checkedNames: []
}
})
</script>
Here is how I would do it.
<icheck :val="'Jack'" id="jack" v-model="checkedNames" > </icheck>
<icheck :val="'John'" id="john" v-model="checkedNames" > </icheck>
props: {
val:{ required: true },
value: { required: false }
},
....
// Check if the value is preset from the props and toggle check
if (this.value.includes(this.val)) {
$(this.$el).iCheck('check');
}
$(this.$el).iCheck({
//checkboxClass: 'icheckbox_minimal',
checkboxClass: 'icheckbox_square-red',
//radioClass: 'iradio_minimal',
radioClass: 'iradio_square',
increaseArea: '20%' // optional
})
.val(this.val)
.trigger('ifChanged')
.on('ifChanged', (event)=>{
// create a local copy so as not to modify the prop
let value = [].concat(this.value)
// check if the array includes the value already
if(value.includes(this.val)){
// if it does remove it
value.splice(value.indexOf(this.val), 1)
} else {
// if it doesn't add it
value.push(this.val)
}
// emit the entire array
vm.$emit('input', value)
});
I see what you try to do, but this only works with native checkboxes. if the v-model is an array and the element is a checkbox, it will change the v-model to something like v-model="data[index]". This does not work with custom elements, as you try to do.

Categories

Resources