Permalink
Browse files

fix v-b-modal directive unbinding (#1617)

This fixes #1613 keeping the default behavior of utils/target untouched.
Multiple event listeners for event type are possible and they are unbound all together.
  • Loading branch information...
dmocho authored and mosinve committed Feb 15, 2018
1 parent 4464f0a commit 3f6a86aee83d1ef88a4070307a8da64bdd0be836
@@ -1,6 +1,6 @@
<div id="app">
<b-btn v-b-modal.modal1>Launch demo modal</b-btn>
<b-btn ref="modalButton" v-b-modal.modal1 v-if="enableModal">Launch demo modal</b-btn>
<b-btn ref="button" v-else>Doesn't launch modal</b-btn>
<!-- Main UI -->
<div class="mt-3 mb-3">
Submitted Names:
@@ -10,7 +10,8 @@
</div>
<!-- Modal Component -->
<b-modal id="modal1"
<b-modal ref="modal"
id="modal1"
title="Submit your name"
header-bg-variant="info"
header-text-variant="light"
@@ -2,7 +2,8 @@ window.app = new Vue({
el: '#app',
data: {
name: '',
names: []
names: [],
enableModal: true
},
methods: {
clearName () {
@@ -1,6 +1,20 @@
import {loadFixture, testVM} from '../../../tests/utils'
import {loadFixture, testVM, nextTick} from '../../../tests/utils'
describe('modal', async () => {
beforeEach(loadFixture(__dirname, 'modal'))
testVM()
it('Should bind event handler', async () => {
const { app } = window
expect(app.$refs.modalButton).toHaveProperty('__BV_boundEventListeners__.click')
})
it('Should unbind event handler', async () => {
const { app } = window
app.enableModal = false
await nextTick()
expect(app.$refs.button).not.toHaveProperty('__BV_boundEventListeners__.click')
})
})
@@ -1,12 +1,12 @@
import target from '../../utils/target'
import { setAttr } from '../../utils/dom'
import { bindTargets, unbindTargets } from '../../utils/target'
import { setAttr, removeAttr } from '../../utils/dom'
const listenTypes = {click: true}
export default {
// eslint-disable-next-line no-shadow-restricted-names
bind (el, binding, vnode) {
target(vnode, binding, listenTypes, ({targets, vnode}) => {
bindTargets(vnode, binding, listenTypes, ({targets, vnode}) => {
targets.forEach(target => {
vnode.context.$root.$emit('bv::show::modal', target, vnode.elm)
})
@@ -15,5 +15,12 @@ export default {
// If element is not a button, we add `role="button"` for accessibility
setAttr(el, 'role', 'button')
}
},
unbind (el, binding, vnode) {
unbindTargets(vnode, binding, listenTypes)
if (el.tagName !== 'BUTTON') {
// If element is not a button, we add `role="button"` for accessibility
removeAttr(el, 'role', 'button')
}
}
}
@@ -2,7 +2,9 @@ import { keys } from '../utils/object'
const allListenTypes = {hover: true, click: true, focus: true}
export default function targets (vnode, binding, listenTypes, fn) {
const BVBoundListeners = '__BV_boundEventListeners__'
const bindTargets = (vnode, binding, listenTypes, fn) => {
const targets = keys(binding.modifiers || {})
.filter(t => !allListenTypes[t])
@@ -17,9 +19,32 @@ export default function targets (vnode, binding, listenTypes, fn) {
keys(allListenTypes).forEach(type => {
if (listenTypes[type] || binding.modifiers[type]) {
vnode.elm.addEventListener(type, listener)
const boundListeners = vnode.elm[BVBoundListeners] || {}
boundListeners[type] = boundListeners[type] || []
boundListeners[type].push(listener)
vnode.elm[BVBoundListeners] = boundListeners
}
})
// Return the list of targets
return targets
}
const unbindTargets = (vnode, binding, listenTypes) => {
keys(allListenTypes).forEach(type => {
if (listenTypes[type] || binding.modifiers[type]) {
const boundListeners = vnode.elm[BVBoundListeners] && vnode.elm[BVBoundListeners][type]
if (boundListeners) {
boundListeners.forEach(listener => vnode.elm.removeEventListener(type, listener))
delete vnode.elm[BVBoundListeners][type]
}
}
})
}
export {
bindTargets,
unbindTargets
}
export default bindTargets

0 comments on commit 3f6a86a

Please sign in to comment.