Code Monkey home page Code Monkey logo

Comments (5)

rylanharper avatar rylanharper commented on September 25, 2024 1

Hey @mklueh

yes I’ve had the :key property a million times haha, but I wasn’t aware of the fullPath key option to refresh the instance on an existing template page! I am fairly new to Gridsome (but not Vue/Nuxt) so this option doesn’t come up to much otherwise.

okay sounds good! Thanks for again for the help

from gridsome-plugin-recommender.

rylanharper avatar rylanharper commented on September 25, 2024

Small update after looking through my codebase.. So it turns out I actually have no idea how my product recommendations are even working. In fact I am not even sure how the plugin knows how to pull in related products, because I am querying the template, NOT the typeName of the shopify-source-plugin. When I input the typeName of the shopify source plugin (the default is set to Shopify) the terminal reads and error similar to this issue posted earlier. However, my code that I have currently does work correctly, but does not follow the plugin documentation (i.e I am querying the template title):

templates: {
// Shopify template
 ShopifyProduct: [
   {
     path: '/products/:handle',
     component: './src/templates/product.vue'
   }
 ],
 ShopifyCollection: [
   {
     path: '/collections/:handle',
     component: './src/templates/collection.vue'
   }
 ]
},

...

plugins: [
 {
   use: 'gridsome-source-shopify',
   options: {
     typeName: 'Shopify',
     storeName: process.env.GRIDSOME_SHOPIFY_STOREFRONT,
     storefrontToken: process.env.GRIDSOME_SHOPIFY_STOREFRONT_TOKEN
   }
 },
 {
   use: 'gridsome-plugin-recommender',
   options: {
     enabled: true,
     debug: true,
     typeName: 'ShopifyProduct',
     field: 'title',
     referenceField: 'title',
     relatedFieldName: 'related',
     referenceRelatedFieldName: 'related',
     minScore: 0.1,
     maxRelations: 4
   }
 }
]

and here is how the code is suppose to look based on this plugin documentation, but does not work correctly (draws a compiling error):

templates: {
// Shopify template
 ShopifyProduct: [
   {
     path: '/products/:handle',
     component: './src/templates/product.vue'
   }
 ],
 ShopifyCollection: [
   {
     path: '/collections/:handle',
     component: './src/templates/collection.vue'
   }
 ]
},

...

plugins: [
 {
   use: 'gridsome-source-shopify',
   options: {
     typeName: 'Shopify',
     storeName: process.env.GRIDSOME_SHOPIFY_STOREFRONT,
     storefrontToken: process.env.GRIDSOME_SHOPIFY_STOREFRONT_TOKEN
   }
 },
 {
   use: 'gridsome-plugin-recommender',
   options: {
     enabled: true,
     debug: true,
     typeName: 'Shopify',
     field: 'title',
     referenceField: 'title',
     relatedFieldName: 'related',
     referenceRelatedFieldName: 'related',
     minScore: 0.1,
     maxRelations: 4
   }
 }
]

This is likely the reason why my recommendation links are broken, but it is odd how I still retrieve the data, images, and product info via gql. Its like the plugin is working, but is breaking at the same time lol. I think I have raised more questions than answers, or maybe I am just misunderstanding how to properly use the plugin within my Gridsome config. Any info would be helpful

from gridsome-plugin-recommender.

mklueh avatar mklueh commented on September 25, 2024

Hi @rylanharper ,

first of all, always nice to see people using my plugin, glad it finds some users :)
And of course thanks for the detailed issue explanation. I din´t know that it works together with the Shopify source, which is amazing!

I´ve looked into the shopify source code and it seems the typeName you have to specify in their options is a bit misleading, as it rather seems to be a type prefix, see here:

  createTypeName (name) {
    let typeName = this.options.typeName
    // If typeName is blank, we need to add a prefix to these types anyway, as on their own they conflict with internal Gridsome types.
    const types = ['Page']
    if (!typeName && types.includes(name)) typeName = 'Shopify'

    return camelCase(`${typeName} ${name}`, { pascalCase: true })
  }

which is called for multiple types to create several collections

   this.TYPENAMES = {
      ARTICLE: this.createTypeName('Article'),
      BLOG: this.createTypeName('Blog'),
      COLLECTION: this.createTypeName('Collection'),
      PRODUCT: this.createTypeName('Product'),
      PRODUCT_VARIANT: this.createTypeName('ProductVariant'),
      PAGE: this.createTypeName('Page'),
      PRODUCT_TYPE: this.createTypeName('ProductType'),
      PRODUCT_TAG: this.createTypeName('ProductTag'),
      IMAGE: 'ShopifyImage',
      PRICE: 'ShopifyPrice'
    }

So this should explain why you are correctly using 'ShopifyProduct' and 'Shopify' is not working, as there is no plain 'Shopify' collection.

Now regarding the actual carousel rendering issue, I´m not sure what exactly goes wrong here.
Are these just product preview images that get mixed with other products or do you use the recommender plugin as well for the product images?

Not sure how this can be related to the recommender plugin as this plugin has no impact on any page rendering and is only running during the build phase to create the required collections.

If you print out the .related field on your product site, and it contains valid recommendations, this is literally all you get from this plugin :)

Guessing a bit, I´d investigate further when the carusel is loading, if anything is cached and if the component is reused in any way

For example, from the vue-agile FAQ:

FAQ
1. Using component with dynamic content
If content changes, you have to use reload or in some cases, you can use key property: <agile :key="mySlides.length">...</agile> (it'll rebuild the carousel after each change of mySlides length).

Oh and by the way, the min config in your case of the recommender plugin should be something like this:

{
   use: 'gridsome-plugin-recommender',
   options: {
     enabled: true,
     typeName: 'ShopifyProduct',
     field: 'title',
     minScore: 0.1,
     maxRelations: 4
   }
 }

the field names you´ve specified are the defaults, and as you are building up relations between items of the same collection and not two different collections you don´t need the "reference" options. Those are only required if you like to build up recommendations between for example:

Products <-> Categories
Products <-> Product Articles / Blog Posts

etc

Hope I could help

from gridsome-plugin-recommender.

rylanharper avatar rylanharper commented on September 25, 2024

Hey @mklueh

Wow thank you for the detailed response! After spending time looking into this issue you are correct that it is not the recommender plugin. I also checked the shopify-source-plugin code and realized that I just got lucky naming the related typeName lol! However, I really appreciate you looking into that and confirming that as well.

So what I have been able to find is that it is indeed that the carousel/slider component that is breaking due to the Vue instance not being properly destroyed within the page's lifecycle. I believe this is due to the Gridsome template (templates/product.vue) not refreshing due a dynamic data change. When I am on the current product.vue page and click a link from the recommended product component it says within the same instance on product.vue that was currently on and does not refresh into a new instance. I am not why it does that exactly since it technically is a new route change.. You can see the code example of how most carousel/slider libraries work where the component needs to be destroyed in order to render correctly for a new instance:

<template>
  <section class="product-carousel">
    <div ref="slider" class="keen-slider">
      <div v-for="image in images" :key="image.id" class="keen-slider__slide">
        <figure style="padding-bottom: 150%" class="product-carousel__image">
          <picture>
            <img
              v-lazy="image.originalSrc"
              :src="image.originalSrc"
              :alt="image.altText"
            />
          </picture>
        </figure>
      </div>
    </div>
    <div v-if="slider" class="dots">
      <button
        v-for="(slide, idx) in dotHelper"
        @click="slider.moveToSlideRelative(idx)"
        :class="{ dot: true, active: current === idx }"
        :key="idx"
      />
    </div>
  </section>
</template>

<script>
import KeenSlider from 'keen-slider'
import 'keen-slider/keen-slider.min.css'

export default {
  name: 'ProductCarousel',

  props: {
    images: {
      type: Array,
      require: true,
      default: () => []
    }
  },

  data() {
    return {
      current: 0,
      slider: null
    }
  },

  computed: {
    dotHelper() {
      return this.slider ? [...Array(this.slider.details().size).keys()] : []
    }
  },

  mounted() {
    this.slider = new KeenSlider(this.$refs.slider, {
      initial: this.current,
      slideChanged: s => {
        this.current = s.details().relativeSlide
      }
    })
  },

  beforeDestroy() {
    if (this.slider) this.slider.destroy()
  }
}
</script>

So in short, this appears to a Gridsome/slider component problem lol! There are some work arounds to this I can think of, but I will spend more time on that later (I already have a few ideas for things I can try). I really apologize for wasting your time and looking into an issue that wasn't related to the plugin you made, but again I do really appreciate it. Also thank you for the config example you provided. I have moved that into my current gridsome.config file! Thank you for the awesome plugin!:)

Edit: The solution was simple.. I just needed to add :key="$route.fullPath" to my product.vue template in order to "refresh" the instance on an internal link that uses the same template

from gridsome-plugin-recommender.

mklueh avatar mklueh commented on September 25, 2024

Hey @rylanharper ,

no problem :)

I´m probably going to add your example to the readme for others that are using it together with Shopify. It´s really missleading that they are calling the prefix option field typeName.

Edit: The solution was simple.. I just needed to add :key="$route.fullPath" to my product.vue template in order to "refresh" the instance on an internal link that uses the same template

I see, great to hear 👍 haven´t you had the :key property at all before? Never ran into any side-effects with it before, just warnings if it was entirely missing, but good to get to know some sample issue now

from gridsome-plugin-recommender.

Related Issues (7)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.