Gregor
Gregor
NNuxt
Created by Gregor on 10/16/2024 in #❓・help
nuxt ui with zod-validation
Hi, I have a form with this structure
const formData = ref({
email: "",
address: {
firstName: "",
lastName: "",
street: "",
addressDetails: "",
city: "",
country: "",
postalcode: "",
}
});
const schema = z.object({
email: z
.string()
.min(1, { message: "E-Mail is required" })
.email("Invalid email"),
address: z.object({
firstName: z.string().min(1, { message: "First Name is required" }),
sameBillingAddress: z.enum(["true", "false"]).array(),
lastName: z.string().min(1, { message: "Last Name is required" }),
street: z.string().min(1, { message: "Street is required" }),
city: z.string().min(1, { message: "City is required" }),
country: z.string().min(1, { message: "Country is required" }),
postalcode: z.string().min(1, { message: "Postalcode is required" }),
}),
shipping: z.enum(["standard", "express"], {
errorMap: () => ({ message: "Shipping is required" }),
}),
});
const formData = ref({
email: "",
address: {
firstName: "",
lastName: "",
street: "",
addressDetails: "",
city: "",
country: "",
postalcode: "",
}
});
const schema = z.object({
email: z
.string()
.min(1, { message: "E-Mail is required" })
.email("Invalid email"),
address: z.object({
firstName: z.string().min(1, { message: "First Name is required" }),
sameBillingAddress: z.enum(["true", "false"]).array(),
lastName: z.string().min(1, { message: "Last Name is required" }),
street: z.string().min(1, { message: "Street is required" }),
city: z.string().min(1, { message: "City is required" }),
country: z.string().min(1, { message: "Country is required" }),
postalcode: z.string().min(1, { message: "Postalcode is required" }),
}),
shipping: z.enum(["standard", "express"], {
errorMap: () => ({ message: "Shipping is required" }),
}),
});
<div class="flex-1 flex flex-col gap-10">
<UForm
:state="formData"
:schema="schema"
class="space-y-8 w-full flex flex-col"
@submit="onSubmit"
>
<checkoutAccount v-model="formData.email" />
<formsAddress
v-model:firstName="formData.address.firstName"
v-model:lastName="formData.address.lastName"
v-model:street="formData.address.street"
v-model:addressDetails="formData.address.addressDetails"
v-model:city="formData.address.city"
v-model:postalcode="formData.address.postalcode"
v-model:country="formData.address.country"
/>
<div class="flex-1 flex flex-col gap-10">
<UForm
:state="formData"
:schema="schema"
class="space-y-8 w-full flex flex-col"
@submit="onSubmit"
>
<checkoutAccount v-model="formData.email" />
<formsAddress
v-model:firstName="formData.address.firstName"
v-model:lastName="formData.address.lastName"
v-model:street="formData.address.street"
v-model:addressDetails="formData.address.addressDetails"
v-model:city="formData.address.city"
v-model:postalcode="formData.address.postalcode"
v-model:country="formData.address.country"
/>
if I don`t group the address inside an own object it works. The e-mail is validated correctly What do I have to do to get it up and running?
2 replies
NNuxt
Created by Gregor on 10/16/2024 in #❓・help
validate nuxtui radio buttons with zod
Hi, I do not get an error message for my radio buttons when I click on submit. Text input works as expected.
import { z } from "zod";

const formState = ref({
firstName: "",
shipping: "",
});
const schema = z.object({
firstName: z.string().min(1, { message: "First Name is required" }),
shipping: z.enum(["standard", "express"], {
required_error: "You must select an option.",
}),
});
const shippingVariants = ref([
{
value: "standard",
label: "Standard",
},
{
value: "express",
label: "Express",
},
]);

<UForm
ref="form"
:state="formState"
:schema="schema"
@submit="onSubmit"
>
<UFormGroup label="First Name" required name="firstName">
<UInput v-model="firstName" />
</UFormGroup>
<URadioGroup
v-model="formState.shipping"
legend="Select a shipping method"
:options="shippingVariants"
/>
<UButton type="submit">Review Summery</UButton>
</UForm>
import { z } from "zod";

const formState = ref({
firstName: "",
shipping: "",
});
const schema = z.object({
firstName: z.string().min(1, { message: "First Name is required" }),
shipping: z.enum(["standard", "express"], {
required_error: "You must select an option.",
}),
});
const shippingVariants = ref([
{
value: "standard",
label: "Standard",
},
{
value: "express",
label: "Express",
},
]);

<UForm
ref="form"
:state="formState"
:schema="schema"
@submit="onSubmit"
>
<UFormGroup label="First Name" required name="firstName">
<UInput v-model="firstName" />
</UFormGroup>
<URadioGroup
v-model="formState.shipping"
legend="Select a shipping method"
:options="shippingVariants"
/>
<UButton type="submit">Review Summery</UButton>
</UForm>
I got it worked with wrapping a formgroup around it, but then only the error message appears, but the radiobuttons do not get an error styling like an input text field
<UFormGroup
required
name="shipping"
>
<template #default>
<URadioGroup
v-model="formState.shipping"
legend="Select a shipping method"
:options="shippingVariants"
/>
</UFormGroup>
<UFormGroup
required
name="shipping"
>
<template #default>
<URadioGroup
v-model="formState.shipping"
legend="Select a shipping method"
:options="shippingVariants"
/>
</UFormGroup>
any ideas how I can get also error styling on inputs? best, gregor
2 replies
NNuxt
Created by Gregor on 10/7/2024 in #❓・help
[useFetch] Component is already mounted, please use $fetch instead.
Hi,
I am using useFetch to load a product on the server side once... works fine, but the user can change the region and then price/taxe change, so the product has to be reloaded. this causes this error... Should I just duplicate the function and rename it to reFetchProduct and use $fetch or are there other solutions for this use case?
async getProduct(handle) {
const regionsStore = useRegionsStore();
const queryParams = new URLSearchParams({
fields: `*variants.calculated_price`,
region_id: regionsStore.regionId,
country_code: regionsStore.selectedRegion.countries[0].iso_2,
});
const { MEDUSA_PUBLISHABLE_KEY } = useRuntimeConfig().public;
try {
const { data } = await useFetch(
`http://localhost:9000/store/products?handle=${handle}&${queryParams.toString()}`,
{
credentials: "include",
headers: {
"x-publishable-api-key": MEDUSA_PUBLISHABLE_KEY,
},
}
);

return data.value.products[0];
} catch (error) {
throw error;
}
},
async getProduct(handle) {
const regionsStore = useRegionsStore();
const queryParams = new URLSearchParams({
fields: `*variants.calculated_price`,
region_id: regionsStore.regionId,
country_code: regionsStore.selectedRegion.countries[0].iso_2,
});
const { MEDUSA_PUBLISHABLE_KEY } = useRuntimeConfig().public;
try {
const { data } = await useFetch(
`http://localhost:9000/store/products?handle=${handle}&${queryParams.toString()}`,
{
credentials: "include",
headers: {
"x-publishable-api-key": MEDUSA_PUBLISHABLE_KEY,
},
}
);

return data.value.products[0];
} catch (error) {
throw error;
}
},
14 replies
NNuxt
Created by Gregor on 9/5/2024 in #❓・help
middleware hard reload, wrong redirects
Hi, I have this middlware where I check if a session exists in the backend
//middleware/auth.js
export default defineNuxtRouteMiddleware(async (to, from) => {
const medusa = useMedusaClient();
try {
await medusa.auth.getSession();
} catch (error) {
return navigateTo("/login");
}
});
//middleware/auth.js
export default defineNuxtRouteMiddleware(async (to, from) => {
const medusa = useMedusaClient();
try {
await medusa.auth.getSession();
} catch (error) {
return navigateTo("/login");
}
});
this works when I navigate with a link inside my app to the secured page if I am logged in and have an open session in medusa-backend, it shows the page, if not, it redirects to the login but when I type the URL into the browser and press enter, I get always redirected to the login page, even if I have an existing session any idea why?
1 replies
NNuxt
Created by Gregor on 8/27/2024 in #❓・help
pretty urls for e-commerce shop
I have a url structure like this. https://www.myshop.com/beer/red-ale/england?page=2 but I want a more pretty url like this https://www.myshop.com/beer/red-ale/england/2 ?
beer is a category red-ale and england are optional filters 2 is a optional pagenumber my folder looks like [category]/[...filters].vue At the moment I just think to check if the last parameter in the array is a number
if (Number(params[params.length - 1])) {
console.log("I'm a pagenumber");
} else {
console.log("I'm a filter");
}
if (Number(params[params.length - 1])) {
console.log("I'm a pagenumber");
} else {
console.log("I'm a filter");
}
this works only if there are no filters with numbers... and also only for pagenumbers, if I want to add "sort" to the url https://www.myshop.com/beer/red-ale/england/new-arrival/2 it also doesn't work there are other options to handle this? or is this the way to go https://www.myshop.com/beer/red-ale/england?page=2&sort=new-arrival cheers, gregor
3 replies
NNuxt
Created by Gregor on 7/9/2024 in #❓・help
ui.nuxt: Overwriting styles for UInput doesn't work
Hi, I want to remove the outline from an input, but I don't get it work. What I'm doing wrong?
<UInput
variant="outline"
:ui="{
rounded: 'rounded-none',
base: 'h-full text-center [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none',
variant: {
outline: 'shadow-none ring-0',
},
}"
type="number"
:model-value="number"
/>
<UInput
variant="outline"
:ui="{
rounded: 'rounded-none',
base: 'h-full text-center [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none',
variant: {
outline: 'shadow-none ring-0',
},
}"
type="number"
:model-value="number"
/>
demo on https://stackblitz.com/edit/nuxt-ui-mtxuq3?file=app.vue Many thanks, gregor 😉
2 replies
NNuxt
Created by Gregor on 6/10/2024 in #❓・help
nuxtpage: child page inside parent page
Hi, I have this page structure app.vue layouts/ --default.vue pages/ --categories ----[category].vue ----index.vue my problem is that i can't render the [category].vue inside the <nuxtPage /> from index.vue from the same folder... it just replaces the whole page, instead rendering the subcategories inside the nuxtPage... What I'm doing wrong?
//layouts/default.vue
<template>
<div>
<slot />
</div>
</template>
//layouts/default.vue
<template>
<div>
<slot />
</div>
</template>
//app.vue
<template>
<div>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</div>
</template>
//app.vue
<template>
<div>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</div>
</template>
//categories/index.vue
<template>
<div class="flex">
<div class="w-full">
Categories
<uLink to="/categories/cat1">Cat1</uLink>
<uLink to="/categories/cat2">Cat2</uLink>
<uLink to="/categories/cat3">Cat3</uLink>
</div>
<div>
<NuxtPage :page-key="(route) => route.fullPath" />
</div>
</div>
</template>
//categories/index.vue
<template>
<div class="flex">
<div class="w-full">
Categories
<uLink to="/categories/cat1">Cat1</uLink>
<uLink to="/categories/cat2">Cat2</uLink>
<uLink to="/categories/cat3">Cat3</uLink>
</div>
<div>
<NuxtPage :page-key="(route) => route.fullPath" />
</div>
</div>
</template>
//categories/[category].vue
<script setup>
const { category } = useRoute().params;
</script>
<template>
<div class="w-full">Sub Assortment {{ category }}</div>
</template>
//categories/[category].vue
<script setup>
const { category } = useRoute().params;
</script>
<template>
<div class="w-full">Sub Assortment {{ category }}</div>
</template>
10 replies
NNuxt
Created by Gregor on 4/10/2024 in #❓・help
dynamic pagetransitions with js hooks
Hi, is there an example how this example from the docs would work with js hooks?
definePageMeta({
pageTransition: {
name: 'slide-right',
mode: 'out-in'
},
middleware (to, from) {
if (to.meta.pageTransition && typeof to.meta.pageTransition !== 'boolean')
to.meta.pageTransition.name = +to.params.id > +from.params.id ? 'slide-left' : 'slide-right'
}
definePageMeta({
pageTransition: {
name: 'slide-right',
mode: 'out-in'
},
middleware (to, from) {
if (to.meta.pageTransition && typeof to.meta.pageTransition !== 'boolean')
to.meta.pageTransition.name = +to.params.id > +from.params.id ? 'slide-left' : 'slide-right'
}
https://nuxt.com/docs/getting-started/transitions#dynamic-transitions because I do not have access to the pageTransition.name inside the onEnter hook
pageTransition:
{
name: "slide",
onEnter: (el, done) => {
// no access to pageTransition.name
if(to.meta.pageTransition.name === "slide") {
// slide ani
}else{
// fade ani
}
}
pageTransition:
{
name: "slide",
onEnter: (el, done) => {
// no access to pageTransition.name
if(to.meta.pageTransition.name === "slide") {
// slide ani
}else{
// fade ani
}
}
and pageTrannsition doesn't accept an array like
pageTransition: [
{
name: "slide",
onEnter: (el, done) => {
}
},
{
name: "fade",
onEnter: (el, done) => {
}
},
]
pageTransition: [
{
name: "slide",
onEnter: (el, done) => {
}
},
{
name: "fade",
onEnter: (el, done) => {
}
},
]
2 replies