Adding class to element in v-for loop - vue.js

I have a v-for loop, and I wanna make background: red; by adding a class. But when I click my action button it coloring all indexes.
My goal is if I have 3 elements when I click the priority button then make that line(index) background red. I mean list element make the background red/yellow/green whichever.
<div v-for="(item, index) in todos" :key="item.id">
<div :class="{'bg-red-500': isRed, 'bg-yellow-500': isYellow, 'bg-green-500': isGreen}" class="rounded transition ease-in-out delay-200 duraiton-200 flex align-middle justify-between">
<div id="checklist" #click="addCompleted(index)" class="w-1/2 break-all text-white transition duration-200 ease-out text-1xl text-left my-5 transition ease-in-out delay-150 duration-200 cursor-pointer flex justify-start align-center">
<input v-bind:id="item.id" type="checkbox" name="checkbox" class="outline-0 offset-0 ring-0 border-0 focus:outline-0 focus:ring-0 focus:offset-0 focus:border-0 focus:ring-offset-0" />
<label v-bind:for="item.id">{{ item.text }}</label>
</div>
<div class="priority flex items-center justify-between text-white">
<div #click="priortiy_red(index)" class="red rounded-full bg-red-500 p-2 "></div>
<div #click="priortiy_yellow(index)" class="yellow rounded-full bg-yellow-500 p-2 mx-2"></div>
<div #click="priortiy_green(index)" class="green rounded-full bg-green-500 p-2 "></div>
</div>
<span class="X-icon items-center justify-end inline-flex cursor-pointer" #click="removeTodo(index)">
<svg class="fill-current text-red-500" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
<path d="M0 0h24v24H0z" fill="none" />
</svg>
</span>
</div>
</div>
What I Try for now I try normal vuejs's class bind property. But as I say it coloring all divisions.
Github Repo Link: https://keremunce.github.io/Vue-ToDo/

A simple solution is to add a color prop to each todo object.
Then apply class with item.color === 'red' etc..
... 'bg-red-500': item.color === 'red', 'bg-yellow-500': item.color === 'yellow', 'bg-green-500': item.color === ''green ...
and apply color with:
...
#click="item.color = 'red'"
// etc
...

Related

absolute positioned element to the right above other content

I am trying to position a panel to the right of avatar icon. i want to make it look like the supabase dashboard.
i have the following already. iam using tailwindcss and tailwind/headlessui for the popover
<Popover className="relative flex flex-col items-center">
<Popover.Panel
className="absolute -top-32 right-0 z-50 w-screen max-w-[270px] px-4 sm:px-0 translate-x-full ">
<div className="overflow-hidden rounded-sm shadow ring-1 ring-black ring-opacity-5">
<div className="block w-full h-12 bg-blue-50 py-3 px-3 content-center">
<div>
{
(isLoading || isError) ? (
<div role="status" className="space-y-2.5 animate-pulse max-w">
<div className="h-2.5 bg-gray-200 rounded w-full"></div>
</div>
) : (
<h4 className="font-semibold">
{user.email}
</h4>
)
}
</div>
</div>
<div className="relative grid grid-cols-1 gap-4 bg-white py-7 ">
<div className="flex flex-col gap-6">
<PanelItem content="Wishlist" href="/v/wishlist">
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
>
<path
d="M12.62 20.81C12.28 20.93 11.72 20.93 11.38 20.81C8.48 19.82 2 15.69 2 8.68998C2 5.59998 4.49 3.09998 7.56 3.09998C9.38 3.09998 10.99 3.97998 12 5.33998C13.01 3.97998 14.63 3.09998 16.44 3.09998C19.51 3.09998 22 5.59998 22 8.68998C22 15.69 15.52 19.82 12.62 20.81Z"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</PanelItem>
</div>
</div>
<Button variant="primary" className="rounded-none" onClick={handleSignOut}>
<span className="text-sm font-medium" >Sign Out</span>
</Button>
</div>
</Popover.Panel>
</Popover>
it looks like this.
but should look like this

Flowbite plugin not working in RouterView

I am currently building a dashboard app and I am facing an issue I canĀ“t solve.
App.vue
<template>
<div class="flex flex-row min-h-screen w-screen">
<SideBar />
<div class="flex flex-col w-full bg-gray-300 shrink min-w-0">
<TopBar />
<RouterView />
</div>
</div>
</template>
Dropdown fragment in TopBar component (flowbite acts normal):
<button
type="button"
class="flex mr-3 text-sm md:mr-0 items-center"
id="user-menu-button"
aria-expanded="false"
data-dropdown-toggle="user-menu"
>
<span class="sr-only">Open user menu</span>
<img
class="w-8 h-8 rounded-full border-green"
src="https://picsum.photos/200"
alt="user photo"
/>
<span class="ml-3 text-medium text-gray-500"
>Hallo, <span class="font-semibold">Leon!</span></span
>
</button>
<!-- Dropdown menu -->
<div
class="
hidden
z-50
my-4
text-base
list-none
bg-white
rounded
divide-y divide-gray-100
shadow
dark:bg-gray-700 dark:divide-gray-600
"
id="user-menu"
style="
position: absolute;
inset: auto auto 0px 0px;
margin: 0px;
transform: translate(1246px, 723px);
"
data-popper-reference-hidden=""
data-popper-escaped=""
data-popper-placement="top"
>
Start of at the RouterView injected Component:
<template>
<main class="w-full h-full py-5 px-5">
<CardStatus />
<Card class="max-w-3xl max-h-80 p-5">
<div class="mb-4 flex flex-row justify-between">
<h5
class="
text-xl
font-semibold
tracking-tight
text-gray-900
dark:text-white
"
>
Dropdown fragment in CardStatus component (flowbite not working):
<button
id="dropdownDefault"
data-dropdown-toggle="dropdown"
class="
text-white
bg-blue-700
hover:bg-blue-800
focus:ring-4 focus:outline-none focus:ring-blue-300
font-medium
rounded-lg
text-sm
px-4
py-2.5
text-center
inline-flex
items-center
dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800
"
type="button"
>
Dropdown button
<svg
class="w-4 h-4 ml-2"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 9l-7 7-7-7"
></path>
</svg>
</button>
<!-- Dropdown menu -->
<div
id="dropdown"
class="
z-10
hidden
bg-white
divide-y divide-gray-100
rounded
shadow
w-44
dark:bg-gray-700
"
>
<ul
class="py-1 text-sm text-gray-700 dark:text-gray-200"
aria-labelledby="dropdownDefault"
>
I have no idea why it acts like this. I imported and installed everything like explained in the documentation.
Thanks

[Vue warn]: Error in render: "TypeError: Cannot read properties of undefined (reading 'length')" error when using datatables in vue

In my laravel vuejs application I have following vue to display some data inside a datatable .
For the better user experience, I have added a Show more option to load data.
<show-more :data-size="documents.length" increment-amount="5" >
<div slot-scope="{ showMore, showAmount }">
<div v-bind:class = "selectedForAction.count() === 0 ? 'h-15' : ''">
<action-bar :count="selectedForAction.count()">
<div slot="table-header" class="flex items-center justify-between bg-white border-certstyle-border border-b rounded-t py-4 px-10 w-full ">
<!--Course -->
<div class="flex items-center rounded-full w-22 overflow-hidden shadow-soft">
<selectable-all item="selectAll" :data="documents" #select="selectAll"></selectable-all>
</div>
<div class="flex flex-col items-left text-left w-10/12">
Document
</div>
<div class="w-74 text-left" item="validFor">
Valid until
</div>
<div class="w-1/12 text-center" item="status">
Validity
</div>
<div class="px-8 w-32">
</div>
<div class="px-8">
</div>
</div>
<button v-if="selectedForAction.count() === 1" #click="editSelectedDocument" class="flex items-center text-certstyle-titles text-sm mx-4" >
<span class="mr-1">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2"><path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path></svg>
</span>
<span class="font-bold">Edit</span>
</button>
<button #click="removeSelectedDocument" class="flex items-center text-certstyle-titles text-sm mx-4" >
<span class="mr-1">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-x-square"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><line x1="9" y1="9" x2="15" y2="15"></line><line x1="15" y1="9" x2="9" y2="15"></line></svg>
</span>
<span class="font-bold">Remove</span>
</button>
</action-bar>
</div>
<!--Certificates-->
<div v-if="documents[index] !== undefined" v-for="(i, index) in showAmount" class="flex items-center justify-between border-certstyle-border border-b px-10 py-1 hover:bg-certstyle-background-light transition-colors duration-150">
<!--Certificate institute image-->
<div class="flex items-center " item="certificatedChecked" >
<div class="relative">
<div class="rounded-full h-14 w-10 overflow-hidden shadow-soft pt-4">
<selectable
v-model="selectedForAction"
:item="documents[index].id"
:ref="documents[index].id"
></selectable>
</div>
</div>
</div>
<div class="flex flex-col items-left text-left w-10/12" item="certificate">
<span :title="documents[index].name" style="cursor: help;" class="text-certstyle-titles font-bold cursor-help">{{ documents[index].name }}</span>
</div>
<!--Certificate due date-->
<div class="w-74 text-left" item="validFor">
<p class="text-sm valid-until not-applicable" v-if="documents[index].is_valid_forever">{{ 'Indefinite'}}</p>
<p class="text-sm valid-until" v-else>{{ documents[index].expires_at_formatted }}</p>
</div>
<!-- Certificate status-->
<div class="w-48 text-center" item="status">
<status :status="documents[index].validity_status.toLowerCase()"></status>
</div>
<!--Download icon-->
<div class="cs--dashboard-employee-certificate-index--certificate-download-icon px-8" item="download">
<a v-if="documents[index].url !== null" :href="getDocumentDownloadLocation(documents[index].id)" class="text-certstyle-text-light">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-download"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>
</a>
</div>
<!--Preview icon-->
<div class="cs--dashboard-employee-certificate-index--certificate-download-icon px-8" item="view">
<a v-if="documents[index].url !== null" target="_blank" :href="getDocumentPreviewLocation(documents[index].id)" class="text-certstyle-text-light">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-eye"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg>
</a>
</div>
<div class="w-0 flex justify-end">
<edit-documents-modal :document="documents[index]" :identifier="`editDocument${documents[index].id}`"></edit-documents-modal>
</div>
</div>
<div class="relative flex items-center justify-center">
<!--Show more button-->
<button class="absolute border focus:outline-none hover:bg-certstyle-orange bg-white border-certstyle-orange hover:text-white text-certstyle-orange font-bold text-sm rounded px-4 py-1 mt-32 " v-if="showAmount < documents.length" #click="showMore">
show more documents
</button>
</div>
</div>
</show-more>
Now the issue is, When I tried to run this, I get following console error and my data table is not getting displayed. Not even the headers...
[Vue warn]: Error in render: "TypeError: Cannot read properties of
undefined (reading 'length')"
Its better to use computed property to handle these situations
computed: {
getDocumentSize() {
return this.documents ? this.documents.length : 0;
}
}
and in template, do the below change
<show-more :data-size="getDocumentSize" increment-amount="5" >
....

Vuelidate & Tailwind: Why am I always seeing invalid errors?

For the life of me I cannot seem to understand why I am always seeing the validation error(s). The logic is working great, it seems to all be in my :class binding(s) that I've got it all wrong. I know I'm going to feel really silly when I get this figured out, but after countless tutorials that I feel like I've literally copy/paste from, I'm still in the same boat.
Here is my template for email. The password input is the same...
<div class="relative">
<label for="email" class="sr-only block text-sm font-medium leading-5 text-gray-700">
Email address
</label>
<input type="email"
id="email"
v-model.trim="$v.user.email.$model"
:class="{ 'border-red-500': !$v.user.email.required}"
placeholder="Email"
class="mt-1 placeholder-gray-400 shadow appearance-none border rounded w-full py-3 px-3 text-gray-700 leading-tight transition duration-150 ease-in-out sm:text-sm sm:leading-5 focus:outline-none focus:border-gray-400 focus:shadow-outline-gray"
/>
<div class="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none"
v-if="!$v.user.email.required">
<svg
class="h-5 w-5 text-red-500"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fill-rule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z"
clip-rule="evenodd"
/>
</svg>
</div>
</div>
<div>
<p class="mt-2 text-sm text-red-600" v-if="!$v.user.email.required">
Email is required
</p>
<p class="mt-2 text-sm text-red-600" v-if="!$v.user.email.email">
Please use a valid email address
</p>
</div>
This is what my script block looks like:
data: () => ({
errors: false,
user: {
email: "",
password: "",
},
}),
validations: {
user: {
email: { required, email },
password: { required },
},
},
methods: {
async handleSignIn() {
this.$v.user.$touch();
this.empty = !this.$v.user.$anyDirty;
this.errors = this.$v.user.$anyError;
if (this.$v.$invalid) {
this.errors = true;
} else {
try {
...
}
}
}
As I enter a valid email and/or password, the validation errors go away. If I try to submit with invalid data, the validator is working properly. With a valid email/password, I'm able to successfully submit the form.
When the page first loads, here is what my form looks like. How can I correctly render the form to only show the errors if a field is invalid?
Thank you for any suggestions!
Try to add the $v.user.email.$error condition to the border class binding, the icon and the error message :
<div id="app">
<div class="relative">
<label for="email" class="sr-only block text-sm font-medium leading-5 text-gray-700">
Email address
</label>
<input type="email" id="email" v-model.trim="$v.user.email.$model" :class="{ 'border-red-500': $v.user.email.$error}" placeholder="Email" class="mt-1 placeholder-gray-400 shadow appearance-none border rounded w-full py-3 px-3 text-gray-700 leading-tight transition duration-150 ease-in-out sm:text-sm sm:leading-5 focus:outline-none focus:border-gray-400 focus:shadow-outline-gray" />
<div class="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none" v-if="!$v.user.email.required">
<svg v-if="$v.user.email.$error" class="h-5 w-5 text-red-500" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clip-rule="evenodd" />
</svg>
</div>
</div>
<div>
<p class="mt-2 text-sm text-red-600" v-if="$v.user.email.$error">
Email is required
</p>
<p class="mt-2 text-sm text-red-600" v-if="!$v.user.email.email">
Please use a valid email address
</p>
<button class="rounded w-full flex justify-center text-gray-100 bg-purple-700 hover:bg-purple-800 px-6 py-2 flex items-center">
Submit
</button>
</div>
</div>
LIVE DEMO

SVG inside Razor Pages Form

I'm using Tailwind CSS, .NET Core 3.1 Razor Pages and get the following error
Found a malformed 'input' tag helper. Tag helpers must have a start and end tag or be self closing
with this code
<form asp-route="Search" method="get">
<label for="place-address" class="block text-sm font-medium leading-5 text-gray-700">Enter your address</label>
<div class="mt-1 flex rounded-md shadow-sm">
<div class="relative flex-grow focus-within:z-10">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<svg class="h-5 w-5 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" clip-rule="evenodd" />
</svg>
</div>
<input asp-for="Address" id="place-address" class="form-input block w-full rounded-none rounded-l-md pl-10 transition ease-in-out duration-150 sm:text-sm sm:leading-5" />
</div>
<button type="submit" class="-ml-px relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm leading-5 font-medium rounded-r-md text-gray-700 bg-gray-50 hover:text-gray-500 hover:bg-white focus:outline-none focus:shadow-outline-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150">
<svg class="h-5 w-5 text-gray-400" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" ">
<path d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
</svg>
<span class="ml-2">Search</span>
</button>
</div>
</form>
When I remove the SVG elements the error goes away. How can I keep the SVG elements and make this form work