How can i refresh only nuxt component in Nuxt? - vue.js

i want refresh my component after add something. İ try
refresh() {
this.$nuxt.refresh()
}
this but not working this is truelly

Here is my idea to refresh the component. Base on your issue, you can use some ways to achieve this goal. But in my opinion, there is a way that you can bind a key to your component, and by changing the key, your component will refresh.
I implement a simple example to show you how it works:
Vue.component('button-counter', {
data() {
return {
count: 0
}
},
template: '<button #click="count++">You clicked me {{ count }} times.</button>'
})
new Vue({
el: '#app',
data: {
component_key: 0
},
methods: {
refreshComponent() {
this.component_key += 1
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app">
<button #click="refreshComponent()">
Refresh Compoenent
</button>
<button-counter :key="component_key" />
</div>
You can click on the right button in the above example and see the count is going up. After that, when you click on the Refresh Component button, you see that the component refreshes.
Also, you can use this.$forceUpdate() to refresh all of your variables. Maybe it'll help with your situation, but I recommend the key binding solution for your issue.

Related

Bind click from instance instead of html tag

In vue is possible to bind button click directly from vue instance?
I have this button:
<el-button #click="alert_me" class="gf-button" type="primary" style="margin-left: 16px;">Button</el-button>
I wan't to remove #click="alert_me" and do like i would normally do with jquery but with vue.
Is it possible?
My Vue Instance:
new Vue({
el: "#app",
data: {
},
methods: {
alert_me() {
alert('Hello from vue!');
}
},
});
Thanks
If you need to attach a click event listener programmatically, it is possible with the classic javascript api:
<template>
<el-button class="gf-button" type="primary">Button</el-button>
</template>
<script>
export default {
mounted () {
// jquery would also work if it's installed.
document.getElementByClassName('gf-button').addEventListener('click', this.alert_me)
},
methods: {
alert_me() {
console.log('alert')
}
}
}
</script>
You could avoid the manual element query from the document with the Vue $refs object.
<template>
<el-button ref="myButton" class="gf-button" type="primary">Button</el-button>
</template>
<script>
export default {
mounted () {
this.$refs.myButton.addEventListener('click', this.alert_me)
},
methods: {
alert_me() {
console.log('alert')
}
}
}
</script>
But if you need that event as soon as the Vue component is created, I wouldn't recommend doing this. It kinda oversee the shadow dom optimisation of Vue.
The #click="" syntax provided is the best way to attach a click listener to an html element.
You can make use of addEventListener and call it in mounted life cycle.
mounted() {
document.querySelector('#element').addEventListener('click', event =>
{
//handle click
}
)
}

Bootstrap-Vue usage when utilising render() and JSX

I've trauled the docs for Bootstrap Vue, as well as asked this question on their github issue tracker a few days ago, with no luck.
I can't find anything in relation to using Vue's render() or JSX to generate bootstrap vue elements.
I'm having trouble even with the simplest scenario such as opening a modal on the click of a button.
const vue2 = new Vue({
el: '#vue2',
data: function() {
return {
show: false
}
},
render() {
return(
<div>
<b-btn v-b-modal="'myModal'">Show Modal</b-btn>
<b-modal id="myModal">
Hello From My Modal!
</b-modal>
</div>
)
}
});
The elements are actually rendered in HTML:
But the 'click' event on the button doesn't work.
If I log the Vue instance in the console there is no reference to the instance of the modal in this.$refs, either.
Does bootstrap-vue support Vue's render() & JSX functionality? If so, how is this kind of thing achieved?
So, I spent a fair bit of time looking into this. I could not get the above to work, It may be a bug in Bootstrap-Vue.
I ended up adding my own ref to the Vue object, and manually calling a function on click to show the modal.
Example below, for anyone else who comes across this.
const vue2 = new Vue({
el: '#vue2',
data: function() {
return {
modalShow: false
}
},
methods: {
showModal() {
this.$refs.myModal.show()
}
},
render() {
return(
<div>
<b-btn on-click={this.showModal}>Show Modal</b-btn>
<b-modal ref="myModal">
Hello From My Modal!
</b-modal>
</div>
)
}
});

Extend Vue.js v-on:click directive

I'm new to vuejs. I'm trying to create my first app. I would like to show a confirm message on every click on buttons.
Example:
<button class="btn btn-danger" v-on:click="reject(proposal)">reject</button>
My question is: Can I extend the v-on:click event to show the confirm everywhere? I would make my custom directive called v-confirm-click that first executes a confirm and then, if I click on "ok", executes the click event. Is it possible?
I would recommend a component instead. Directives in Vue are generally used for direct DOM manipulation. In most cases where you think you need a directive, a component is better.
Here is an example of a confirm button component.
Vue.component("confirm-button",{
props:["onConfirm", "confirmText"],
template:`<button #click="onClick"><slot></slot></button>`,
methods:{
onClick(){
if (confirm(this.confirmText))
this.onConfirm()
}
}
})
Which you could use like this:
<confirm-button :on-confirm="confirm" confirm-text="Are you sure?">
Confirm
</confirm-button>
Here is an example.
console.clear()
Vue.component("confirm-button", {
props: ["onConfirm", "confirmText"],
template: `<button #click="onClick"><slot></slot></button>`,
methods: {
onClick() {
if (confirm(this.confirmText))
this.onConfirm()
}
}
})
new Vue({
el: "#app",
methods: {
confirm() {
alert("Confirmed!")
}
}
})
<script src="https://unpkg.com/vue#2.2.6/dist/vue.js"></script>
<div id="app">
<confirm-button :on-confirm="confirm" confirm-text="Are you sure?">
Confirm
</confirm-button>
</div>
I do not know of a way to extend a directive. It is easy enough to include a confirm call in the click handler. It won't convert every click to a confirmed click, but neither would writing a new directive; in either case, you have to update all your code to use the new form.
new Vue({
el: '#app',
methods: {
reject(p) {
alert("Rejected " + p);
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="app">
<button class="btn btn-danger" #click="confirm('some message') && reject('some arg')">reject</button>
</div>

Sending one time event to child components

Im struggling to implement something which I think is pretty easy.
In my Vue app I loop through a list. Each list item is a child component. Each list item has an expand/collapse button. That works fine, but I want to be able to close all open items from the parent and I don't seem to be able to get that working as I would like.
The expand/collapse is controlled via a variable called isOpen so
<div v-if="isOpen">Something here</div>
I have tried using a computed property instead of the isOpen and passing props but that issue is I think it needs to act more like an event.
Consider three open list items. If the list items are controlled by a prop, and setting it to false closes the items, when an item is reopened, the prop is still false so therefore will not work a second time. I know I could change it back on the parent, but it seems wrong.
Whats the best way to accomplish this?
If you passed an "allClosed" prop, you would need to have your child components emit events to reset it every time they opened. That seems hacky to me. I think you are right that it should be more of a parent-to-children event, which calls for an event bus.
new Vue({
el: '#app',
data: {
closeBus: new Vue(),
kids: [1, 2, 3]
},
components: {
expandableThing: {
data() {
return {
isOpen: true
}
},
props: ['bus'],
methods: {
toggle() {
this.isOpen = !this.isOpen;
}
},
created() {
this.bus.$on('close', () => this.isOpen = false);
}
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="app">
<expandable-thing v-for="kid in kids" inline-template :bus="closeBus">
<div>
<div v-show="isOpen">My stuff!</div>
<button #click="toggle">Toggle</button>
</div>
</expandable-thing>
<button #click="closeBus.$emit('close')">Close all</button>
</div>

How to set keyup on whole page in Vue.js

Is it possible to set a v-on:keyup.enter on the whole page, not only for an input element in javascript framework Vue.js ?
Perhaps a better way to do this is with a Vue component. This would allow you to control when you listen to events by including or not including the component. Then you could attach event listeners to Nuxt using the no-ssr component.
Here is how you create the component:
<template>
<div></div>
</template>
<script>
export default {
created() {
const component = this;
this.handler = function (e) {
component.$emit('keyup', e);
}
window.addEventListener('keyup', this.handler);
},
beforeDestroy() {
window.removeEventListener('keyup', this.handler);
}
}
</script>
<style lang="stylus" scoped>
div {
display: none;
}
</style>
Then on the page you want to use that component you'd add this HTML:
<keyboard-events v-on:keyup="keyboardEvent"></keyboard-events>
And then you'll have to add your event handler method:
methods: {
keyboardEvent (e) {
if (e.which === 13) {
// run your code
}
}
}
Short answer is yes, but how depends on your context. If you are using vue-router as I am on a current project, you would want to add to the outer-most element you want that applied to. In my case I'm using the actual app.vue entry point's initial div element.
There is one catch that I believe is a hard requirement, the element has to be within the potentially focusable elements. The way I'm dealing with that is setting a -1 tabindex and just declaring my super-hotkeys (mostly for debug purposes right now) on the parent element in my app.
<template>
<div
id="app-main"
tabindex="-1"
#keyup.enter="doSomething"
>
<everything-else></everything-else>
</div>
</template>
EDIT:
As a side note, I also added a touch of additional configuration to my vue-router to make sure the right element is focused when I transition pages. This allows the pageup/pagedown scrolling to already be in the right section based on the content area being the only scrollable section. You'd also have to add the tabindex="-1" to the app-content element as well.
router.afterEach(function (transition) {
document.getElementById('app-content').focus();
});
and the basis of my app-content component:
<template>
<div id="app-content" tabindex="-1">
<router-view
id="app-view"
transition="app-view__transition"
transition-mode="out-in"
></router-view>
</div>
</template>
I created a small npm module that takes care of global keypress events in Vue, hope it makes someone's life easier:
https://github.com/lupas/vue-keypress
My simplest approach:
Add into your root Vue component (or any other component):
new Vue({
//...
created() {
window.addEventListener('keypress', this.onKeyPress);
},
beforeDestroy() {
window.removeEventListener('keypress', this.onKeyPress);
},
methods: {
onKeyPress(e) {
console.log('KEYPRESS EVENT', e)
//... your code
}
}
//...
})
In Vue 3 composition API, you can do it with a composable:
import { onMounted, onUnmounted } from "vue";
export function useKeyupEvent(handler) {
onMounted(() => document.addEventListener("keyup", handler));
onUnmounted(() => document.removeEventListener("keyup", handler));
}
and then in your component setup:
useKeyupEvent( event => console.log(event))