LARAVEL Publish and Not-publish Function has issue - laravel

I am creating a blog site, but I am having a problem as when the user clicks on the button "Create New Post," there is a form display (Create new post picture). There are two checkboxes, "Published" "Not-Published," in the form. When the user checks "Published," their post will be displayed on the Post site with the status "Published". When the user checks "Not-Published," their post will not be displayed on the Post site, but in the post database.
On the Post site, I have to radio button. The first is "Publish Posts," which will display only publish posts, the second is "All Posts," which will display all the posts include the "Not-Published" post.
I have a problem as when I click on the "Publish Posts," only the published posts will be displayed, which is good. But when I click on the "All Posts," still the published posts are displayed, I don't see any "Not-Published" posts. I checked the database and saw the "Not-Published" posts there, so why don't appear when I click "All Posts". Can someone help me to fix it?
Post site
Create new post
posts.blade.php
<button wire:click="create()" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded my-3">Create New Post</button>
#if($isOpen)
#include('livewire.create')
#endif
<div class="float-right">
<span class="mr-3 d-inline">
<label class="inline-flex items-center">
<input type="radio" class="form-radio" wire:model="viewAll" value="0">
<span class="ml-2">Publish Posts</span>
</label>
<label class="inline-flex items-center ml-6">
<input type="radio" class="form-radio" wire:model="viewAll" value="1">
<span class="ml-2">All Posts</span>
</label>
</span>
</div>
<table class="table-fixed w-full">
<thead>
<tr class="bg-gray-100">
<th class="px-4 py-2 w-20">No.</th>
<th class="px-4 py-2">Title</th>
<th class="px-4 py-2">Body</th>
<th class="px-4 py-2">Published</th>
<th class="px-4 py-2">Action</th>
</tr>
</thead>
<tbody>
#foreach($posts as $post)
#if($post->published == 1)
<tr>
<td class="border px-4 py-2">{{ $post->id }}</td>
<td class="border px-4 py-2 overflow-ellipsis truncate ">{{ $post->title }}</td>
<td class="border px-4 py-2 overflow-ellipsis truncate">{{ $post->body }}</td>
<td class="border px-4 py-2 overflow-ellipsis truncate">Published</td>
<td class="border px-4 py-2">
<button class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded">View</button>
#if (Auth::user()->id == $post->user_id )
<button wire:click="edit({{ $post->id }})" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Edit</button>
<button wire:click="delete({{ $post->id }})" class="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">Delete</button>
#endif
</td>
</tr>
#endif
#endforeach
</tbody>
</table>
Post Schema
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string("title");
$table->string("body");
$table->boolean("published");
$table->integer("user_id")->unsigned()->index();
$table->timestamps();
});
create.blade.php
<div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" role="dialog" aria-modal="true" aria-labelledby="modal-headline">
<form>
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="">
<div class="mb-4">
<label for="exampleFormControlInput1" class="block text-gray-700 text-sm font-bold mb-2">Title:</label>
<input type="text" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="exampleFormControlInput1" placeholder="Enter Title" wire:model="title">
#error('title') <span class="text-red-500">{{ $message }}</span>#enderror
</div>
<div class="mb-4">
<label for="exampleFormControlInput2" class="block text-gray-700 text-sm font-bold mb-2">Body:</label>
<textarea class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="exampleFormControlInput2" wire:model="body" placeholder="Enter Body"></textarea>
#error('body') <span class="text-red-500">{{ $message }}</span>#enderror
</div>
<div class="mb-4">
<label class="inline-flex items-center">
<input type="radio" class="form-radio" wire:model="published" name="published" value="1">
<span class="ml-2">Published</span>
</label>
<label class="inline-flex items-center ml-6">
<input type="radio" class="form-radio" wire:model="published" name="published" value="0">
<span class="ml-2">Not-Published</span>
</label>
#error('published') <span class="text-red-500">{{ $message }}</span>#enderror
</div>
</div>
</div>
Post Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
protected $fillable = [
'title', 'body', 'published', 'user_id'
];
public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(User::class);
}
}
app/Http/Livewire/Posts.php
<?php
namespace App\Http\Livewire;
use http\Env\Request;
use Livewire\Component;
use App\Models\Post;
use Illuminate\Support\Facades\Auth;
class Posts extends Component
{
public $posts, $title, $body, $published, $post_id;
public $viewAll = 0;
public $title_filter;
public $isOpen = 0;
public function render()
{
if($this->viewAll == 0){
$this->posts = Post::where('user_id', Auth::user()->id)
->where('title', 'like', '%' . $this->title_filter. '%')
->get();
} else {
$this->posts = Post::where('user_id', Auth::user()->id)
->where('title', 'like', '%' . $this->title_filter. '%')
->get();
}
return view('livewire.posts');
}
public function create()
{
$this->resetInputFields();
$this->openModal();
}
public function openModal()
{
$this->isOpen = true;
}
public function closeModal()
{
$this->isOpen = false;
}
private function resetInputFields(){
$this->title = '';
$this->body = '';
$this->post_id = '';
}
public function store()
{
$this->validate([
'title' => 'required',
'body' => 'required',
'published' => 'required'
]);
Post::updateOrCreate(['id' => $this->post_id], [
'title' => $this->title,
'body' => $this->body,
'published' => $this->published,
'user_id' => Auth::user()->id
]);
session()->flash('message',
$this->post_id ? 'Post Updated Successfully.' : 'Post Created Successfully.');
$this->closeModal();
$this->resetInputFields();
}
/**
* The attributes that are mass assignable.
*
* #var array
*/
public function edit($id)
{
$post = Post::findOrFail($id);
$this->post_id = $id;
$this->title = $post->title;
$this->body = $post->body;
$this->published = $post->published;
$this->openModal();
}
/**
* The attributes that are mass assignable.
*
* #var array
*/
public function delete($id)
{
Post::find($id)->delete();
session()->flash('message', 'Post Deleted Successfully.');
}
}

try this
#foreach($posts as $post)
#if($post->published == 1)
<tr>
<td class="border px-4 py-2">{{ $post->id }}</td>
<td class="border px-4 py-2 overflow-ellipsis truncate ">{{
$post->title }}</td>
<td class="border px-4 py-2 overflow-ellipsis truncate">{{
$post->body }}</td>
<td class="border px-4 py-2 overflow-ellipsis
truncate">Published</td>
<td class="border px-4 py-2">
#elseif($post->published == 0)
<tr>
<td class="border px-4 py-2">{{ $post->id }}</td>
<td class="border px-4 py-2 overflow-ellipsis truncate ">{{
$post->title }}</td>
<td class="border px-4 py-2 overflow-ellipsis truncate">{{
$post->body }}</td>
<td class="border px-4 py-2 overflow-ellipsis
truncate">Published</td>
<td class="border px-4 py-2">
#else
<tr>
<td class="border px-4 py-2">{{ $post->id }}</td>
<td class="border px-4 py-2 overflow-ellipsis truncate ">{{
$post->title }}</td>
<td class="border px-4 py-2 overflow-ellipsis truncate">{{
$post->body }}</td>
<td class="border px-4 py-2 overflow-ellipsis
truncate">Published</td>
<td class="border px-4 py-2">
#endif
<button class="bg-green-500 hover:bg-green-700 text-white
font-bold py-2 px-4 rounded"><a href="/posts/{{ $post->id
}}">View</a></button>
#if (Auth::user()->id == $post->user_id )
<button wire:click="edit({{ $post->id }})" class="bg-
blue-500 hover:bg-blue-700 text-white font-bold py-2
px-4 rounded">Edit</button>
<button wire:click="delete({{ $post->id }})" class="bg-
red-500 hover:bg-red-700 text-white font-bold py-2
px-4 rounded">Delete</button>
#endif
</td>
</tr>
#endforeach

I think that the way you are trying to handle the radio isn't well. I recommend you try with different properties for each radiobutton like
<div>
<input type="radio" name="published" id="published" wire:model="viewPublished">
<label for="published">Published</label>
<input type="radio" name="all" id="all" wire:model="viewAll">
<label for="all">All</label>
</div>
In the component
public $viewAll = 'on';
public $viewPublished = 'off';
public function render()
{
if ($this->viewAll == 'on')
{
return view('livewire.radio-component', ['posts' => Post::all()]); // retrieve all posts
}
else
{
return view('livewire.radio-component', ['posts' => Post::where('published','=',1)->get()]); //....retrieve only published post
}
}
public function updatedViewAll()
{
if($this->viewAll == 'on')
$this->viewPublished = 'off';
}
public function updatedViewPublished()
{
if ($this->viewPublished == 'on')
$this->viewAll = 'off';
}

Related

Why is my Laravel date column displaying a time as well?

I am developing a prototype in Laravel 9 which currently contains 7 user tables. Several of those tables contain dates and all of them are defined as Laravel dates; they are all defined as MySQL dates in the database as well. I can't figure out why one of those date columns displays all its dates as a regular date, followed by a blank and then a time - 00:00:00 - whenever displayed in my blade templates. All of the other date columns display as a date (YYYY-MM-DD) without a time.
I am NOT requesting that a time (which is always 00:00:00/midnight) be shown in that column. Why is Laravel doing this and how can I make it stop?
I realize that I can suppress the time by appending ->format('Y-m-d') but I shouldn't have to do that in the first place; if I only store a date rather that a DateTime or Timestamp, there should only be a date in the column and no need to suppress the time to keep it from displaying.
UPDATE
Here is the migration for the table that is giving me trouble:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('non_driving_weekdays', function (Blueprint $table) {
$table->date('non_driving_weekday_date');
$table->string('reason', 50);
$table->timestamps();
$table->primary('non_driving_weekday_date', 'non_driving_weekday_date_PK');
$table->foreign('reason', 'reason_FK')->references('reason_for_not_driving')->on('non_driving_reasons')->onUpdate('cascade')->onDelete('restrict');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('non_driving_weekdays');
}
};
Here is the blade that displays the index:
<x-layout>
<div class="bg-gradient-to-b from-red-500 to-purple-100">
<h1 class="text-3xl text-center text-white font-bold bg-indigo-700">Non-driving Weekdays - Index</h1>
<h1 class="pb-5"></h1><!-- spacer beneath title -->
#if (session()->has('message'))
<div id="message"
x-data="{show: true}"
x-init="setTimeout(() => show = false, 5000)"
x-show="show"
class="w-1/3 mx-auto text-center text-black bg-yellow-300 rounded-md">
<p class="text-xl py-1">{{session('message')}}</p>
</div>
#endif
<div class="flex justify-center h-screen" style="display: grid; grid-template-rows: auto auto auto auto; row-gap: 10px; padding: 10px">
<table><tr><td><img src="{{asset('icons/green-plus-circle-outline.svg')}}" width="50" alt="add icon"></td><td class="font-bold">Add a new date where the drivers didn't drive</td></tr></table>
{{-- If there are no non-driving weekdays, indicate that to the user. --}}
#if (count($nonDrivingWeekdays) == 0)
<p>No non-driving weekdays found.</p>
#else
{{-- If there are non-driving weekdays, display them. --}}
<div>
<table class="border-black border-2 bg-white">
<thead class="border-black border-2 text-white bg-gray-800">
<tr class="content-center">
<th class="border-black border-2 p-2 text-left">Date</th>
<th class="border-black border-2 p-2 text-left">Reason</th>
<th class="border-black border-2 p-2">View</th>
<th class="border-black border-2 p-2">Edit</th>
<th class="border-black border-2 p-2">Delete</th></tr>
</thead>
<tbody class="border-black border-2">
#foreach($nonDrivingWeekdays as $nonDrivingWeekday)
<tr class="border-black border-2">
{{-- ->format('Y-m-d') --}}
<td class="border-black border-2 p-2">{{$nonDrivingWeekday->non_driving_weekday_date}}</td>
<td class="border-black border-2 p-2">{{$nonDrivingWeekday->reason}}</td>
<td class="border-black border-2 p-2 text-center"><img src="{{asset('icons/magenta-details.svg')}}" width="25" alt="view icon"></td>
<td class="border-black border-2 p-2 text-center"><img src="{{asset('icons/yellow-lead-pencil.svg')}}" width="25" alt="update icon"></td>
<td class="border-black border-2 p-2 text-center">
<form method="POST" action="/nonDrivingWeekdays/destroy/{{$nonDrivingWeekday->non_driving_weekday_date}}">
#csrf
#method('DELETE')
<button><img src="{{asset('icons/red-delete.svg')}}" width="25" alt="delete icon"></button>
</form></td>
</td>
</tr>
#endforeach
</tbody>
</table>
</div>
#endif
<div>
<p class="mt-6 p-4">{{$nonDrivingWeekdays->links()}}</p>
</div>
</div>
</div>
</x-layout>
This is the blade for the show() method:
<x-layout>
{{-- <x-card class="p-10"> --}}
<div class="bg-gradient-to-b from-purple-500 to-purple-100 h-screen">
<h1 class="text-3xl text-center text-white font-bold bg-indigo-700">Non-driving Weekdays - Show One Weekday</h1>
<h1 class="pb-5"></h1><!-- spacer beneath title -->
<form method="GET" enctype="multipart/form-data" class="w-4/5 mx-auto">
<div class="mb-6">
<label for="non_driving_weekday_date" class="inline-block text-lg mb-2">Reason</label>
<input type="text" disabled class="border border-gray-200 rounded p-2 w-full" name="non_driving_weekday_date" value="{{$nonDrivingWeekday->non_driving_weekday_date}}"/>
</div>
<div class="mb-6">
<label for="reason" class="inline-block text-lg mb-2">Reason</label>
<input type="text" disabled class="border border-gray-200 rounded p-2 w-full" name="reason" value="{{$nonDrivingWeekday->reason}}"/>
</div>
<div class="mb-6">
{{-- Cancel submission of the form --}}
<button type="button" class="text-xl text-white bg-black rounded-md py-2 px-4 hover:bg-white hover:text-black hover:outline hover:outline-2 hover:outline-black">Cancel</button>
</div>
</form>
{{-- </x-card> --}}
</div>
</x-layout>
And this is the blade template for the edit() method:
<x-layout>
{{-- <x-card xclass="p-10 max-w-lg mx-auto mt-24"> --}}
<div class="bg-gradient-to-b from-yellow-500 to-yellow-100 h-screen">
<h1 class="text-3xl text-center text-white font-bold bg-indigo-700">Non-driving Weekdays - Edit One Weekday</h1>
<h1 class="pb-5"></h1><!-- spacer beneath title -->
<form method="POST" action="/nonDrivingWeekdays/update/{{$nonDrivingWeekday->non_driving_weekday_date}}" enctype="multipart/form-data" class="w-4/5 mx-auto">
#csrf
#method('PUT')
<div class="mb-6">
<label for="non_driving_weekday_date" class="inline-block text-lg mb-2">Non-driving weekday date</label>
<input type="text" class="border border-gray-200 rounded p-2 w-full" name="non_driving_weekday_date" value="{{$nonDrivingWeekday->non_driving_weekday_date}}"/>
#error('non_driving_weekday_date')
<p class="text-red-500 font-bold text-m mt-1">{{$message}}</p>
#enderror
</div>
<div class="mb-6">
<label for="reason" class="inline-block text-lg mb-2">Reason</label>
<select id="reason" name="reason" class="h-10">
#foreach($reasons as $reason)
#if($reason->reason_for_not_driving === $nonDrivingWeekday->reason)
<option selected class="mx-10" value="{{$reason->reason_for_not_driving}}">{{$reason->reason_for_not_driving}}</option>
#else
<option class="mx-10" value="{{$reason->reason_for_not_driving}}">{{$reason->reason_for_not_driving}}</option>
#endif
#endforeach
</select>
</div>
<div class="mb-6">
{{-- Submit the completed form --}}
<button class="text-xl text-white bg-orange-500 rounded-md py-2 px-4 hover:bg-white hover:text-orange-500 hover:outline hover:outline-2 hover:outline-orange-500">Submit</button>
{{-- Cancel submission of the form --}}
<button type="button" class="text-xl text-white bg-black rounded-md py-2 px-4 hover:bg-white hover:text-black hover:outline hover:outline-2 hover:outline-black">Cancel</button>
</div>
</form>
{{-- </x-card> --}}
</div>
</x-layout>
Lastly, here is the model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class NonDrivingWeekdays extends Model
{
use HasFactory;
protected $fillable = ['non_driving_weekday_date', 'reason'];
protected $primaryKey = 'non_driving_weekday_date';
protected $keyType = 'date';
public $incrementing = 'false';
}
StewieSWS gave me the clue that helped me solve this: I wasn't displaying the dates in form fields that were <input type="date">. Frankly, I'd forgotten there was a special input type for dates! In the blade for my index() method, I was displaying the data as a cell in a table and in the blades for the edit(), show() and create() methods, I was displaying them in <input type="text"> fields. As soon as I started displaying the dates in <input type="date"> fields, they started displaying as normal dates WITHOUT any time component. I even got a little calendar icon at the right end of the box which lets me pick a date from calendar. As an added bonus, I even got some additional validating: when I tried to enter an impossible date, Feb 30, 2023, the input field detected it and displayed an appropriate message.

Dynamic form with dependent dropdown in laravel livewire

I have followed this youtube link for populating dynamic form and i have it working in other livewire component. And also use this link to populate dependent dropdown in another livewire component, and both are working like a charm. Now I need to create dynamic form with dependent dropdown inside one livewire components and cannot get working
Below are from livewire blade
#foreach ($employeeQualifications as $qualiIndex => $empQuali)
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="w-full relative">
<select wire:model.lazy="employeeQualifications.{{ $qualiIndex }}.qualification_id" class="input w-full border-gray-300 text-base text-gray-600 focus:text-green-600 focus:border-green-600 focus:outline-none focus:ring-green-600">
<option>Select Qualification</option>
#foreach ($qualifications as $qualification)
<option value="{{ $qualification->id }}">{{ $qualification->name }}</option>
#endforeach
</select>
<label class="tracking-wide text-gray-500 text-xs font-semibold label" for="qualification">
Qualification*
</label>
</div>
<div class="w-full relative">
<select wire:model.lazy='employeeQualifications.{{ $qualiIndex }}.subject_id' class="input w-full border-gray-300 text-base text-gray-600 focus:text-green-600 focus:border-green-600 focus:outline-none focus:ring-green-600">
<option>Select Subject/Stream</option>
#foreach ($streams as $subject)
<option value="{{ $subject->id }}">{{ $subject->name }}</option>
#endforeach
</select>
<label class="tracking-wide text-gray-500 text-xs font-semibold label" for="subject">
Subject/Stream
</label>
</div>
</div>
#endforeach
<div class="flex w-full mt-2 justify-between">
<button type="button" class="text-green-600 uppercase font-semibold text-sm" wire:click.prevent='addMoreQualification'>Add More</button>
#if (count($employeeQualifications) > 1)
<button type="button" class="text-red-600 uppercase font-semibold text-sm" wire:click.prevent='removeQualification'>Remove</button>
#endif
</div>
And in Livewire components
class EducationDetail extends Component
{
public $qualifications;
public $streams;
public $employeeQualifications = [];
public function addMoreQualification()
{
$this->employeeQualifications[] = ['qualification_id' => null, 'subject_id' => null];
}
public function removeQualification()
{
unset($this->employeeQualifications[array_key_last($this->employeeQualifications)]);
$this->employeeQualifications = array_values($this->employeeQualifications);
}
public function mount()
{
$this->qualifications = Qualification::get();
$this->streams = collect();
$this->employeeQualifications = [
['qualification_id' => null, 'subject_id' => null]
];
}
public function render()
{
return view('livewire.web.auth.education-detail');
}
}
If I do like link2 tutorial like below then it can work
{
public function updatedEmployeeQualifications0QualificationId($qId)
{
if (!is_null($qId)) {
$this->streams = Subject::where('qualification_id', $qId)->get();
}
}
}
but I have to prepare around 10 or more method and it's not a logic for developers, how can I make dynamic function like updatedEmployee{anyno}{anyname}
Sorry for bad English and thanks in advance
Add wire:change="setEmployeeQualifications($event.target.value, {{ $key }})"
#foreach ($employeeQualifications as $qualiIndex => $empQuali)
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="w-full relative">
<select wire:model.lazy="employeeQualifications.{{ $qualiIndex }}.qualification_id"
wire:change="setEmployeeQualifications($event.target.value, {{ $key }})"
class="input w-full border-gray-300 text-base text-gray-600 focus:text-green-600 focus:border-green-600 focus:outline-none focus:ring-green-600">
<option>Select Qualification</option>
#foreach ($qualifications as $qualification)
<option value="{{ $qualification->id }}">{{ $qualification->name }}</option>
#endforeach
</select>
<label class="tracking-wide text-gray-500 text-xs font-semibold label" for="qualification">
Qualification*
</label>
</div>
<div class="w-full relative">
<select wire:model.lazy='employeeQualifications.{{ $qualiIndex }}.subject_id' class="input w-full border-gray-300 text-base text-gray-600 focus:text-green-600 focus:border-green-600 focus:outline-none focus:ring-green-600">
<option>Select Subject/Stream</option>
#foreach ($this->employeeQualifications[$qualiIndex]['streams'] as $subject)
<option value="{{ $subject->id }}">{{ $subject->name }}</option>
#endforeach
</select>
<label class="tracking-wide text-gray-500 text-xs font-semibold label" for="subject">
Subject/Stream
</label>
</div>
</div>
#endforeach
<div class="flex w-full mt-2 justify-between">
<button type="button" class="text-green-600 uppercase font-semibold text-sm" wire:click.prevent='addMoreQualification'>Add More</button>
#if (count($employeeQualifications) > 1)
<button type="button" class="text-red-600 uppercase font-semibold text-sm" wire:click.prevent='removeQualification'>Remove</button>
#endif
</div>
And in Livewire components, I changed the following changes.
class EducationDetail extends Component
{
public $qualifications;
public $streams;
public $employeeQualifications = [];
public function addMoreQualification()
{
$this->employeeQualifications[] = ['qualification_id' => null, 'subject_id' => null, 'streams' => null];
}
public function removeQualification()
{
unset($this->employeeQualifications[array_key_last($this->employeeQualifications)]);
$this->employeeQualifications = array_values($this->employeeQualifications);
}
public function mount()
{
$this->qualifications = Qualification::get();
$this->streams = collect();
$this->employeeQualifications = [
['qualification_id' => null, 'subject_id' => null, 'streams' => null]
];
}
public function render()
{
return view('livewire.web.auth.education-detail');
}
public function setEmployeeQualifications($qId, $key)
{
if (!is_null($qId)) {
$this->employeeQualifications[$key]['streams'] = Subject::where('qualification_id', $qId)->get();
}
}
}

Storing data in multiple pivot tables in Laravel and Livewire

I am working on three tables that have two pivot tables in between. It's a workbook that has a many to many relationship with stations and the same workbook that has a many to many with clients. Right now I have a page where you can save a new workbook and you can select all the stations that should be related to it and also the client that should be associated with that workbook.
I figured I would only need to use the store in workbook since that would be the table that connects them both.
public function store(StoreWorkbookRequest $request)
{
$workbook = Workbook::create($request->only('wrkb_name'));
$workbook->stations()->sync($request->input('stations', []));
$workbook->clients()->sync($request->input('clients', []));
return redirect()->route('admin.workbooks.create')->with('success', 'Successfully Created a New Workbook');
}
I am also using livewire and I have the form for create in a livewire component.
<form action="{{route('admin.workbooks.store')}}" method="POST" enctype="multipart/form-data">
#csrf
<div class="form-group">
<label for="">Workbook Name</label>
<input type="text" class="form-control" name="wrkb_name">
</div>
<table class="table-auto w-full mb-6">
<thead>
<tr>
<th class="px-4 py-2"></th>
#if($showRate)
<th wire:click="sortBy('SFM_rate')" style="cursor: pointer;" class="px-4 py-2">SFM Rate #include('partials.sort-icon',['field'=>'SFM_rate'])</th>
#endif
#if($showLetter)
<th wire:click="sortBy('call_letter')" style="cursor: pointer;" class="px-4 py-2">Call Letter #include('partials.sort-icon',['field'=>'call_letter'])</th>
#endif
</tr>
</thead>
<tbody>
#foreach($stations as $key => $station)
<tr>
<td class="border px-4 py-2">
<input wire:model="selected" value="{{ $station->id }}" type="checkbox">
</td>
#if($showRate)
<td class="border px-4 py-2">{{$station->SFM_rate}}</td>
#endif
#if($showLetter)
<td class="border px-4 py-2">{{$station->call_letter}}</td>
#endif
</tr>
#endforeach
</tbody>
</table>
{!! $stations->links() !!}
#else
<p class="text-center"> No stations were found</p>
#endif
<div class="w-full flex pb-10" >
<div class="w-1/6 relative mx-1">
<select wire:model="clientselected" class="block appearance-none w-full bg-gray-200 border border-gray-200 text-gray-700 py-3 px-4 pr-8 rounded leading-tight focus:outline-none focus:bg-white focus:border-gray-500" id="grid-state">
<option value="" >Select a Client</option>
#foreach($clients as $id => $client)
<option value="{{ $id }}">{{ $client->name }}</option>
#endforeach
</select>
</div>
<div class="w-1/6 relative mx-1 space-x-6">
<button class="block appearance-none w-full bg-black border border-gray-200 text-white py-3 px-4 pr-8 rounded leading-tight focus:outline-none focus:bg-white focus:border-gray-500">Create Workbook</button>
</div>
</div>
</form>
When I submit the form only the workbook is created and the two pivot tables remain unchanged.
I got it to work. I added in my selectors the name="stations[]" and name="clients[]"
<input name="stations[]" wire:model="selected" value="{{ $station->id }}" type="checkbox">
<select name="clients[]" wire:model="clientselected" class="block appearance-none w-full bg-gray-200 border border-gray-200 text-gray-700 py-3 px-4 pr-8 rounded leading-tight focus:outline-none focus:bg-white focus:border-gray-500" id="grid-state">
Now all the data is getting sent.

Table Row in Laravel becomes clickable link

I have a question about how to make a table row in Laravel become a clickable link. I want to when the user inputs a link in the form and click save. Then the title in the table will become clickable so when the user clicks on the title, it will lead them to the page. So like in the Input Form picture, I have a field called "Hyperlink" to get the link and save it in the database. When the user clicks the button "Save", the post will be displayed in the "Post Page". I want the "Title" column in the "Post Page" to become clickable, so when the user clicks on the "Tile" (Test Link), it will lead them to the link which they did input in the "Input Form".
Input Form
Post Page
posts.blade.php
<tbody>
#foreach($posts as $post)
#if( $post->published =='publish')
<tr href="{{$post->hyperlink}}">
<td class="border px-4 py-2">{{ $post->id }}</td>
<td class="border px-4 py-2">{{ $post->title }}</td>
<td class="border px-4 py-2">{{ $post->body }}</td>
<td class="border px-4 py-2">{{ $post->author }}</td>
<td class="border px-4 py-2">{{$post->published}} </td>
<td class="border px-4 py-2">
<button wire:click="edit({{ $post->id }})" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Edit</button>
<button wire:click="delete({{ $post->id }})" class="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">Delete</button>
</td>
</tr>
#endif
#endforeach
</tbody>
create.blade.php
<form>
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="">
<div class="mb-4">
<label for="exampleFormControlInput1" class="block text-gray-700 text-sm font-bold mb-2">Title:</label>
<input type="text" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="exampleFormControlInput1" placeholder="Enter Title" wire:model="title">
#error('title') <span class="text-red-500">{{ $message }}</span>#enderror
</div>
<div class="mb-4">
<label for="exampleFormControlInput2" class="block text-gray-700 text-sm font-bold mb-2">Body:</label>
<textarea class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="exampleFormControlInput2" wire:model="body" placeholder="Enter Body"></textarea>
#error('body') <span class="text-red-500">{{ $message }}</span>#enderror
</div>
<div class="mb-4">
<label for="exampleFormControlInput2" class="block text-gray-700 text-sm font-bold mb-2">Author:</label>
<textarea class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="exampleFormControlInput2" wire:model="author" placeholder="Enter Author"></textarea>
#error('author') <span class="text-red-500">{{ $message }}</span>#enderror
</div>
<div class="mb-4">
<label for="exampleFormControlInput2" class="block text-gray-700 text-sm font-bold mb-2">Hyperlink:</label>
<textarea class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="exampleFormControlInput2" wire:model="hyperlink" placeholder="Enter link here"></textarea>
#error('hyperlink') <span class="text-red-500">{{ $message }}</span>#enderror
</div>
<div class="mb-4">
<label for="check" class="form-check-label">Publish:</label>
<input class="form-check-input" id="publish" value="publish" type="checkbox" name="published" wire:model="published">Publish</input>
<input class="form-check-input" id="no-publish" value="no-publish" type="checkbox" name="published" wire:model="published">No Publish</input>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<span class="flex w-full rounded-md shadow-sm sm:ml-3 sm:w-auto">
<button wire:click.prevent="store()" type="button" class="inline-flex justify-center w-full rounded-md border border-transparent px-4 py-2 bg-green-600 text-base leading-6 font-medium text-white shadow-sm hover:bg-green-500 focus:outline-none focus:border-green-700 focus:shadow-outline-green transition ease-in-out duration-150 sm:text-sm sm:leading-5">
Save
</button>
</span>
<span class="mt-3 flex w-full rounded-md shadow-sm sm:mt-0 sm:w-auto">
<button wire:click="closeModal()" type="button" class="inline-flex justify-center w-full rounded-md border border-gray-300 px-4 py-2 bg-white text-base leading-6 font-medium text-gray-700 shadow-sm hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue transition ease-in-out duration-150 sm:text-sm sm:leading-5">
Cancel
</button>
</span>
</form>
Post Schema
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title');
$table->string('body');
$table->string('author');
$table->boolean('published')->default(0);
$table->string('hyperlink');
//create the relationship between a task and the user that created it
$table->integer('user_id')->unsigned()->index();
$table->timestamps();
});
}
app/Http/Livewire/Posts.php
use Livewire\Component;
use App\Models\Post;
use App\Models\User;
class Posts extends Component
{
public $posts, $title, $body, $post_id, $author, $published, $hyperlink;
public $isOpen = 0;
/**
* The attributes that are mass assignable.
*
* #var array
*/
public function render()
{
$user = auth()->user();
$this->posts = $user->posts;
return view('livewire.posts');
}
/**
* The attributes that are mass assignable.
*
* #var array
*/
public function create()
{
$this->resetInputFields();
$this->openModal();
}
/**
* The attributes that are mass assignable.
*
* #var array
*/
public function openModal()
{
$this->isOpen = true;
}
/**
* The attributes that are mass assignable.
*
* #var array
*/
public function closeModal()
{
$this->isOpen = false;
}
/**
* The attributes that are mass assignable.
*
* #var array
*/
private function resetInputFields(){
$this->title = '';
$this->body = '';
$this->post_id = '';
$this->author = '';
$this->published = '';
$this->hyperlink = '';
}
/**
* The attributes that are mass assignable.
*
* #var array
*/
public function store()
{
$this->validate([
'title' => 'required',
'body' => 'required',
'author' => 'required',
'published' => 'required',
'hyperlink' => 'required'
]);
Post::updateOrCreate(['id' => $this->post_id], [
'title' => $this->title,
'body' => $this->body,
'author' => $this->author,
'published' => $this->published,
'hyperlink' => $this->hyperlink
]);
Page::updateOrCreate(['id' => $this->post_id], [
'title' => $this->title,
'body' => $this->body,
'publish' => $this->published
]);
session()->flash('message',
$this->post_id ? 'Post Updated Successfully.' : 'Post Created Successfully.');
$this->closeModal();
$this->resetInputFields();
}
/**
* The attributes that are mass assignable.
*
* #var array
*/
public function edit($id)
{
$post = Post::findOrFail($id);
$this->post_id = $id;
$this->title = $post->title;
$this->body = $post->body;
$this->author = $post->author;
$this->published = $post->published;
$this->hyperlink = $post->hyperlink;
$this->openModal();
}
/**
* The attributes that are mass assignable.
*
* #var array
*/
public function delete($id)
{
Post::find($id)->delete();
session()->flash('message', 'Post Deleted Successfully.');
}
}
Post Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;
class Post extends Model
{
use HasFactory;
protected $fillable = [
'title', 'body', 'author', 'published', 'hyperlink'
];
public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(User::class);
}
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
$model->user_id = Auth::id();
});
static::updating(function ($model) {
$model->user_id = Auth::id();
});
}
}
I solve something similar and expose this to you like one way to do it.
<td class="border px-4 py-2" onclick="window.location='{{ route('show.companies', ['company' => $company]) }}'" style="cursor: pointer;">{{ $post->title }}</td>
As you can see, when the column title is clicked, it's going to resume the function that I implement in the route...in this case act like a link to another component with data binding.

Getting my toggle to show correctly in laravel livewire

I have a pivot table that links my products and categories together. What I'm trying to do is in my edit page for a product I
have a list of all the categories and each category has a toggle button that will enable or disable that category for that product.
The problem I'm having is that all my categories is set to enabled, but I only have one enabled and the rest is supposed to be disabled
I'm using laravel 8 and livewire
Here is my code
namespace App\Http\Livewire\Products;
use App\Models\Product;
use Livewire\Component;
use App\Models\Category;
class Edit extends Component
{
public Product $product;
public bool $enabled;
public $name;
public $description;
public function mount()
{
$pcPivot = $this->product->categories()->where('product_id', $this->product->id)->exists();
if($pcPivot === true)
{
$this->enabled = true;
}else{
$this->enabled = false;
}
$this->name = $this->product->name;
$this->description = $this->product->description;
}
public function render()
{
$categories = Category::all();
return view('livewire.products.edit', [
'categories' => $categories,
]);
}
}
and here is my edit.blade.php
<div>
<div class="md:grid md:grid-cols-3 md:gap-6">
<div class="md:col-span-1">
<div class="px-4 sm:px-0">
<h3 class="text-lg font-medium leading-6 text-gray-900">Edit Product</h3>
</div>
</div>
<div class="mt-5 md:mt-0 md:col-span-2">
<div class="shadow sm:rounded-md sm:overflow-hidden">
<form wire:submit.prevent="submit">
<div class="px-4 py-5 bg-white sm:p-6">
<div class="grid grid-cols-3 gap-6">
<div class="col-span-3 sm:col-span-2">
<label for="title" class="block text-sm font-medium leading-5 text-gray-700">
Name
</label>
<div class="rounded-md shadow-sm">
<input id="name" wire:model="product.name" class="flex-1 form-input block w-full min-w-0 transition duration-150 ease-in-out sm:text-sm sm:leading-5">
</div>
</div>
</div>
</div>
<div class="px-4 py-5 bg-white sm:p-6">
<div class="grid grid-cols-3 gap-6">
<div class="col-span-3 sm:col-span-2">
<label for="description" class="block text-sm font-medium leading-5 text-gray-700">
Description
</label>
<div class="rounded-md shadow-sm">
<textarea id="description" wire:model="product.description" rows="3" class="form-textarea mt-1 block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5"></textarea>
</div>
</div>
</div>
</div>
<div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
<span class="inline-flex rounded-md shadow-sm">
<button type="submit" class="inline-flex justify-center py-2 px-4 border border-transparent text-sm leading-5 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:shadow-outline-indigo active:bg-indigo-700 transition duration-150 ease-in-out">
Update
</button>
</span>
</div>
</form>
</div>
</div>
</div>
#include('spacer')
<div class="md:grid md:grid-cols-3 md:gap-6">
<div class="md:col-span-1">
<div class="px-4 sm:px-0">
<h3 class="text-lg font-medium leading-6 text-gray-900">Categories</h3>
</div>
</div>
<div class="mt-5 md:mt-0 md:col-span-2">
<div class="shadow sm:rounded-md sm:overflow-hidden">
<table class="min-w-full divide-y divide-gray-200">
<thead>
<tr>
<x-th>Title</x-th>
<x-th>Enable/Disable</x-th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
#foreach($categories as $category)
<tr>
<td class="px-6 py-4 whitespace-no-wrap">
<div class="flex items-center">
<div class="text-sm font-medium text-gray-900">
{{ $category->title }}
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-no-wrap">
<div class="mt-1 flex rounded-md">
<span role="checkbox" tabindex="0" aria-checked="false" class="#if($enabled) bg-indigo-600 #else bg-gray-200 #endif relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:shadow-outline">
<span aria-hidden="true" class="#if($enabled) translate-x-5 #else translate-x-0 #endif inline-block h-5 w-5 rounded-full bg-white shadow transform transition ease-in-out duration-200">
<input id="enabled" type="checkbox" wire:model="enabled" class="invisible">
</span>
</span>
</div>
</td>
</tr>
#endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
If you check the documentation for Livewire, at lifecycle hooks... you will see that:
mount : Runs once, immediately after the component is instantiated, but before render() is called
So basically you are getting an "enabled" value once, before rendering the component,then you start rendering it, with that foreach, using the same "enabled" from mount for each item of your dataset.
Consider building your cursor with the enabled value inside for each record.

Resources