Bootstrap-Vue usage when utilising render() and JSX - vue.js

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>
)
}
});

Related

How to call a component method each time this component show in vue2?

Vue component hasn't onShow lifecycle method.
How to call a component method each time this component show in vue2?
I have used this library for that purpose before:
https://github.com/Akryum/vue-observe-visibility
I am assuming you are dynamically hiding and showing the component and you want to trigger few functionality every time component show. If Yes, You can simply achieve this requirement by using v-if directive instead of v-show. As v-if will rebuild the component every time condition got passed.
Live Demo :
Vue.component('child', {
props: ['childmsg'],
template: '<p>{{ childmsg }}</p>',
mounted() {
console.log('child component mounted');
}
});
var app = new Vue({
el: '#app',
data: {
buttonMsg: 'Show Child Component',
showChild: false
},
methods: {
toggleBtn() {
this.showChild = !this.showChild;
this.buttonMsg = this.showChild ? 'Hide Child Component' : 'Show Child Component';
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button #click="toggleBtn">{{ buttonMsg }}</button>
<child v-if="showChild" childmsg="This is a child message"/>
</div>

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
}
)
}

How can i refresh only nuxt component in Nuxt?

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.

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>

Vuejs modal component cannot reference method

I have a modal dialog which is trying to use a method on the Vue app instance but getting the error
app.js:32117 [Vue warn]: Property or method "calcFees" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
The app declaration
Vue.component('sale', require('./components/Sale.vue'));
const app = new Vue({
el: '#app',
data: {
showModal: false
},
methods: {
calcFees: function (event) {
alert('GOOD');
}
}
});
Sale.vue component minimised for now
<template name="sale">
<input type="text" placeholder="Sale Price" class="form-control" #blur="calcFees">
</template>
The sale component is simply included in the main page here
<sale v-if="showModal"></sale>
The modal dialog works fine, displays the above text input however the above error is shown in the console and the blur event doesn't call the method.
It seems it has something to do with the component template, because i tested the blur event successfully by putting a text input in the main blade page directly.
Any ideas why it doesn't work in this way? I saw a comment somewhere about something to do with it being a <template> but it didn't explain how to fix.
Components cannot access methods declared in other components or the root Vue directly.
The problem with this code is that the calcFees method is declared in the root Vue, but you are trying to call it from the Sale.vue component.
There are several ways to make this work. One is you can move calcFees to the component. Another is you can $emit an event to the parent with whatever it needs to use in calcFees.
Sale.vue
<template name="sale">
<input type="text" v-model="price" placeholder="Sale Price" class="form-control" #blur="onSale">
</template>
<script>
export default {
data(){
return {
price: null
}
},
methods: {
onSale(){
this.$emit('sale', this.price)
}
}
}
</script>
Vue
<sale v-if="showModal" #sale="calcFees"></sale>
const app = new Vue({
el: '#app',
data: {
showModal: false
},
methods: {
calcFees: function (price) {
alert(price);
}
}
});