Problem with back-link when routing to the main-view from a panel


#1

Hi,

I have a small issue on a project I am working on.

I have a main view and a side panel, when routing normally through the main view the back links work flawlessly. However, if I select a link from my side panel that has ‘link-view="#main-view"’ set to open the link in the main view the back link navigation causes a lot of issues in the main view.

The correct router history is there but when moving back through the pages only the navbar title updates and the page is completely wrong.

Any help or a point in the right direction would be much appreciated.


#2

@nolimits4web do you have any idea on this issue? I know you’re a busy man but if there is any documentation anywhere regarding routing from side panel to main view? Should it be possible?


#3

history заполняется как-то не так, если вы перешли по ссылке из панели? Проведите небольшое исследование, посмотрите консоль, сравните с kitchen.


#4

Нет, история пополняется отлично. Он даже удаляет элементы, когда я возвращаюсь назад. Он даже меняет навигационную панель на правильную страницу, но отображаемая страница является моей «домашней» страницей. Нет ошибок в консоли. Я сейчас запишу видео, надеюсь, это поможет


#5

Video of the issue… I also noticed that the panel also has an issue when the router does, as can be seen at the end of the video. https://drive.google.com/open?id=1zB97Atr0h28m-cURSCIA62tZh8UVCNJB


#6

Возьмите cli, создайте минимальный пример, который содержит ошибку, и закиньте на GitHub. Если ошибки не будет, значит что-то у вас в коде не так.


#7

data-view, а не link-view


#8

There is something wrong in the code, under the hood there is no difference when you call link directly on view or with link-view prop (in Vue). There should be somthing on your side that breaks it. First of all, you don’t call somewhere else in pages router’s .navigate() or .back() methods withing pageInit or mounted hooks. Also, check the data in this pages that loaded with Ajax, if you request it on mounted()/created() try to move it to pageAfterIn event handler. And finally, if you have push-state enabled, make sure it is enabled only on main view


#9

Thank you for the help, I have moved all of my mounted code to the @page:afterin , but now I face a different error and it must be to do with the product.vue page as this is the only one causing issues now.

The ‘pageAfterIn’ gets fired when navigating back to the product page, all of the DOM elements are there with all the correct product information in them, but the page is blank.

I have recorded another video and will provide the full product.vue page here for you.

Here is the video: https://drive.google.com/open?id=1TRfK5kDH9lzRXm4jTg3-99yQFwy9TJDi

Here is the product.vue:

<template>
  <f7-page @page:afterin="init">
    <f7-navbar sliding :back-link="category.title">
      <f7-nav-title>
        {{product.title}}
      </f7-nav-title>
      <f7-nav-right>
        <f7-link icon-f7="icon-bars" panel-open="right"></f7-link>
      </f7-nav-right>
    </f7-navbar>
    <f7-toolbar :bottom-md="true" class="product-toolbar">
      <f7-link :text-color="$store.getters.colorTheme">Total: £{{total}}</f7-link>
      <f7-link :text-color="$store.getters.colorTheme" @click="addToCart()" v-if="orderable">Add To Basket</f7-link>
    </f7-toolbar>

    <f7-block strong inset>
      <f7-swiper data-space-between="100" data-centered-slides="true" pagination navigation
        v-if="product.photos.length > 0">
        <f7-swiper-slide v-for="(photo, index) in product.photos" :key="`product-photo-${photo.id}`"
          @click.native="openBrowser(index)">
          <div style="height:auto; width:100%;">
            <img :src="photo.image" style="display:block; margin:auto; width:100%;" />
          </div>
        </f7-swiper-slide>
      </f7-swiper>
      <h1>{{product.title}}</h1>
      <h3>£{{price}}</h3>
      <h4 v-if="product.qty == 0" style="color:crimson;">OUT OF STOCK</h4>
      <p>{{product.description}}</p>
      <f7-list>

        <f7-list-item v-for="option in product.options" :key="`option${option.id}`" :title="`${option.title}`"
          smart-select
          :smart-select-params="{openIn: 'popup', closeOnSelect:true, formColorTheme:$store.getters.colorTheme, navbarColorTheme: $store.getters.colorTheme, cssClass: ($store.getters.darkTheme) ? 'theme-dark' : '',}">
          <select v-if="!option.unique" :name="option.id" :id="option.id" multiple @change="calculate()">
            <option selected disabled value="null">Please Select One</option>
            <option v-for="item in option.items" :key="`iop-${item.id}`" :value="item.id" :id="`item${item.id}`"
              :data-price="item.price" :data-display-as="item.title">{{item.title}}&emsp;[+£{{item.price}}]</option>
          </select>
          <select v-if="option.unique" :name="option.id" :id="option.id" @change="calculate()">
            <option selected disabled value="null">Please Select One</option>
            <option v-for="item in option.items" :key="`iop-${item.id}`" :value="item.id" :id="`item${item.id}`"
              :data-price="item.price" :data-display-as="item.title">{{item.title}}&emsp;[+£{{item.price}}]</option>
          </select>
        </f7-list-item>

        <f7-list-item smart-select :smart-select-params="{openIn: 'popover',closeOnSelect:true}" title="Qty"
          v-if="max_qty > 0">
          <select id="qty" @change="calculate()">
            <option v-for="n in max_qty" :key="`qty${n}`" :value="n">{{n}}</option>
          </select>
        </f7-list-item>

        <f7-list-item v-if="max_qty < 1">
          Max quantity reached for this item
        </f7-list-item>
      </f7-list>

    </f7-block>
    
  </f7-page>
</template>
<script>
  export default {
    props: {
      productID: String
    },
    data() {
      return {
        product: {
          title: '',
          photos: [],
          options: []
        },
        category: {
          title: ''
        },
        qty: 1,
        loading: true,
        effect: 'blink',
        price: 0.00,
        total: 0.00,
        selected_options: [],
        selected_options_text: [],
        orderable: false,
        max_qty: 10,
        photoBrowser: null
      }
    },
    mounted() {

    },
    methods: {
      init() {
        console.log('PRODUCT INIT');
        const self = this;
        const app = self.$f7;
        const store = self.$store;
        let product = store.getters.product(self.productID);
        if (product) {
          self.product = product;
          self.total = product.price;
          self.price = product.price;
          if (self.product.qty != null) {
            self.max_qty = store.getters.qtyLeftForProduct(self.productID);
          }
        }

        self.photoBrowser = app.photoBrowser.create({
          photos: self.photo_browser(),
          type: 'page',
          theme: (store.getters.darkTheme) ? 'dark' : 'light',
          iconsColor: store.getters.colorTheme
        });

        app.preloader.show();
        store.dispatch('getProduct', self.productID)
          .then(data => {
            self.loading = false;
            self.product = data;
            self.total = self.product.price;
            self.price = self.product.price;
            if (self.product.qty != null) {
              self.max_qty = store.getters.qtyLeftForProduct(self.productID);
            }
            self.category = store.getters.category(self.product.product_category_id);
          })
          .catch(error => {
            console.error('Get product Error ', error);
          }).finally(res => {
            app.preloader.hide();
            self.calculate();
          });
      },
      calculate() {
        const self = this;
        let qty = self.$$('#qty').val();
        if (qty == null) {
          self.qty == 1;
        } else {
          self.qty = qty;
        }
        var price = parseFloat(self.product.price);
        var options = self.product.options;
        var so = [];
        var option_text = [];
        var orderable = true;

        for (var o in options) {
          var selected_options = self.$$(`#${options[o].id}`).val();
          if (selected_options != null && selected_options != 'null') {
            so.push(selected_options);
          }
          if (options[o].required) {
            if (selected_options == null || selected_options == "null") {
              orderable = false;
            }
          }
        }

        for (var o in so) {
          if (Array.isArray(so[o])) {
            for (var i in so[o]) {
              option_text.push(self.$$(`#item${so[o][i]}`).text().replace(/ *\[[^\]]*]/, ''));
              price += parseFloat(self.$$(`#item${so[o][i]}`).attr('data-price'));
            }
          } else {
            option_text.push(self.$$(`#item${so[o]}`).text().replace(/ *\[[^\]]*]/, ''));
            price += parseFloat(self.$$(`#item${so[o]}`).attr('data-price'));
          }
        }

        self.price = price.toFixed(2);
        price *= self.qty;
        self.total = price.toFixed(2);
        self.selected_options = so;
        self.selected_options_text = option_text;
        if (self.max_qty < 1) {
          orderable = false;
        }
        self.orderable = orderable;
      },
      addToCart: function () {
        const self = this;
        const app = self.$f7;
        const store = self.$store;
        const router = self.$f7router;
        var item = {
          productID: self.productID,
          qty: self.qty,
          title: self.product.title,
          selected_options: self.selected_options,
          selected_options_text: self.selected_options_text,
          price: self.price,
          total: self.total
        };
        app.toast.create({
          icon: '<i class="f7-icons">check</i>',
          text: 'Item added to basket',
          position: 'center',
          closeTimeout: 2000,
        }).open();
        store.commit('addItemToCart', item);
        router.back();
      },
      openBrowser(index) {
        this.photoBrowser.open(index);
      },
      photo_browser() {
        const self = this;
        const app = self.$f7;
        const store = self.$store;
        let res = [];
        for (var i = 0; i < self.product.photos.length; i++) {
          let p = {
            url: self.product.photos[i].image,
          }
          res.push(p);
        }
        return res;
      }
    }
  };
</script>

#10

Thank you for your patience


#11

For anybody else experiencing similar issues…

I have discovered a temporary workaround by setting stackPages=“true” to the main view. This will ensure that previously visited pages will remain in the DOM when navigating back.

Still looking for a better long term solution if anybody finds anything of interest.