triniwiz / nativescript-pager

Apache License 2.0
90 stars 48 forks source link

Unshift + selectedIndex bugged #194

Open Sunhat opened 3 years ago

Sunhat commented 3 years ago

Which platform(s) does your issue occur on?

Please, provide the following version numbers that your issue occurs with:

Please, tell us how to recreate the issue in as much detail as possible.

I'm trying to use unshift to push more pages to the front as I scroll. Forcing Vue and forcing Pager to refresh doesn't appear to work.

Is this possible?

const arr = ['2021-01-01', '2021-02-01']
const selectedIndex = 0
arr.unshift('2020-12-01')

Pager shows '2021-01-01' and cannot swipe left to new previous slide

triniwiz commented 3 years ago

Can you try using an observable array ?

Sunhat commented 3 years ago

Thanks for responding @triniwiz, I've tried a few different ideas including

What I'm aiming to do it, as the user swipes to 0th index of the array, I add more items to the array and remove items from the end

<Pager :selectedIndex="selectedIndex" for="month in months" @selectedIndexChanged="selectedIndexChanged">
    <v-template>
        <MonthCalendar :month="month" />
    </v-template>
</Pager>

<script>
const getMonths = (startDate: Date) => {
    // array of 5 dates, if startDate = today, [2] = 1st of this month, [1] = 1st of last month
    return []; 
}

import { ObservableArray } from '..'
export default {
     data: () => ({
         selectedIndex: 2,
         months: new ObservableArray(getMonths(new Date)),
     }),

}
</script>
Sunhat commented 3 years ago

Hi @triniwiz, it's quite vital that I get this sorted and offering a bounty for this to be fixed is on the table for me - Thanks!

triniwiz commented 3 years ago

Looking at your code you're recreating a new ObservableArray each time "the user swipes to 0th index of the array" you don't want to do this it's basically the same as using a regular array if you're removing an adding items to the end you should go for splice . You don't want to set a new ObservableArray if u wanna set a fresh set of data u can still use spice

Sunhat commented 3 years ago

I'll get back to you in the next few days I hope - Please keep this ticket open

Sunhat commented 3 years ago
                <Pager
                    cache="false"
                    ref="pager"
                    height="100%"
                    width="100%"
                    :selectedIndex="selectedIndex"
                    :disableSwipe="disableSwipe"
                    @selectedIndexChange="selectedIndexChanged($event)"
                    for="day in monthDays"
                >
                    <v-template>
                        <StackLayout>
                            <SingleMonth
                                :month-of="day"
                            />
                        </StackLayout>
                    </v-template>
                </Pager>

JS:


const getStartDate = () => {
    const date = new Date()
    date.setDate(1)
    return date
}

const generateMonthDays = (startDate: Date) => {
    startDate.setDate(1)
    const day0 = new Date(startDate.getTime())
    day0.setMonth(startDate.getMonth() - 2)
    const day1 = new Date(startDate.getTime())
    day1.setMonth(startDate.getMonth() - 1)
    const day3 = new Date(startDate.getTime())
    day3.setMonth(startDate.getMonth() + 1)
    const day4 = new Date(startDate.getTime())
    day4.setMonth(startDate.getMonth() + 2)
    return new ObservableArray([
        day0, day1,
        startDate,
        day3, day4,
    ])
}
export default {
data: () => ({
    monthDays: generateMonthDays(getStartDate()),
}),
methods: {

        refresh() {
            // console.log(this.$refs)
            if (this.$refs.pager) {
                this.$nextTick(() => {
                    console.log('this.selectedIndex')
                    console.log(this.selectedIndex)
                    this.$refs.pager.nativeView.refresh(false)
                })
            }
        },
        selectedIndexChanged (event) {
            const from = this.selectedIndex
            const to = event
            this.selectedIndex = to
            this.selectedDay = this.monthDays.getItem(to)
            if (to > from) {
                const lastItem = this.monthDays.getItem(this.monthDays.length - 1)
                const nextItem = new Date(lastItem.getTime())
                nextItem.setMonth(nextItem.getMonth() + 1)
                // this.monthDays.push(nextItem)
            }

            this.swipeEnabled = true
        },
},
}
triniwiz commented 3 years ago
  1. You don't need refresh once you're using an ObservableArray
  2. Can you try removing for="day in monthDays" an attach a @loaded event then set the items when that fires event.object.items = yourObservableArray and lmk what happens
Sunhat commented 3 years ago
                <Pager
                    ref="pager"
                    height="100%"
                    width="100%"
                    for="day in months"
                >
                    <v-template>
                        <StackLayout>
                            <Label :text="day"/>
                        </StackLayout>
                    </v-template>
                </Pager>
    data () {
        return {
            months: new ObservableArray(['jan', 'feb', 'march', 'ap', 'may', 'jun', 'jul', 'aug', 'sept', 'oct', 'nov', 'december']),
        }
    }

Thanks for the quick reply

I just came back to add that the code above the slides go jan -> feb -> march -> april -> may -> june -> july -> august-> september -> october -> november -> jan

and adding further elements to the end of the array

data() => ({
      months: new ObservableArray(['jan', 'feb', 'march', 'ap', 'may', 'jun', 'jul', 'aug', 'sept', 'oct', 'nov', 'december', 'test']),
})

goes

jan -> feb -> march -> april -> may -> june -> july -> august-> september -> october -> november -> jan -> feb


Thanks yeah I know that refresh shouldn't be necessary but I thought it was worth observing it's behaviour and it seems odd to me

I'll give what you suggested a go now