Skip to content
This repository has been archived by the owner on Apr 17, 2022. It is now read-only.

What are the situations "setMenuPosition" runs or reposition the menu #81

Closed
Codefa opened this issue Jan 18, 2022 · 14 comments
Closed
Labels
bug Something isn't working
Milestone

Comments

@Codefa
Copy link

Codefa commented Jan 18, 2022

First of all thanks for this awesome date time picker in vuejs composition API.

Let's come to my issue
I have a carousel with multiple cards each cards have time label at top right, when I click there the date picker opens i can update the date or time that works well, Because of the carousel the last card date picker menu is little bit overflow to the right not visible the select button in viewport i fixed that by calculating the free space to the right side of the browser window and move a bit to the left to adjust the position that too works well, but when I click on any day, click on next,prev Arrow ( month's ) select a tim, then the menu recalculate the position and come back to the real one, how can I fix that ? is your version 2.5 comes as responsive one then that fixes this issue by default ?

@Jasenkoo
Copy link
Contributor

Can you provide some kind of a demo code so I could check the issue?

@Jasenkoo Jasenkoo added the bug Something isn't working label Jan 18, 2022
@Jasenkoo Jasenkoo added this to the v2.5.0 milestone Jan 18, 2022
@Codefa
Copy link
Author

Codefa commented Jan 18, 2022

Can you provide some kind of a demo code so I could check the issue?

sorry can't share the exact code because it's company project, anyway i will try to make a codesandbox demo based on the issue ( it will take some time sorry for that )

@Codefa
Copy link
Author

Codefa commented Jan 18, 2022

@Jasenkoo here is the demo Demo
please click on the last card ended label ( top right of the card ) ( if something not works open in incognito )
ignore the scrolling below ( not responsive now ) in my case it's responsive can't scroll again, thank you

@Jasenkoo
Copy link
Contributor

Tnx, will be fixed in v2.5

@Jasenkoo
Copy link
Contributor

Investigated your reported issue. So far this is an edge case and I can't provide some uni solution, since it may cause unwanted positioning behavior. In the upcoming version, there will be an option to stack multiple calendars one below another and not in a single row. Or I can also provide an event on position recalculation and you can handle it that way. Would that solve your issue?

I can also make a prop that will auto position based on on-screen position, but it may move depending on the window.

@Codefa
Copy link
Author

Codefa commented Jan 20, 2022

I understood I have to use the multiple calenders as now
I fixed the positioning by this way please check the codes
at first I call agendaDpOpen when opening the picker menu

agendaDpOpen() {
      setTimeout(() => {
        this.convertHtmlCollectionsToArray()
      })
    }

from there I have to get the dp__menu element

convertHtmlCollectionsToArray() {
      const shapesHC = document.getElementsByClassName('dp__menu')
      const shapesArrHCSpread = [...shapesHC]
      if (shapesArrHCSpread) {
        this.setDpMenuPosition(shapesArrHCSpread)
      }
    }

if I have the dp__menu element then call setDpMenuPosition to reposition the picker menu
(I really don't know how to access the dp__menu by ref )

then on setDpMenuPosition i do this I hope you can understand this block of codes.

setDpMenuPosition(shapesArrHCSpread) {
      let dpMenu = shapesArrHCSpread[0]
      const el = this.$refs && this.$refs.tcstBuilderAgendaDp

      if (el) {
        const { right, width } = el.getBoundingClientRect()
        const fullWidth = window.innerWidth

        const freeSpaceRight = fullWidth - right - width

        if (freeSpaceRight < 0) {
          const dpMenuStyle = dpMenu.style
          dpMenu.children[0].style.left = '90%'
          dpMenuStyle.animation = 'slide-out'
          dpMenuStyle.animationDuration = '0.5s'
          dpMenuStyle.animationDirection = 'forwards'
          dpMenuStyle.left = `${right - 239.4}px`
        }
      }
    }

this method works well on opening the picker menu, but when i click on next & prev month icon, select a time in a time-picker the position comes to old one, if you can alternate this code a little bit then I'm happy i can manage this issue like this for now.
if i can prevent reposition menu on other clicks or i can reposition again using this methods that will be helpfull.

@Jasenkoo
Copy link
Contributor

Ok, then I will emit an event when the calendar is repositioning, so you can handle the event @recalculatePosition="convertHtmlCollectionsToArray"

@Codefa
Copy link
Author

Codefa commented Jan 20, 2022

Ok, then I will emit an event when the calendar is repositioning, so you can handle the event @recalculatePosition="convertHtmlCollectionsToArray"

Yep I hope that will work well, thank you, is there any timeline for the 2.5.0 release ?
also i tried to use state driven css ( v-bind css varibles ) unfortunately that won't work inside a teleport ( known issue )

@Jasenkoo
Copy link
Contributor

At the end of the month, next weekend probably

@Codefa
Copy link
Author

Codefa commented Jan 20, 2022

@Jasenkoo I tired another trick to fix, it works well

Dynamic CSS varible method ( in vue 3 there is a state driven css( v-bind) that won't work here with this picker beacause of the teleport feature )

add a :root varible in the css section (initial left is 0px)

:root {
  --leftPos: 0;
}

inside setDpMenuPosition method add

const r = document.querySelector(':root')

then when there is no free space on the right assign

r.style.setProperty('--leftPos', `${right - 239.4}px`)

also we need a Boolean to know there is free space on right or not ( this is for adding conditional menuClassName
this.hasFreeSpaceRight = false
hasFreeSpaceRight deafault is true

then we need to add css to do the job

.dp-custom-menu-agenda-time {
  left: var(--leftPos) !important;
  animation: 0.5s forwards slide-out;
}
@keyframes slide-out {
  0% {
    transform: translateX(0%);
  }
  100% {
    transform: translateX(-50%);
  }
}

we can add this css class to date-picker component menuClassName

:menuClassName="!hasFreeSpaceRight ? 'dp-custom-menu-agenda-time' : ''"

Here is the full code of setDpMenuPosition

setDpMenuPosition(shapesArrHCSpread) {
      let dpMenu = shapesArrHCSpread[0]
      const el = this.$refs && this.$refs.tcstBuilderAgendaDp
      const r = document.querySelector(':root')

      if (el) {
        const { right, width } = el.getBoundingClientRect()
        const fullWidth = window.innerWidth
        const freeSpaceRight = fullWidth - right - width

        if (freeSpaceRight < 0) {
          this.hasFreeSpaceRight = false
          dpMenu.children[0].style.left = '90%'
          r.style.setProperty('--leftPos', `${right - 239.4}px`)
        }
      }
    },

this will do the fixes for now maybe usefull for someone who read this later

and I'm also waiting for your recalculatePosition event but maybe if recalculate the Position everytime there will be a little shaking for the menu i think, hope we can fix that with css ! ( please check this too )

@Jasenkoo
Copy link
Contributor

Will do, thanks 😄

Jasenkoo added a commit that referenced this issue Jan 20, 2022
- altPosition altered to accept both boolean or function
Jasenkoo added a commit that referenced this issue Jan 29, 2022
- altPosition altered to accept both boolean or function
@Jasenkoo
Copy link
Contributor

Included in the v2.5.0

@Codefa
Copy link
Author

Codefa commented Jan 31, 2022

@Jasenkoo I tried the new version sadly the issue is not resolved
the recalculation event is not emiting on

  • clicking on a date number in the calender
  • click on next or prev button to change the months
  • click on timepicker numbers

@Jasenkoo
Copy link
Contributor

@Codefa Ok, then the problem is not in the recalculatePosition, this might be happening because the CSS alters the position.

I've added an option on altPosition prop to pass a custom positioning function. You can use that instead of the setDpMenuPosition that you tried, make sure to return { top: string; left: string; } from that function and you can position the menu whenver. Also, if the recalculation method is called, it will call that function again, but since you don't get anything on the event, that is not a problem.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants