如何使 nuxt 多选与 Laravel API 中的数据正常工作?

问题描述 投票:0回答:1

我正在使用 Nuxt UI 库中的 USelectMenu 组件,我需要确保显示用户可以选择的所有选项。我已经用mapped_looking_for 方法覆盖了这一点,并且选项绑定正确。然后,我需要显示用户已经选择的所有选项,我也在某种程度上进行了工作。

问题是选择应该以这样的方式工作:如果选择了一个选项,则右侧旁边应该有一个勾号,表明它确实被选择了。然而,尽管它显示选择了 5 个选项,但我没有看到它们旁边的勾号。我也无法以可以删除选项的方式与他们互动。本质上,它对我不起作用;我必须手动从数据库中删除它们。

有人可以提供一些建议吗?我对使用 API 还比较陌生,并且可能错误地传递了数据。谢谢你。

这是前端。

<template>
    <div class="">
        <Heading as="h2">
            <span>Your profile</span>
        </Heading>
        <div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
            <form @submit.prevent="updateProfile">

                <Heading>
                    <UAvatar :src="getAvatarUrl(profile.avatar)" size="xl" />

                </Heading>

                <UFormGroup label="About me">

                    <UTextarea autoresize color="primary" placeholder="Search..." v-model="profile.bio" />
                </UFormGroup>

                <UFormGroup label="Name">
                    <UInput color="primary" disabled v-model="user.name" />
                </UFormGroup>

                <UDivider label="Stats" class="mt-5" />
                <UFormGroup label="Show age">

                    <UToggle on-icon="i-heroicons-check-20-solid" off-icon="i-heroicons-x-mark-20-solid"
                        v-model="profile.show_age" />
                </UFormGroup>
                <UFormGroup label="Age">
                    <UInput color="primary" disabled v-model="profile.age" />
                </UFormGroup>
                <UFormGroup label="Height">
                    <USelect color="primary" v-model="profile.height" :options="height_option" />
                </UFormGroup>
                <UFormGroup label="Weight">
                    <USelect color="primary" v-model="profile.weight" :options="weight_option" />
                </UFormGroup>
                <UFormGroup label="Body Type">
                    <USelect color="primary" v-model="profile.body_type" :options="body_types" />
                </UFormGroup>
                <UFormGroup label="Relationship Status">
                    <USelect color="primary" v-model="profile.relationship_status" :options="relationship_status" />
                </UFormGroup>
                <UDivider label="What are you looking for?" class="mt-5" />

                <USelectMenu v-model="selected_looking_for" :options="mapped_looking_for" multiple
    placeholder="Vyber, co hledáš"  value-field="value" label-field="label" 
    />
                <div class="selected-options">
                    <UBadge v-for="item in profile.looking_fors" :key="item.id" :label="item.name" color="primary"
                        class="mr-2 mb-2 mt-2" />
                </div>
                <UDivider label="Identity" class="mt-5" />
                <UFormGroup label="Gender">
                    <USelect color="primary" v-model="profile.gender" :options="genders" />
                </UFormGroup>
                <div class="flex justify-center mt-4">
                    <UButton color="primary" size="md" type="submit">
                        Save
                    </UButton>
                </div>
            </form>


        </div>
    </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'

const { api } = useAxios();
const profile = ref({});

const user = ref({});

const mapped_looking_for = ref([]);
const selected_looking_for = ref([]);
const genders = ['male', 'female']

const height_option = ref([{ label: 'Do not show', value: 'Do not show' }]);

const weight_option = ref([{ label: 'Do not show', value: 'Do not show' }]);

const relationship_status = ["Do not show", "Commited", "Dating", "Engaged", "Exclusive", "Married", "Open Relationship", "Partnered", "Single"]

const body_types = ["Do not show", "Toned", "Average", "Large", "Muscular", "Slim", "Stocky"]

const fetchLookingFor = async () => {
    try {
        const { data } = await api.get('/api/lookingFor');
        mapped_looking_for.value = data.data.map(item => ({
            label: item.name,
            value: item.id
        }));
        console.log('Mapped looking_for:', mapped_looking_for.value);
    } catch (error) {
        console.error('Error fetching looking for options:', error);
    }
};




const fetchProfile = async () => {
    try {
        const { data } = await api.get('/api/profiles/show');
        profile.value = data.profile;
        user.value = data.user;
        selected_looking_for.value = data.looking_fors.map(item => item.id);
    } catch (error) {
        console.error('Error fetching profile:', error);
    }
};


// Updating profile
const updateProfile = async () => {
    try {
        const looking_for_id = selected_looking_for.value.map(item => item.value);

        await api.put(`/api/profiles/${profile.value.id}`, {
            bio: profile.value.bio,
            gender: profile.value.gender,
            show_age: profile.value.show_age,
            height: profile.value.height,
            weight: profile.value.weight,
            body_type: profile.value.body_type,
            relationship_status: profile.value.relationship_status
        });

        await api.put(`/api/profiles/${profile.value.id}/looking-for`, {
            looking_for: looking_for_id
        });
        console.log('Profile updated successfully');
    } catch (error) {
        console.error('Error updating profile:', error);
    }
};


const getAvatarUrl = (avatarPath) => {
    const baseUrl = 'http://localhost:8080';
    return `${baseUrl}/storage/${avatarPath}`;
};

watch(() => profile.value.show_age, async (new_value) => {
    try {
        await api.put(`/api/profiles/${profile.value.id}`, {
            show_age: new_value
        });
        console.log('Show age updated successfully');
    } catch (error) {
        console.error('Error updating profile:', error);
    }
});


// height select

for (let i = 120; i <= 230; i++) {
    height_option.value.push({
        label: `${i} cm`,
        value: `${i}`
    });
}

// weight select

for (let x = 40; x <= 270; x++) {
    weight_option.value.push({
        label: `${x} kg`,
        value: `${x}`
    })
}

onMounted(() => {
    fetchProfile();
    fetchLookingFor();
});

</script>

这就是我后端的内容。

 public function show(): JsonResponse
    {
        $user = Auth::user();

        $profile = $user->profile;

        return response()->json([
            'user' => [
                'name' => $user->name,
                'email' => $user->email,
            ],
            'profile' => $profile,
            'looking_fors' => $profile->lookingFors
        ]);
    }

 public function updateLookingFor(Request $request): JsonResponse
{
    $user = $request->user();
    $profile = $user->profile;
    $validated = $request->validate([
        'looking_for' => 'array',
        'looking_for.*' => 'exists:looking_fors,id',
    ]);

    $profile->lookingFors()->sync($validated['looking_for']);

    return response()->json(['message' => 'Looking for updated successfully']);
}

//还有路线

    Route::put('/profiles/{id}/looking-for', [ProfileController::class, 'updateLookingFor']);

附加信息: 这是当用户在数据透视表 profile_looking_fors 的looking_for 字段中没有保存任何内容时初始请求的有效负载:

{looking_for: [1, 2, 3]}

它存储了各自的looking_for的id,这是正确的。

但是,当我再次选择相同的值时(这本质上意味着我想取消选择它们或将它们从数据库中删除以使其在两个方向上工作),会发生错误:

"errors": {
    "looking_for.0": [
        "The selected looking_for.0 is invalid."
    ],
    "looking_for.1": [
        "The selected looking_for.1 is invalid."
    ],
    "looking_for.2": [
        "The selected looking_for.2 is invalid."
    ]
}

这是有效负载:发生错误后

{looking_for: [null, null, null, 1, 2, 3]}

它发送空值以及 1、2、3。

javascript php laravel nuxt.js
1个回答
0
投票

我通过创建自己的多选组件而不是使用 Nuxt UI 库中的组件来解决这个问题。问题在于 Nuxt UI 组件本身,正如我在其 GitHub 问题页面上发现的那样,当用户从后端 API 获取数据时,它似乎很难正确设置初始值。

© www.soinside.com 2019 - 2024. All rights reserved.