Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there support for nuxt + vue 3 #168

Closed
makerovski opened this issue Nov 24, 2022 · 19 comments
Closed

Is there support for nuxt + vue 3 #168

makerovski opened this issue Nov 24, 2022 · 19 comments

Comments

@makerovski
Copy link

Hello, does this support Vue 3 + Nuxt 3 ?

Thank you!

@harlan-zw
Copy link
Collaborator

Yes, Nuxt v3 depends on this package. If you use useHead anywhere in your Nuxt app you'll be using it :)

Did you have any questions or issues with it in Nuxt?

@makerovski
Copy link
Author

makerovski commented Nov 24, 2022

Thank you for the answer!

Yes a help would be very good..

I am using vue + nuxt 3, latest release. Composition API

First Problem I have is that I can not acess "My Data" to make it dynamic, solved this declaring useHead after

At first I used the component like this:

import:

import { useHead } from '@vueuse/head'

 useHead({
      meta: [
        { hid: 'og-type', property: 'og:type', content: 'website' },
        { hid: 'og-title', property: 'og:title', content: `App Name - ${projectName}` },
        { hid: 'og-image', property: 'og:image', content: `${imageUrl}`},
      ]

And I don't know what else I should to configure. The metadata should be Dynamic, because on this page will be different "projects" rendered

Here is the code. (I removed some sensible data)

<script lang="ts">
import { useUserStore } from '@/store/user'
import { useHead } from '@vueuse/head'
export default defineComponent({
  name: 'PublicProjectsId',
  setup() {
    definePageMeta({
      layout: "public",
    })
    const imageUrl = ref('')
    const router = useRouter()
    const route = useRoute()
    
    const projectName = computed(() => {
      return project.value.name
    })
    const setImage = (url) => {
      imageUrl.value = url
    }
    useHead({
      meta: [
        { hid: 'og-type', property: 'og:type', content: 'website' },
        { hid: 'og-title', property: 'og:title', content: `App Name - ${projectName}` },
        { hid: 'og-image', property: 'og:image', content: `${imageUrl}`},
      ]
    })
    
 
    return {
      project,
      projectName
    }
  }
})
</script>

Thank you very much for your help, and this would definitely worth a beer :)

@harlan-zw
Copy link
Collaborator

harlan-zw commented Nov 24, 2022

Sure, let me try and help you with this.

The issue you seem to be having is you're resolving the reactive data before it's sent into useHead.

Let's look at this example:

const myTitle = ref('initial title')
useHead({
  title: `${myTitle}`
})
myTitle.value = 'new title'

In this, the title would be 'initial title' no matter what happens to the ref value. To get around this, you should either provide the ref as is, a computed value, or a reactive getter.

const myTitle = ref('initial title')
useHead({
  title: myTitle
})
myTitle.value = 'new title'

This would fix it.

For your code, this is how I would personally handle it:

    useHead({
      meta: [
        { hid: 'og-type', property: 'og:type', content: 'website' },
        { hid: 'og-title', property: 'og:title', content: () => `App Name - ${project.value.name}` },
        { hid: 'og-image', property: 'og:image', content: imageUrl },
      ]
    })

The () => value is the reactive getter syntax and is your friend

If that doesn't help then I might need some more of the code, specifically around how the project is being fetched.

Also some tips:

  • you don't need to import useHead, the auto-imports should do that for you
  • you don't need to provide hid, these og props are already deduped based on the property name

@makerovski
Copy link
Author

Mega thank you, I will try it this evening and write an answer!

Thank you!

@makerovski
Copy link
Author

makerovski commented Nov 25, 2022

Hello, I have tried but it also did not work!

Same as if I use static values, I have also tried in differents components.

here is my setup code:

<script lang="ts">
import { useUserStore } from '@/store/user'

export default defineComponent({
  name: 'PublicProjectsId',

  setup() {
    definePageMeta({
      layout: "public",
    })

    const project = ref(null)
    const locations = ref([])
    const imageUrl = ref('')
    const projectContactFormModalOpen = ref(false)
    const router = useRouter()
    const snackbar = useSnackbar()

    const route = useRoute()
    const userStore = useUserStore()
    let api = usePublicApi()
    

    useHead({
      title: 'alex-test',
      meta: [
        { hid: 'og-type', property: 'og:type', content: 'website' },
        { hid: 'og-title', property: 'og:title', content: 'test-alex' },
        { hid: 'og-image', property: 'og:image',content: '' },
      ]
    })

    const handleResetLink = () => {
      if (router.currentRoute.value.path === '/') {
        location.reload()
      } else {
        router.push({ path: '/' })
      }
    }
    if (useUser().loggedIn()) {
      api = usePrivateApi()
    }


    const projectId = computed(() => {
      return route.params.id
    })

 
    onMounted(() => {
      getPublicProject()
    })

    const getPublicProject = async () => {
      try {
        const res = await api.call('get', `projects/${projectId.value}`, null)
        if (res) {
          project.value = res.data.resource
          locations.value = []
          project.value.locations.forEach((location: any) => {
            locations.value.push({
              id: project.value.id,
              longitude: parseFloat(location.longitude),
              latitude: parseFloat(location.latitude),
              draggable: false
            })
          })
          setImage(project.value.image_url)
        }
      } catch (error) {
        console.log(error)
      }
    }

    const setImage = (url) => {
      imageUrl.value = url
    }
 

    return {
      project,
      locations,
      userStore,
      setImage,
      getPublicProject,
      projectContactFormModalOpen,
      handleResetLink,
    }
  }
})
</script> 

Thank you very much again for your help :)

@harlan-zw
Copy link
Collaborator

Could you confirm the issue in this second code example? It looks like it should work correctly, are you saying nothing is updating?

@makerovski
Copy link
Author

Hello, yes this is the actual code, and unfortunately it does not work. Can you say a better way to test it? Maybe my tests are wrong.

Thank you!

@makerovski
Copy link
Author

makerovski commented Dec 5, 2022

Here is the development, and this code is present on this page.

https://wiiir-frontend-proto-preview.herokuapp.com/public/projects/38273166-867d-4481-a3cb-dfbc8836a000

@harlan-zw
Copy link
Collaborator

The code you provided has static useHead values and it looks like they are being added to that page.

If you provide a dynamic code example and push that to that URL I can help you debug further.

@makerovski
Copy link
Author

Perfect, I am going to do it right now and send you the changes

@makerovski
Copy link
Author

I have updated the code:

for projects it's now like this:

useHead({
      title: 'Smart Wendel',
      meta: [
        { property: 'og:type', content: 'website' },
        { property: 'og:title', content: () => `${project.name}` },
        { property: 'og:image', content: imageUrl },
        { property: 'og:description', content: () => `${project.excerpt}` }
      ]
    })

And in public vue:

useHead({
   title: 'Smart Wendel',
   meta: [
     { property: 'og:type', content: 'website' },
     { property: 'og:title', content: 'website'},
     { property: 'og:image', content: '' },
   ]
 })

Thank you!!

@harlan-zw
Copy link
Collaborator

harlan-zw commented Dec 5, 2022

I think you're missing the .value. Looking at the site it shows those values as undefined

useHead({
      title: 'Smart Wendel',
      meta: [
        { property: 'og:type', content: 'website' },
        { property: 'og:title', content: () => `${project.value.name}` },
        { property: 'og:image', content: imageUrl },
        { property: 'og:description', content: () => `${project.value.excerpt}` }
      ]
})

@makerovski
Copy link
Author

Hello,

.value is already given here, it also not necessary in the place, it also doesn't work using .value

 const getPublicProject = async () => {
      try {
        const res = await api.call('get', `projects/${projectId.value}`, null)
        if (res) {
          **project.value = res.data.resource**
          locations.value = []
          project.value.locations.forEach((location: any) => {
            locations.value.push({
              id: project.value.id,
              longitude: parseFloat(location.longitude),
              latitude: parseFloat(location.latitude),
              draggable: false
            })
          })
          setImage(project.value.image_url)
        }
      } catch (error) {
        console.log(error)
      }
    }

@harlan-zw
Copy link
Collaborator

harlan-zw commented Dec 5, 2022

Please understand that the issue you're having is related to your code. You are not providing data correctly.

I'm not exactly sure what you mean by this snippet, but you can see yourself that undefined is the output of what you've given.

You can see this yourself by putting console logs in the functions

useHead({
      title: 'Smart Wendel',
      meta: [
        { property: 'og:type', content: 'website' },
        { property: 'og:title', content: () => { 
                console.log(project, project.name)
              return `${project.value.name}`
             } 
        },
        { property: 'og:image', content: imageUrl },
        { property: 'og:description', content: () => `${project.value.excerpt}` }
      ]
})

@makerovski
Copy link
Author

makerovski commented Dec 8, 2022

Hello, thank you for the answer .. I made tests and confirm that useHead is working, means it works as it should...

In fact, the dynamic text is not working, with .value, I have also tried a workaround using computed and ref() as u said before but I get [object] [object] as value.

I also made some other tests, but no success. I have also another question, would Facebook, WhatsApp.. read those values ? Because it is only in elements, but not in the source code of the page. The only way I found to do that is in nuxt config with:

 app: {
    head: {
      charset: 'utf-16',
      viewport: 'width=500, initial-scale=1',
      title: 'My App',
      meta: [
        { property: 'og:type', content: 'website' },
        { property: 'og:title', content: 'please work' },
        { property: 'og:description', content: 'oh God' }
      ],
    }
  }

But it does not help, since I have dynamic pages and it is properties (projects).

Thank you veeery much!

@harlan-zw
Copy link
Collaborator

If you're using SSR or SSG then they will be able to read these tags correctly. You can right click -> inspect source and you should be able to see the tags.

As an example my personal site which uses dynamic tags for the og:title has no issues: https://harlanzw.com/

@makerovski
Copy link
Author

Hi :)

I have Issues to enable the SSR in my project, but at least now I understand how useHead works

Thank you very much!

@SquirrelCoder
Copy link

SquirrelCoder commented Dec 15, 2022

I have the same problem sadly.
Using an older version (e.g. 0.7.12), I do not encounter such problem, but using the latest version, the attributes won't even show up, when using SSR.

e.g.:

useHead({
  title: metaTitle,
  meta: [
    { property: "og:title", content: metaTitle },
    { property: "og:type", content: "website" },
    { property: "og:description", content: metaTitle },
  ],
});

metaTitle is generated dynamically.

There has been definitely some breaking changes since v. 1.0, because as soon as I downgrade to version 0.7.12 then everything works perfectly.

The way I test the SSR is using wget and then opening the downloaded web page in some editor.

Any help would be great. Thanks!

@harlan-zw
Copy link
Collaborator

If you can make a reproduction repo I'll be happy to sort it out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants