Skip to content

Commit 835bb02

Browse files
tmorehousejacobmllr95
authored andcommitted
chore(alert): code refactoring (closes #2967) (#2969)
* Update alert.js * Update alert.js * Update alert.js * Update alert.spec.js * Update alert.spec.js * Update alert.js * Update alert.js * Update alert.spec.js * Update alert.js * Update alert.js * Update alert.js * Update alert.js * add support for countodown number (via `show` prop) as a string number * Update alert.js * Update alert.spec.js * Update alert.spec.js * Update alert.spec.js * Update alert.spec.js * Update alert.spec.js * Update alert.spec.js * Update alert.js * Update alert.js * Update alert.js * Update alert.js * Update alert.spec.js * Update alert.js * Update package.json * Update README.md * Update alert.spec.js * Update alert.js
1 parent d30fafe commit 835bb02

File tree

4 files changed

+271
-54
lines changed

4 files changed

+271
-54
lines changed

src/components/alert/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,6 @@ Use the `fade` prop to enable animation. By default alerts are not animated.
238238
dismissible
239239
fade
240240
variant="warning"
241-
@dismissed="dismissCountDown=0"
242241
@dismiss-count-down="countDownChanged"
243242
>
244243
This alert will dismiss after {{ dismissCountDown }} seconds...

src/components/alert/alert.js

Lines changed: 73 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,33 @@ import { requestAF } from '../../utils/dom'
44

55
const NAME = 'BAlert'
66

7+
// Convert `show` value to a number
8+
const parseCountDown = show => {
9+
if (show === '' || typeof show === 'boolean') {
10+
return 0
11+
}
12+
show = parseInt(show, 10)
13+
return show > 0 ? show : 0
14+
}
15+
16+
// Convert `show` value to a boolean
17+
const parseShow = show => {
18+
if (show === '' || show === true) {
19+
return true
20+
}
21+
if (parseInt(show, 10) < 1) {
22+
// Boolean will always return false for the above comparison
23+
return false
24+
}
25+
return Boolean(show)
26+
}
27+
28+
// Is a value number like (i.e. a number or a number as string)
29+
const isNumericLike = value => !isNaN(parseInt(value, 10))
30+
731
// @vue/component
832
export default {
933
name: NAME,
10-
components: { BButtonClose },
1134
model: {
1235
prop: 'show',
1336
event: 'input'
@@ -26,7 +49,7 @@ export default {
2649
default: () => getComponentConfig(NAME, 'dismissLabel')
2750
},
2851
show: {
29-
type: [Boolean, Number],
52+
type: [Boolean, Number, String],
3053
default: false
3154
},
3255
fade: {
@@ -37,71 +60,74 @@ export default {
3760
data() {
3861
return {
3962
countDownTimerId: null,
40-
dismissed: false,
41-
localShow: this.show,
63+
countDown: 0,
64+
// If initially shown, we need to set these for SSR
65+
localShow: parseShow(this.show),
4266
showClass: this.fade && this.show
4367
}
4468
},
4569
watch: {
4670
show(newVal) {
47-
this.showChanged(newVal)
71+
this.countDown = parseCountDown(newVal)
72+
this.localShow = parseShow(newVal)
73+
},
74+
countDown(newVal) {
75+
this.clearTimer()
76+
this.$emit('dismiss-count-down', newVal)
77+
if (this.show !== newVal) {
78+
// Update the v-model if needed
79+
this.$emit('input', newVal)
80+
}
81+
if (newVal > 0) {
82+
this.localShow = true
83+
this.countDownTimerId = setTimeout(() => {
84+
this.countDown--
85+
}, 1000)
86+
} else {
87+
// Slightly delay the hide to allow any UI updates
88+
this.$nextTick(() => {
89+
requestAF(() => {
90+
this.localShow = false
91+
})
92+
})
93+
}
4894
},
49-
dismissed(newVal) {
50-
if (newVal) {
51-
this.localShow = false
95+
localShow(newVal) {
96+
if (!newVal && (this.dismissible || isNumericLike(this.show))) {
97+
// Only emit dismissed events for dismissible or auto dismissing alerts
5298
this.$emit('dismissed')
5399
}
100+
if (!isNumericLike(this.show) && this.show !== newVal) {
101+
// Only emit booleans if we weren't passed a number via `this.show`
102+
this.$emit('input', newVal)
103+
}
54104
}
55105
},
106+
created() {
107+
this.countDown = parseCountDown(this.show)
108+
this.localShow = parseShow(this.show)
109+
},
56110
mounted() {
57-
this.showChanged(this.show)
111+
this.countDown = parseCountDown(this.show)
112+
this.localShow = parseShow(this.show)
58113
},
59-
destroyed /* istanbul ignore next */() {
60-
this.clearCounter()
114+
beforeDestroy() {
115+
this.clearTimer()
61116
},
62117
methods: {
63118
dismiss() {
64-
this.clearCounter()
65-
if (typeof this.show === 'number') {
66-
this.$emit('dismiss-count-down', 0)
67-
this.$emit('input', 0)
68-
} else {
69-
this.$emit('input', false)
70-
}
71-
this.dismissed = true
119+
this.clearTimer()
120+
this.countDown = 0
121+
this.localShow = false
72122
},
73-
clearCounter() {
123+
clearTimer() {
74124
if (this.countDownTimerId) {
75125
clearInterval(this.countDownTimerId)
76126
this.countDownTimerId = null
77127
}
78128
},
79-
showChanged(show) {
80-
// Reset counter status
81-
this.clearCounter()
82-
// Reset dismiss status
83-
this.dismissed = false
84-
// Set localShow state
85-
this.localShow = Boolean(show)
86-
// No timer for boolean values
87-
if (show === true || show === false || show === null || show === 0) {
88-
return
89-
}
90-
// Start counter (ensure we have an integer value)
91-
let dismissCountDown = parseInt(show, 10) || 1
92-
this.countDownTimerId = setInterval(() => {
93-
if (dismissCountDown < 1) {
94-
this.dismiss()
95-
return
96-
}
97-
dismissCountDown--
98-
this.$emit('dismiss-count-down', dismissCountDown)
99-
this.$emit('input', dismissCountDown)
100-
}, 1000)
101-
},
102129
onBeforeEnter() {
103130
if (this.fade) {
104-
// Add show class one frame after inserted, to make transitions work
105131
requestAF(() => {
106132
this.showClass = true
107133
})
@@ -113,12 +139,13 @@ export default {
113139
},
114140
render(h) {
115141
const $slots = this.$slots
116-
let $alert = h(false)
142+
let $alert // undefined
117143
if (this.localShow) {
118144
let $dismissBtn = h(false)
119145
if (this.dismissible) {
146+
// Add dismiss button
120147
$dismissBtn = h(
121-
'b-button-close',
148+
BButtonClose,
122149
{ attrs: { 'aria-label': this.dismissLabel }, on: { click: this.dismiss } },
123150
[$slots.dismiss]
124151
)
@@ -143,8 +170,6 @@ export default {
143170
'transition',
144171
{
145172
props: {
146-
mode: 'out-in',
147-
// Disable use of built-in transition classes
148173
'enter-class': '',
149174
'enter-active-class': '',
150175
'enter-to-class': '',

0 commit comments

Comments
 (0)