mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
feat(components): [el-message] & [el-notification] appendTo option added (#4012)
* feat(components): [el-message] & [el-notification] appendTo option added * fix(components): unit test and replaced warn with debugWarn
This commit is contained in:
@@ -87,4 +87,32 @@ describe('Message on command', () => {
|
||||
expect(Message.info).toBeInstanceOf(Function)
|
||||
expect(Message.error).toBeInstanceOf(Function)
|
||||
})
|
||||
|
||||
test('it should appendTo specified HTMLElement', async () => {
|
||||
const htmlElement = document.createElement('div')
|
||||
const handle = Message({
|
||||
appendTo: htmlElement,
|
||||
})
|
||||
await rAF()
|
||||
expect(htmlElement.querySelector(selector)).toBeTruthy()
|
||||
handle.close()
|
||||
await rAF()
|
||||
await nextTick()
|
||||
expect(htmlElement.querySelector(selector)).toBeFalsy()
|
||||
})
|
||||
|
||||
test('it should appendTo specified selector', async () => {
|
||||
const htmlElement = document.createElement('div')
|
||||
htmlElement.classList.add('message-manager')
|
||||
document.body.appendChild(htmlElement)
|
||||
const handle = Message({
|
||||
appendTo: '.message-manager',
|
||||
})
|
||||
await rAF()
|
||||
expect(htmlElement.querySelector(selector)).toBeTruthy()
|
||||
handle.close()
|
||||
await rAF()
|
||||
await nextTick()
|
||||
expect(htmlElement.querySelector(selector)).toBeFalsy()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,6 +2,7 @@ import { createVNode, render } from 'vue'
|
||||
import { isVNode } from '@element-plus/utils/util'
|
||||
import PopupManager from '@element-plus/utils/popup-manager'
|
||||
import isServer from '@element-plus/utils/isServer'
|
||||
import { debugWarn } from '@element-plus/utils/error'
|
||||
import MessageConstructor from './message.vue'
|
||||
import { messageTypes } from './message'
|
||||
|
||||
@@ -38,6 +39,21 @@ const message: MessageFn & Partial<Message> = function (options = {}) {
|
||||
},
|
||||
}
|
||||
|
||||
let appendTo: HTMLElement | null = document.body
|
||||
if (options.appendTo instanceof HTMLElement) {
|
||||
appendTo = options.appendTo
|
||||
} else if (typeof options.appendTo === 'string') {
|
||||
appendTo = document.querySelector(options.appendTo)
|
||||
}
|
||||
// should fallback to default value with a warning
|
||||
if (!(appendTo instanceof HTMLElement)) {
|
||||
debugWarn(
|
||||
'ElMessage',
|
||||
'the appendTo option is not an HTMLElement. Falling back to document.body.'
|
||||
)
|
||||
appendTo = document.body
|
||||
}
|
||||
|
||||
const container = document.createElement('div')
|
||||
|
||||
container.className = `container_${id}`
|
||||
@@ -60,7 +76,7 @@ const message: MessageFn & Partial<Message> = function (options = {}) {
|
||||
render(vm, container)
|
||||
// instances will remove this item when close function gets called. So we do not need to worry about it.
|
||||
instances.push({ vm })
|
||||
document.body.appendChild(container.firstElementChild!)
|
||||
appendTo.appendChild(container.firstElementChild!)
|
||||
|
||||
return {
|
||||
// instead of calling the onClose function directly, setting this value so that we can have the full lifecycle
|
||||
|
||||
@@ -62,7 +62,9 @@ export const messageEmits = {
|
||||
}
|
||||
export type MessageEmits = typeof messageEmits
|
||||
|
||||
export type MessageOptions = Omit<MessageProps, 'id'>
|
||||
export type MessageOptions = Omit<MessageProps, 'id'> & {
|
||||
appendTo?: HTMLElement | string
|
||||
}
|
||||
export type MessageOptionsTyped = Omit<MessageOptions, 'type'>
|
||||
|
||||
export interface MessageHandle {
|
||||
|
||||
@@ -80,4 +80,33 @@ describe('Notification on command', () => {
|
||||
expect(document.querySelector(`.el-icon-${type}`)).toBeDefined()
|
||||
}
|
||||
})
|
||||
|
||||
test('it should appendTo specified HTMLElement', async () => {
|
||||
const htmlElement = document.createElement('div')
|
||||
const handle = Notification({
|
||||
appendTo: htmlElement,
|
||||
})
|
||||
await rAF()
|
||||
expect(htmlElement.querySelector(selector)).toBeDefined()
|
||||
|
||||
handle.close()
|
||||
await rAF()
|
||||
await nextTick()
|
||||
expect(htmlElement.querySelector(selector)).toBeNull()
|
||||
})
|
||||
|
||||
test('it should appendTo specified selector', async () => {
|
||||
const htmlElement = document.createElement('div')
|
||||
htmlElement.classList.add('notification-manager')
|
||||
document.body.appendChild(htmlElement)
|
||||
const handle = Notification({
|
||||
appendTo: '.notification-manager',
|
||||
})
|
||||
await rAF()
|
||||
expect(htmlElement.querySelector(selector)).toBeDefined()
|
||||
handle.close()
|
||||
await rAF()
|
||||
await nextTick()
|
||||
expect(htmlElement.querySelector(selector)).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -76,7 +76,9 @@ export const notificationEmits = {
|
||||
}
|
||||
export type NotificationEmits = typeof notificationEmits
|
||||
|
||||
export type NotificationOptions = Omit<NotificationProps, 'id'>
|
||||
export type NotificationOptions = Omit<NotificationProps, 'id'> & {
|
||||
appendTo?: HTMLElement | string
|
||||
}
|
||||
export type NotificationOptionsTyped = Omit<NotificationOptions, 'type'>
|
||||
|
||||
export interface NotificationHandle {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { createVNode, render } from 'vue'
|
||||
import isServer from '@element-plus/utils/isServer'
|
||||
import PopupManager from '@element-plus/utils/popup-manager'
|
||||
import { isVNode } from '@element-plus/utils/util'
|
||||
import { debugWarn } from '@element-plus/utils/error'
|
||||
import NotificationConstructor from './notification.vue'
|
||||
import { notificationTypes } from './notification'
|
||||
|
||||
@@ -57,6 +58,22 @@ const notify: NotifyFn & Partial<Notify> = function (options = {}) {
|
||||
},
|
||||
}
|
||||
|
||||
let appendTo: HTMLElement | null = document.body
|
||||
if (options.appendTo instanceof HTMLElement) {
|
||||
appendTo = options.appendTo
|
||||
} else if (typeof options.appendTo === 'string') {
|
||||
appendTo = document.querySelector(options.appendTo)
|
||||
}
|
||||
|
||||
// should fallback to default value with a warning
|
||||
if (!(appendTo instanceof HTMLElement)) {
|
||||
debugWarn(
|
||||
'ElNotification',
|
||||
'the appendTo option is not an HTMLElement. Falling back to document.body.'
|
||||
)
|
||||
appendTo = document.body
|
||||
}
|
||||
|
||||
const container = document.createElement('div')
|
||||
|
||||
const vm = createVNode(
|
||||
@@ -77,7 +94,7 @@ const notify: NotifyFn & Partial<Notify> = function (options = {}) {
|
||||
// instances will remove this item when close function gets called. So we do not need to worry about it.
|
||||
render(vm, container)
|
||||
notifications[position].push({ vm })
|
||||
document.body.appendChild(container.firstElementChild!)
|
||||
appendTo.appendChild(container.firstElementChild!)
|
||||
|
||||
return {
|
||||
// instead of calling the onClose function directly, setting this value so that we can have the full lifecycle
|
||||
|
||||
Reference in New Issue
Block a user