Is it possible to bind focus event for all the inputs in web app in Vue? - vue.js

I have existing web app in Vue. Now I need to create an event for each input/textarea focus. Is it possible to bind it globally so I don't have to add #focus="function" to each element?

Why wouldn't it be possible?
Get required elements
Assign whatever functionality you want
mounted () {
// Get all input elements with class="CLASS_NAME"
const inputs = document.querySelectorAll('input.CLASS_NAME')
// Iterate over elements and add each one of them a `focus` listener
inputs.forEach(input => {
input.addEventListener('focus', this.inputFocusHandler)
})
},
methods: {
inputFocusHandler (event) {
...
}
}

Related

How to render el-dialog before the first popup?

If the el-dialog has not opened before,elements under el-dialog cannot be retrieved using this.$refs as elements has not rendered.
I want to know how to render el-dialog but not show it because I need to initialize something in el-dialog.
You can use vm.$nextTick( [callback] )
Example
in methods
OpenDialog() {
this.dialogFormVisible = true; // your dialog toggle variable
this.$nextTick(() => {
// some action or your this.$refs will here
});
},
Reference
https://v2.vuejs.org/v2/api/#vm-nextTick

How to set focus to a vue.js sfc root-element once it is visible (v-show is toggled)

I have a side-nav component that is hidden by default using v-show.
A click event in an external component sets a flag in vuex to toggle the side-nav.
How can I set focus to the side-nav component's root div once it's displayed?
I am trying to use this focus-on focus-off technique to hide the side-nav
Maybe something like this:
export default {
watch: {
someVarFromVuex(value) {
// Don't focus unless the value got switched on
if (!value) return;
// Make sure to add the ref to your template.
// You could also use an id.
const $input = this.$refs.input.$el;
// Just in case the input somehow doesn't exist...
if ($input) {
this.$nextTick(() => {
$input.focus();
})
}
},
},
};
Note that if you are actually trying to focus a div, then it will need to have a tabindex.

"nativeOn" vs. "on" in the render function & JSX

In the Vue documentation at https://v2.vuejs.org/v2/guide/render-function.html#The-Data-Object-In-Depth there is an explanation for “on” and “nativeOn”:
// Event handlers are nested under `on`, though
// modifiers such as in `v-on:keyup.enter` are not
// supported. You'll have to manually check the
// keyCode in the handler instead.
on: {
click: this.clickHandler
},
// For components only. Allows you to listen to
// native events, rather than events emitted from
// the component using `vm.$emit`.
nativeOn: {
click: this.nativeClickHandler
},
We are trying to listen to an “input” event from a custom component we created. We noticed that the event did not get detected in the on property, so we tried nativeOn and we were surprised to find that this worked. We were surprised because the docs say nativeOn:
Allows you to listen to
// native events, rather than events emitted from
// the component using vm.$emit
In this case, we are using an event emitted from a (custom) component using vm.$emit.
Here is a snippet from our code demonstrating the above:
on: {
input: (event) => {
console.log('hi'); // We did not receive "hi" in the console
}
},
nativeOn: {
input: (event) => {
console.log('hi2'); // We did receive "hi2" in the console
}
Any clarification on why we would need nativeOn to listen to “input” events from a custom component, or on when to use nativeOn vs. on and the differences therein would be most appreciated. Thanks in advance!

How to automatically construct watch property based on data attributes in Vue.js?

I have standard Vue.js component and I'd like to convert attributes in data property to watcher or in other words I want to construct a watch object based on data property attributes automatically
my idea looks something like this
watch: {
...(() => {
const watchers = {}
Object.keys(this.$data).forEach(key => {
watchers[key] = () => {
new ProductNutrientUpdate(this).run()
}
})
return watchers
})(),
},
the problem with this approach is that this.$data is not constructed yet
maybe there is some way how I can add watchers in created hook for example??
Vue already watches properties of the data object (note if any of these values are themselves objects, I think you need to update the whole object, i.e. change its value to a shallow copy with the desired nested key-values).
Refer to: https://v2.vuejs.org/v2/guide/reactivity.html
You can then use the update lifecycle hook to watch for all changes to data: https://v2.vuejs.org/v2/api/#updated
I was able to resolve a challenge using the following approach
created() {
Object.keys(this.$data).forEach(key => {
this.$watch(key, function() {
// ... some logic to trigger on attribute change
})
})
}

VueJS2: Update data pattern?

So, in one of my VueJS templates, I have a left sidebar that generates buttons by iterating (v-for) through a multidimensional items array.
When one of these buttons is clicked, a method is run:
this.active.notes = item.notes
active.notes is bound to a textarea in the right content section.
So, every time you click one of the item buttons, you see the (active) notes associated with that item.
I want to be able to have the user edit the active notes in the textarea. I have an AJAX call on textarea blur which updates the db. But the problem is, the items data hasn't changed. So if I click a different item, then click back to the edited item, I see the pre-edited notes. When I refresh the page, of course, everything lines up perfectly.
What is the best way to update the items data, so that it is always consistent with the textarea edits? Should I reload the items data somehow (with another AJAX call to the db)? Or is there a better way to bind the models together?
Here is the JS:
export default {
mounted () {
this.loadItems();
},
data() {
return {
items: [],
active: {
notes: ''
},
}
},
methods: {
loadItems() {
axios.get('/api/items/'+this.id)
.then(resp => {
this.items = resp.data
})
},
saveNotes () {
...api call to save in db...
},
updateActive (item) {
this.active.notes = item.notes;
},
}
}
i can't find items property in your data object.
a property must be present in the data object in order for Vue to convert it and make it reactive
Vue does not allow dynamically adding new root-level reactive properties to an already created instance
maybe you can have a look at this:
Vue Reactivity in Depth
It doesn't seem like this.items exists in your structure, unless there is something that isn't shown. If it doesn't exist set it as an empty array, which will be filled on your ajax call:
data() {
return {
active: {
notes: ''
},
items: [],
},
Now when you ajax method runs, the empty array, items, will be filled with your resp.data via this line:(this.items = resp.data). Then you should be able to iterate through your items array using v-for and your updateActive method should work as you intend it to.
use PUSH
this.items.push(resp.data);
here is a similar question
vue.js http get web api url render list