Replies: 5 comments 4 replies
-
I probably need more details to understand your situation. If this isn't working, what's the actual behavior vs. what's the expected behavior. Also, it would be helpful to have a way to preview your app so that it can be debugged. |
Beta Was this translation helpful? Give feedback.
-
The goal is a nested modal. so you open a modal menu, which has a button to open another modal menu etc, each level of modal should have a clickable background input blocker which only closes that modal and leaves all others open. |
Beta Was this translation helpful? Give feedback.
-
const { button, div } = van.tags
const dropdowns = vanX.reactive([])
const Dropdowns = () => {
return vanX.list(div({ class: 'absolute noInput fill' }), dropdowns, dropdown => {
prnt('dropdown func ', dropdown)
return div({
class: 'input absolute fill red',
style: '',
onclick: (e) => {
prnt('click')
vanX.replace(dropdowns, dropdowns.filter(d => d.func !== dropdown.func))
},
}, dropdown.func)
})
}
function showDropdown(dropdown, e) {
const target = e.target
const targetPos = target.getBoundingClientRect()
const pos = { x: targetPos.left, y: targetPos.top + targetPos.height }
dropdowns.push({
func: dropdown,
pos
})
}
const File = () => {
return div('File', button({ onclick: (e) => { showDropdown(Help(), e) } }, 'Help'))
}
const Help = () => {
return div('Help')
}
const Home = () => {
const el = div(
{ class: 'bigButtons panel', style: 'width:15rem;' },
button({ onclick: (e) => { showDropdown(File(), e) } }, 'File'),
Dropdowns()
)
return el
}
van.add(document.body, Home()) File and Help do not appear when clicking the button to fire showDropdown |
Beta Was this translation helpful? Give feedback.
-
@sirenkovladd Thank you, () => dropdown.val.func did the trick. Here is the final nested modals component: const dropdowns = vanX.reactive([])
const Dropdowns = () => {
return vanX.list(div({ class: 'absolute noInput fill' }), dropdowns, dropdown => {
return div({
class: 'fill dark absolute dropdownbackdrop input',
onclick: (e) => {
if (e.target.classList.contains('dropdownbackdrop')) {
timers.dropdown = requestAnimationFrame(() => {
console.log('click outside modal')
vanX.replace(dropdowns, dropdowns.slice(0, -1))
})
}
},
}, div({ style: `position:absolute;left:${dropdown.val.pos.x}px;top:${dropdown.val.pos.y}px;` }, () => dropdown.val.func))
})
}
function showDropdown (dropdown, e, position = 'bottom') {
const target = e.target
const targetPos = target.getBoundingClientRect()
let pos = { x: targetPos.left, y: targetPos.top + targetPos.height }
switch (position) {
case 'right':
pos = { x: targetPos.left + targetPos.width + 4, y: targetPos.top - 3 }
break
}
dropdowns.push({
func: vanX.noreactive(dropdown),
pos
})
} |
Beta Was this translation helpful? Give feedback.
-
function showDropdown (dropdown, e, position = 'bottom') {
const target = e.target
const targetPos = target.getBoundingClientRect()
let pos = { x: targetPos.left, y: targetPos.top + targetPos.height }
switch (position) {
case 'right':
pos = { x: targetPos.left + targetPos.width + 4, y: targetPos.top - 3 }
break
}
const modal = { func: vanX.noreactive(dropdown), pos }
dropdowns.push({ func: vanX.noreactive(dropdown), pos })
timers.dropdown2 = setTimeout(() => { clampToWindow2(dropdowns[dropdowns.length - 1].func) }, 200)
} Adding this line function clampToWindow2 (element) {
timers.clamp = requestAnimationFrame(() => {
const rect = element.getBoundingClientRect()
const windowHeight = window.innerHeight
const windowWidth = window.innerWidth
const maxX = windowWidth - rect.width
const maxY = windowHeight - rect.height
const clampedX = Math.min(maxX, Math.max(0, rect.left))
const clampedY = Math.min(maxY, Math.max(0, rect.top))
prnt('clamp 2', clampedX, clampedY)
element.style.left = clampedX + 'px'
element.style.top = clampedY + 'px'
})
} it was working fine in this single dropdown version: const showDropdown = () => {
if (dropdown.val) { dropdown.val = false; state.isOpen = false; return }
state.isOpen = true
dropdown.val = DropdownMenu({ x: inp.start.x, y: inp.start.y })
timers.toggleDropdown = requestAnimationFrame(() => {
clampToWindow2(dropdown.val)
timers.toggleDropdown2 = requestAnimationFrame(() => {
dropdown.val.classList.remove('transparent')
})
})
} How can I get this to work with the dropdowns array version? |
Beta Was this translation helpful? Give feedback.
-
I'm trying to create a nested modal system:
So you can open nested menus within menus and close them one level at a time. This approach isn't working, is there a more vanJS way to do it?
Beta Was this translation helpful? Give feedback.
All reactions