Dropdown component not show selected option Laravel inertia (vue) - laravel

hi all I'm using laravel inertia and I'm filling a Dropdown with locations. But when I select one, doesn't show as a selected item in the dropdown. I need help to load the selected option.
When I select one. in console I get "Cannot create property 'id' on string ''
Here I describe my code
#### Function create in CompanyController
```
public function create() { $locations = Location::orderBy('name')->get(); return Inertia::render('Companies/Create', [ 'locations' => $locations, ]); }
```
if I inspect on vuedevtools, I can see the locations array
In my Dropdown I've done a foreach locations in #content section.
Dropdown component
<Dropdown align="left" width="60">
<template #trigger>
<div class="relative">
<button type="button"
class="inline-flex justify-between w-full rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
id="options-menu" aria-haspopup="true" aria-expanded="true">
<span v-if="form.locations === ''">Select Location</span>
<span v-else>{{ form.locations }}</span>
<svg class="-mr-1 ml-2 h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"
fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd"
d="M5 8a1 1 0 011.707 0L10 11.293l3.293-3.294a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4A1 1 0 015 8z"
clip-rule="evenodd" />
</svg>
</button>
</div>
</template>
<template #content>
<div class="py-1" role="none">
<button v-for="location in locations" :key="location.id" type="button"
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"
role="menuitem" #click="form.locations.id = location.id">
{{ location.name }}
</button>
</div>
</template>
</Dropdown>
```
#### Here some screenshots of the form view (locations are faker words)
#### screenshot of error in console (when location is selected)
Here the complete Create Component
https://codeshare.io/N3Mxw1
Thanks in advance
I spect all locations filled on Dorpdown component and whe a location is selected, its show in dropdown, ready to send to store by id.

Related

Alpinejs Hide/Show element inside laravel foreach loop

I am using alpinejs with laravel for a project, for every row of data i want to add hide/show button to show a descritption , the problem when i press show every decription inside foreach show and same for hide
#foreach ($positives as $positive)
<!-- Card -->
<div class="bg-white rounded-lg p-4 shadow-xs dark:bg-gray-800">
<div class=" flex items-center justify-between p-4 bg-white rounded-lg
dark:bg-gray-800">
<div class="flex items-center">
<div
class="p-3 mr-4 text-orange-500 bg-orange-100 rounded-full dark:text-orange-100 dark:bg-orange-500 grow-0">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24"
stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round"
d="M12 8v13m0-13V6a2 2 0 112 2h-2zm0 0V5.5A2.5 2.5 0 109.5 8H12zm-7 4h14M5 12a2 2 0 110-4h14a2 2 0 110 4M5 12v7a2 2 0 002 2h10a2 2 0 002-2v-7" />
</svg>
</div>
<div>
<p class="mb-2 text-sm font-medium text-gray-600 dark:text-gray-400">
{{$positive->name}}
</p>
<p class="text-lg font-semibold text-gray-700 dark:text-gray-200">
376
</p>
</div>
</div>
<div class=" cursor-pointer mb-8" #click="isDescriptionOpen=!isDescriptionOpen">
</div>
<div x-show="isDescriptionOpen">
<p> description </p>
</div>
</div>
<!-- Card -->
#endforeach
The problem here is that you don't have multiple components created.
Instead of:
<!-- Card -->
<div class="bg-white rounded-lg p-4 shadow-xs dark:bg-gray-800">
you should have
<!-- Card -->
<div class="bg-white rounded-lg p-4 shadow-xs dark:bg-gray-800" x-data="{isDescriptionOpen: false}">
and you should remove outer component that you probably created for isDescriptionOpen data.

Laravel pagination style is broken

The pagination in my project displays as shown below:
And renders the following HTML:
<nav role="navigation" aria-label="Pagination Navigation" class="flex items-center justify-between">
<div class="flex justify-between flex-1 sm:hidden">
<span
class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md">
« Précédent
</span>
<a href="http://127.0.0.1:8000/clients?page=2"
class="relative inline-flex items-center px-4 py-2 ml-3 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150">
Suivant »
</a>
</div>
<div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
<div>
<p class="text-sm text-gray-700 leading-5">
Showing
<span class="font-medium">1</span>
to
<span class="font-medium">10</span>
of
<span class="font-medium">11</span>
results
</p>
</div>
<div>
<span class="relative z-0 inline-flex shadow-sm rounded-md">
<span aria-disabled="true" aria-label="&laquo; Précédent">
<span
class="relative inline-flex items-center px-2 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default rounded-l-md leading-5"
aria-hidden="true">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd"
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
clip-rule="evenodd" />
</svg>
</span>
</span>
<span aria-current="page">
<span
class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5">1</span>
</span>
<a href="http://127.0.0.1:8000/clients?page=2"
class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 hover:text-gray-500 focus:z-10 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150"
aria-label="Go to page 2">
2
</a>
<a href="http://127.0.0.1:8000/clients?page=2" rel="next"
class="relative inline-flex items-center px-2 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 rounded-r-md leading-5 hover:text-gray-400 focus:z-10 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-500 transition ease-in-out duration-150"
aria-label="Suivant &raquo;">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd"
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
clip-rule="evenodd" />
</svg>
</a>
</span>
</div>
</div>
</nav>
Which in an isolated environment from my project results in:
Last time I seen the pagination in my project is a month ago, after that I:
Upgraded from Laravel 8 to Laravel 9.
Upgraded from Tailwind 2.6^ to Tailwind 3^.
Upgraded Mix
Deleted some of the components that comes by default with Breeze scafolding .
Edit
When I export the pagination views to resources\views using:
php artisan vendor:publish --tag=laravel-pagination
Then run:
npm run dev
The pagination is fixed!
But When I delete resources\views\vendor\pagination and rerun npm run dev, The pagination is broken again!
This makes me think that Mix is missing the CSS classes used in the pagination element. which wasn't the case before I upgrade.
So how can I fix this? (exporting feels like a patch and not a solution).
By going back to the guide Upgrading your Tailwind CSS projects from v2 to v3 I noticed:
If you weren’t already using the purge option in your project, it’s crucial that you configure your template paths now or your compiled CSS will be empty.
I fixed the issue by referencing "./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php" in tailwind.config.js and running npm run dev
const defaultTheme = require("tailwindcss/defaultTheme");
module.exports = {
content: [
"./resources/**/*.blade.php",
"./resources/**/*.js",
"./resources/**/*.vue",
"./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php",
],
// ...
}
Checking my upgrade commit
Because I blindly followed the "Laravel with Tailwind 3 docs/posts" without noticing that they did not consider the Pagination.

I can't dispatch event in Alpinejs

I am using Laravel 8, Alpinejs and Livewire and having this problem:
This is my index file:
#extends('dashboard')
#section('content')
<header class="max-w-7xl mx-auto bg-white flex items-center justify-between">
<div class="mx-9 py-6 mt-4">
<h1 class="text-3xl font-bold text-gray-900">
Boards
</h1>
</div>
<div class="mx-9 py-6 mt-4">
<a href="#" #click="
$dispatch('custom-event')
"
class="w-28 text-base text-white bg-blue hover:text-gray-50 hover:bg-blue-hover rounded-xl py-2 px-3 leading-none transition ease-in duration-150 text-center">
Create new board
</a>
</div>
</header>
<livewire:boards-table
:boards="$boards"
/>
<livewire:create-board />
#endsection
When I click the "Create new board" button in the header tag, I want the create-board livewire component to be displayed. So I used #click="$dispatch('custom-event').
And here is my create-board file:
<div
x-cloak
x-data="{ isOpen: false }"
x-show="isOpen"
#keydown.escape.window="isOpen = false"
#custom-event.window="isOpen = true"
class="fixed z-20 inset-0 overflow-y-auto"
aria-labelledby="modal-title"
role="dialog"
aria-modal="true"
>
<div class="flex items-end justify-center min-h-screen">
<div x-show.transition.opacity="isOpen" class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity"
aria-hidden="true">
</div>
<div x-show.transition.origin.bottom.duration.300ms="isOpen"
class="modal bg-white rounded-tl-xl rounded-tr-xl overflow-hidden transform transition-all sm:max-w-lg sm:w-full">
<div class="absolute top-0 right-0 pt-6 pr-6">
<button #click="isOpen = false" class="text-gray-400 hover:text-gray-500">
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd"
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
clip-rule="evenodd" />
</svg>
</button>
</div>
<div class="bg-white sm:p-6 my-3">
<h3 class="text-center text-xl font-bold text-gray-900">Create a new board</h3>
<form wire:submit.prevent="createBoard" action="#" method="POST" class="space-y-4 px-4 pt-6">
<div>
<input wire:model.defer="boardName" type="text"
class="w-full bg-gray-100 rounded-xl placeholder-gray-900 border-none font-semibold px-4 text-sm"
placeholder="Board name">
</div>
<div>
<input wire:model.defer="urlName" type="text"
class="w-full bg-gray-100 rounded-xl placeholder-gray-900 border-none font-semibold px-4 py-2 text-sm"
placeholder="Short name (used in board URL)">
</div>
<div class="flex items-center justify-end">
<button type="submit"
class="text-center w-44 bg-blue font-bold h-11 text-sm text-white rounded-xl border border-blue hover:bg-blue-hover transition duration-150 ease-in px-6 py-3 mr-4 mt-2">Create new board</button>
</div>
</form>
</div>
</div>
</div>
</div>
But when I click on "Create new board" button, nothing happens.
Create-board component is still rendered in the browser.

Change value of select option by clicking anchor tag with Alpine.js

I'm using x-data to dynamically build my HTML. I have two anchor tags which act as tab buttons to'x-show' a paragraph depending on which link is clicked. I also would like that anchor tag to select an option on the form's select element. It kind of works when you starts clicking on the buttons but initially the select options are empty?
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine#v2.x.x/dist/alpine.min.js"></script>
<div x-data="{activeTab : window.location.hash ? window.location.hash.substring(1) : 0, lessons:[{id:0,room:'online',description:'Online description'},{id:1,room:'in class',description:'in class description'}]}" class="w-full">
<nav class="w-full flex flex-no-wrap justify-between mb-8">
<template x-for="lesson in lessons">
<a href="#" #click.prevent="activeTab = lesson.id; window.location.hash = 0; select = lesson.room" class="focus:outline-none focus:text-teal-800 hover:text-teal-800 meta bold py-1 uppercase mr-1 flex items-center justify-between text-lg w-1/2 border-b-4 focus:border-teal-800 hover:border-teal-800 border-teal-600 tracking-widest text-teal-600"><span x-text="lesson.room"></span><svg class="w-6 h-6" width="6" height="6" viewBox="0 0 21 21" xmlns="http://www.w3.org/2000/svg">
<path d="m8.5.5-4 4-4-4" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" transform="translate(6 8)" /></svg></a>
</template>
</nav>
<template x-for="lesson in lessons">
<div x-show="activeTab === lesson.id">
<p x-text="lesson.description" class="text-gray-800 mb-6">Online classes are streaemed to your device. You can atned a yoga class wherever there is a why-fi</p>
</div>
</template>
<form action="">
<fieldset class="border p-4">
<legend class="text-center text-xs uppercase tracking-widest text-orange-800 px-2">choose a classroom</legend>
<select class="uppercase text-lg tracking-widest text-teal-800 w-full border border-teal-800 px-5 py-4 focus:outline-none focus:border-shadow rounded" name="" id="" x-model="select">
<template x-for="lesson in lessons">
<option x-text="lesson.room"></option>
</template>
</select>
</fieldset>
</form>
</div>
I added:
x-init="select = lessons[0].room"
to the parent of the component which set the select to the initial value
A better way would be to add this onto the select
<select x-model="foo" x-init="foo = $el.options[$el.selectedIndex || 0].value">

Q: how to make use of Alpinejs and tailwindcss within Laravel?

I am trying to make use of Alpinejs using Adam Wathan's responsive navbar using vuejs, but i am experimenting if i can get it to work with Alpinejs.
app.blade.php
<head>
[...]
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine#v2.x.x/dist/alpine.min.js" defer></script>
[...]
</head>
In case you are wondering if Alpine is already loaded, it is working trying a simple dropdown toggle, but with this approach i find it hard to get it working.
Navbar.blade.php
#guest('applicant')
#else
<header class="bg-gray-900 sm:flex sm:items-center sm:justify-between xl:bg-white" x-data="dropdown()">
<div class="flex justify-between px-4 py-3 xl:w-72 xl:bg-gray-900 xl:justify-center xl:py-5">
<div>
[...]
</div>
<div class="flex sm:hidden">
<button x-on:click="open" type="button"
class="px-2 text-gray-500 hover:text-white focus:outline-none focus:text-white">
<svg class="h-6 w-6 fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path x-if="isOpen" fill-rule="evenodd" clip-rule="evenodd"
d="M18.278 16.864a1 1 0 0 1-1.414 1.414l-4.829-4.828-4.828 4.828a1 1 0 0 1-1.414-1.414l4.828-4.829-4.828-4.828a1 1 0 0 1 1.414-1.414l4.829 4.828 4.828-4.828a1 1 0 1 1 1.414 1.414l-4.828 4.829 4.828 4.828z" />
<path x-if="!isOpen" fill-rule="evenodd"
d="M4 5h16a1 1 0 0 1 0 2H4a1 1 0 1 1 0-2zm0 6h16a1 1 0 0 1 0 2H4a1 1 0 0 1 0-2zm0 6h16a1 1 0 0 1 0 2H4a1 1 0 0 1 0-2z" />
</svg>
</button>
</div>
</div>
<nav class="sm:flex sm:items-center sm:px-4 xl:flex-1 xl:justify-between"
:class="{ 'hidden': !isOpen, 'block': isOpen }" x-show="open" x-on:click.away="close">
<div class="hidden xl:block xl:relative xl:max-w-xs xl:w-full">
[...]
</div>
<div class="sm:flex sm:items-center">
[...]
<div class="relative px-5 py-5 sm:py-0 sm:ml-4 sm:px-0">
[...]
<Dropdown class="hidden sm:block">
<template #trigger="{ hasFocus, isOpen }">
<span class="block h-8 w-8 overflow-hidden rounded-full border-2 "
:class="[(hasFocus || isOpen) ? 'border-white xl:border-indigo-500' : 'border-gray-600 xl:border-gray-300']">
<img class="h-full w-full object-cover"
src="https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=256&q=80"
alt="">
</span>
</template>
<template #dropdown>
<div class="mt-3 bg-white xl:border rounded-lg w-48 py-2 shadow-xl">
<a href="#account" class="block hover:text-white text-gray-800 px-4 py-2 hover:bg-indigo-500">Account
settings</a>
<a href="#support"
class="block hover:text-white text-gray-800 mt-0 px-4 py-2 hover:bg-indigo-500">Support</a>
<a href="#sign-out" class="block hover:text-white text-gray-800 mt-0 px-4 py-2 hover:bg-indigo-500">Sign
out</a>
</div>
</template>
</Dropdown>
</div>
</div>
</nav>
</header>
<script>
function dropdown() {
return {
open: false,
open() {
this.show = true
},
close() {
this.show = false
},
toggle() {
this.isOpen = !this.isOpen
},
}
}
</script>
#endguest
You do not need to add the scripts to make a dropdown open and close.
You need to have x-data defined in a parent (to both button and dropdown) div. Then reference it in the button and/or dropdown elements.
A simple example:
<div x-data="{isOpen : false}">
<button x-on:click="isOpen = !isOpen" class="button">Menu</button>
<!-- you need to toggle isOpen state on click. You can also use #click just like in vue -->
<div x-show="isOpen" class="dropdown"> <!-- x-show to show and hide -->
Account settings
Support
</div>
</div>
That is all there is to make a dropdown using alpine js.
In my case i didn't my javascript nor installed it, i just used the cdn
{{-- scrip --}}
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine#v2.x.x/dist/alpine.min.js" defer></script>
and had installed tailwind css. my code is..
<div x-data="{dropdownMenu: false}" class="lg:inline-block relative">
<!-- Dropdown toggle button -->
<button #click="dropdownMenu = ! dropdownMenu"
class="text-base no-underline hover:bg-indigo-300 hover:text-cool-gray-900 rounded-3xl py-1 px-2 ">
<span class="sr-only">{{ Auth::user()->name }}</span>
<img class="h-8 w-8 rounded-full"
src="https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=4&w=256&h=256&q=60"
alt="avatar">
</button>
<!-- Dropdown list -->
<div x-show="dropdownMenu"
class="absolute right-0 py-2 mt-2 bg-white bg-gray-100 rounded-md shadow-xl w-44">
<a href="#"
class="block px-4 py-2 text-sm text-gray-300 text-gray-700 hover:bg-gray-400 hover:text-white">
Your Profile
</a>
<a href="#"
class="block px-4 py-2 text-sm text-gray-300 text-gray-700 hover:bg-gray-400 hover:text-white">
Settings
</a>
<a href="#"
class="block px-4 py-2 text-sm text-gray-300 text-gray-700 hover:bg-gray-400 hover:text-white">
Reports
</a>
<a href="{{ route('logout') }}"
class="block px-4 py-2 text-sm text-gray-300 text-gray-700 hover:bg-gray-400 hover:text-white"
onclick="event.preventDefault();document.getElementById('logout-form').submit();">{{ __('Logout') }}</a>
<form id="logout-form" action="{{ route('logout') }}" method="POST"
class="hidden">
{{ csrf_field() }}
</form>
</div>
</div>
this was my result when i click the avatar..
i hope this will assist you solve your problem

Resources