I'm using laravel livewire and I've created a page that you can select a date for when you want the post
to publish. When I create a new post and save the date then it saves fine in the database, but if I try
to edit the post and change the date the date that I saved in the database isn't showing in the form.
Here is my code.
My EditPost.php
<?php
namespace App\Http\Livewire;
use App\Models\Post;
use Livewire\Component;
class EditPost extends Component
{
public $name;
public $publishDate;
public Post $post;
public function mount(Post $post)
{
$this->name = $post->name;
$this->publishDate = $post->publish_date;
}
public function render()
{
return view('livewire.edit-post');
}
}
and this is my edit.blade.php
<div>
<div class="mt-10 sm:mt-0">
<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 Post</h3>
</div>
</div>
<div class="mt-5 md:mt-0 md:col-span-2">
<div class="form">
<div class="shadow overflow-hidden sm:rounded-md">
<div class="px-4 py-5 bg-white sm:p-6">
<div class="grid grid-cols-6 gap-6">
<div class="col-span-6 sm:col-span-3">
<label for="name" class="block text-sm font-medium leading-5 text-gray-700">Name</label>
<input id="name" wire:model="name" class="#error('name') border border-red-500 #enderror mt-1 form-input block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5">
#error('name')
<small>
<div class="text-red-500">{{ $message }}</div>
</small>
#enderror
</div>
<div class="col-span-6 sm:col-span-4">
<label for="publish_date" class="block text-sm font-medium leading-5 text-gray-700">Publish Date</label>
<input id="publish_date" wire:model="publishDate" type="date" class="mt-1 form-input block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5">
</div>
</div>
</div>
<div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
<button wire:click="editPost" class="py-2 px-4 border border-transparent text-sm leading-5 font-medium rounded-md text-white bg-indigo-600 shadow-sm hover:bg-indigo-500 focus:outline-none focus:shadow-outline-blue active:bg-indigo-600 transition duration-150 ease-in-out">
Save
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Related
I made chat app using livewire, and i want to emit an event where in that event emitting antohter event to another component, but when i emit the event the component it self vanish from view, and i dont know why here is my code
<div class="flex flex-row py-2 px-2 items-center border-b-2 cursor-pointer hover:bg-gray-100" wire:click="$emit('chatUserSelected',{{$conversation}})">
and the event in chatlist component
protected $listeners = ['chatUserSelected'];
public $conversations;
public $selectedConversation;
public function chatUserSelected(Conversation $conversation)
{
$this->selectedConversation = $conversation;
$receiverInstance = KontakModel::find($conversation->kontak_id);
$this->emitTo('chat.chat-box','loadConversation',$this->selectedConversation,$receiverInstance);
$this->emitTo('chat.send-message','updateSendMessage',$this->selectedConversation,$receiverInstance);
}
public function mount()
{
$this->auth_id = auth()->id();
$this->conversations = Conversation::orderBy('last_time_message','DESC')->where('solved_at',NULL)->get();
// dd($this->conversations);
}
public function render()
{
return view('livewire.chat.chat-list', );
}
here is my view before emitting event
and after emitting event
the chatlist somehow disappear
for additional this is code for my main view
<div class="flex flex-row justify-between bg-white h-screen" x-data="chatApp">
#livewire('chat.chat-list')
#livewire('admin.side-bar')
<!-- message -->
#livewire('chat.chat-box')
<!-- end message -->
</div>
chat.chat-list.blade.php
<div class="overflow-y-auto">
#forelse ($conversations as $conversation)
<div class="flex flex-row py-2 px-2 items-center border-b-2 cursor-pointer hover:bg-gray-100" wire:key="{{$conversation->id}}" wire:click="$emit('chatUserSelected',{{$conversation}})">
<div class="w-1/4">
<img
src="https://source.unsplash.com/otT2199XwI8/600x600"
class="object-cover h-12 w-12 rounded-full"
alt=""
/>
</div>
<div class="w-full">
<div class="text-lg font-semibold">{{ $conversation->kontak->name }}</div>
<span class="text-gray-500">{{$conversation->messages->sortBy('created_at')->last()->body}}</span>
</div>
<div class="w-2/12">
#php
$unread = $conversation->messages->where('status', NULL)->where('category','receive')->count()
#endphp
#if ($unread > 0)
<div class="text-sm text-center font-light rounded-full bg-red-600 text-white min-w-5 h-5">{{$unread}}</div>
#endif
<span class="text-xs">{{$conversation->messages->sortBy('created_at')->last()->created_at->shortAbsoluteDiffForHumans()}}</span>
</div>
</div>
#empty
<div class="flex flex-row py-2 px-2 items-center border-b-2 text-2xl text-center">
<div class="text-center m-auto">
No Conversation
</div>
</div>
#endforelse
</div>
I have different inputs depends on radio buttons. How to validate them according to selection?
<div class="sm:col-span-2">
<div class="mt-4">
<nav class=" " aria-label="Tabs">
<div class="border-gray-300 border-2 rounded-lg pl-3 py-2 w-40" :class="tab == 'tab1' ? ' bg-green-200 border-green-500 ' : ''">
<input type="radio" #click="tab = 'tab1'" checked="tab == 'tab1' ? true: false" name="person_company"> <span class="text-gray-600 font-medium text-sm pl-2">person</span> </input>
</div>
<br>
<div class="border-gray-300 border-2 rounded-lg pl-3 py-2 w-40" :class="tab == 'tab2' ? ' bg-green-200 border-green-500 ' : ' '">
<input type="radio" #click="tab = 'tab2'" name="person_company"> <span class="text-gray-600 font-medium text-sm pl-2">company</span> </input>
</div>
</nav>
</div>
</div>
<div class="sm:col-span-2 " x-show="tab == 'tab1'">
<label for="identity_no" class="block text-sm font-medium text-gray-700">Identity</label>
<div class="mt-1">
<input type="text" name="identity_no" id="identity_no" class="block w-full py-4 border-gray-300 rounded-md shadow-sm focus:ring-green-500 focus:border-green-500 sm:text-sm">
</div>
</div>
<div class="sm:col-span-2" x-show="tab == 'tab2'">
<label for="company" class="block text-sm font-medium text-gray-700">Company name</label>
<div class="mt-1">
<input type="text" name="company" id="company" class="block w-full py-4 border-gray-300 rounded-md shadow-sm focus:ring-green-500 focus:border-green-500 sm:text-sm">
</div>
</div>
this code needs both of them that's not what I want
$this->validate($request,[
'identity' => 'required',
'company' => 'required',
]);
You should use jquery to manage it. First of all, you will have to take values to radio inputs. And then apply the required property through jquery condition.
<input type="radio" #click="tab = 'tab1'" checked="tab == 'tab1' ? true: false" name="person_company" value = "tab1"> <span class="text-gray-600 font-medium text-sm pl-2">person</span> </input>
<input type="radio" #click="tab = 'tab2'" name="person_company"> <span class="text-gray-600 font-medium text-sm pl-2" value = "tab2">company</span> </input>
$('input[type=radio][name= person_company]').change(function() {
if (this.value == 'tab1') {
$("#identity_no").prop('required',true);
$("#company").prop('required',false);
}
else if (this.value == 'tab2') {
$("#company").prop('required',true);
$("#identity_no").prop('required',false);
}
});
I want to validate the form with AJAX, because when the normal validation fails, the uploaded files are gone.
I get a JSON response but at the working URL: /properties, instead of the form properties/create.
This is an example of the response:
{"error":{"title":["The title must be at least 10 max:50 characters."],"asking_price":["The asking price must be at least 10000."],"description":["The description must be at least 100 characters."],"feat_image_path":["The feat image path has invalid image dimensions."]}}
I tried a lot of things, but none is working.
Am I doing something wrong logically, or is it the URL of the AJAX script??
Thanks in advance, Sander
This is the blade file with the AJAX script.
#section('tinymce')
<script src="https://cdn.tiny.cloud/1/izqu9favecmjvbbfp1dhe96fphutb1stn4aqs7363k6j8trm/tinymce/5/tinymce.min.js" referrerpolicy="origin"></script>
<script>
tinymce.init({
selector: '#description'
});
</script>
#stop
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Properties') }}
</h2>
</x-slot>
<div class="py-12">
<div class=" mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<h1 class="text-2xl px-12 font-bold w-full my-4">Add Property<span class="text-sm ml-2 text-red-500 italic">* is required</span></h1>
<div class="container my-4 xl:text-lg text-center">
<div class="w-full mx-auto">
#if ($errors->any())
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
<div class="alert alert-danger print-error-msg" style="display:none">
<ul></ul>
</div>
{{-- Add Porperty Form --}}
<form action="../properties" method="post" enctype="multipart/form-data" id="create_property_form" class="bg-white shadow-md rounded mb-4 xl:mb-8 w-full">
#csrf
<h2 class="text-center text-xl font-bold w-full my-4">General Information</h2>
{{-- Title --}}
<div class="form-wrapper w-full flex flex-wrap px-8">
<div class="mb-4 xl:mb-8 w-full xl:w-1/2 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="title">
Property Title*
</label>
<input class="block shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="title" type="text" placeholder="Title of the property" name="title" value="{{ old('title') }}" required>
<span class="error title-error"></span>
</div>
{{-- Asking Price --}}
<div class="mb-4 xl:mb-8 w-full xl:w-1/2 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="asking_price">
Asking Price*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="asking_price" name="asking_price" type="number" placeholder="Price in $ USD" value="{{ old('asking_price') }}" required>
<span class="error asking_price-error"></span>
</div>
<h2 class="text-center text-xl font-bold w-full my-4">Adress</h2>
{{-- Street --}}
<div class="mb-4 xl:mb-8 w-full xl:w-2/3 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="street">
Street*
</label>
<input class="block shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="street" name="street" type="text" placeholder="Name of the street" value="{{ old('street') }}" required>
<span class="error street-error"></span>
</div>
{{-- Number --}}
<div class="mb-4 xl:mb-8 w-full xl:w-1/3 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="number">
Number*
</label>
<input class="block shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="number" name="number" type="text" placeholder="Appt/house number" value="{{ old('number') }}" required>
<span class="error number-error"></span>
</div>
{{-- Zip Code --}}
<div class="mb-4 xl:mb-8 w-full xl:w-1/3 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="zip_code">
Zip Code
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="zip_code" name="zip_code" type="text" placeholder="Zip / Postal code" value="{{ old('zip_code') }}">
<span class="error zip_code-error"></span>
</div>
{{-- City --}}
<div class="mb-4 xl:mb-8 w-full xl:w-1/3 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="city">
City*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="city" name="city" type="text" placeholder="eg. 'New Tork'" value="{{ old('city') }}" required>
<span class="error city-error"></span>
</div>
{{-- Location --}}
<div class="mb-4 xl:mb-8 w-full xl:w-1/3 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="location">
Location*
</label>
<select name="location_id" id="location_id" class="w-full">
#foreach ($locations as $location)
<option value="{{ $location->id }}">{{ $location-> name}}</option>
#endforeach
</select>
</div>
{{-- Coördinates --}}
<h2 class="text-center text-xl font-bold w-full my-4">Position<span class="text-sm ml-2 text-gray-500">Get coördinates with Google Maps or Latlong </span></h2>
{{-- Latitude --}}
<div class="mb-4 xl:mb-8 w-full xl:w-1/2 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="latitude">
Latitude*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="latitude" name="latitude" min="11.979144" max="18.145982" step="0.000001" type="number" placeholder="eg. 12.123456" value="{{ old('latitude') }}" required>
<span class="error latitude-error"></span>
</div>
{{-- Longitude --}}
<div class="mb-4 xl:mb-8 w-full xl:w-1/2 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="longitude">
Longitude*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="longitude" name="longitude" min="-68.440281" max="-62.966999" step="0.000001" type="number" placeholder="eg. -64.123456" value="{{ old('longitude') }}" required>
<span class="error longitude-error"></span>
</div>
{{-- Details --}}
<h2 class="text-center text-xl font-bold w-full my-4">Property Details</h2>
{{-- Built Year --}}
<div class="mb-4 xl:mb-8 w-full xl:w-4/12 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="built_in">
Built in Year*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="built_in" name="built_in" min="1900" step="1" type="number" placeholder="YYYY" value="{{ old('built_in') }}" required>
<span class="error built_in-error"></span>
</div>
{{-- Indoor Area --}}
<div class="mb-4 xl:mb-8 w-full xl:w-4/12 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="area_size_indoor">
Indoor Area Size*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="area_size_indoor" name="area_size_indoor" type="number" placeholder="Size in sqm (m2)" step="1" value="{{ old('area_size_indoor') }}" required>
<small>1 sqft = 0.09290304 sqm</small>
<span class="error area_size_indoor-error"></span>
</div>
{{-- Outdoor Area --}}
<div class="mb-4 xl:mb-8 w-full xl:w-4/12 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="area_size_outdoor">
Outdoor Area Size*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="area_size_outdoor" name="area_size_outdoor" type="number" placeholder="Size in sqm (m2)" step="1" value="{{ old('area_size_outdoor') }}" required>
<small>1 sqft = 0.09290304 sqm</small>
<span class="error area_size_outdoor-error"></span>
</div>
{{-- Bedrooms --}}
<div class="mb-4 xl:mb-8 w-full xl:w-4/12 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="bedrooms">
Bedrooms*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="bedrooms" name="bedrooms" type="number" step="1" value="{{ old('bedrooms') }}" required>
<span class="error bedrooms-error"></span>
</div>
{{-- Bathrooms --}}
<div class="mb-4 xl:mb-8 w-full xl:w-4/12 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="bathrooms">
Bathrooms*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="bathrooms" name="bathrooms" type="number" step="1" value="{{ old('bathrooms') }}" required>
<span class="error bathrooms-error"></span>
</div>
{{-- Property Type --}}
<div class="mb-4 xl:mb-8 w-full xl:w-4/12 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="property_type">
Property Type*
</label>
<select name="property_type" id="property_type" class="w-full">
<option value="Villa">Villa</option>
<option value="Chalet">Chalet</option>
<option value="Appartment">Appartment</option>
<option value="Condo">Condo</option>
<option value="Lot">Lot</option>
<option value="Penthouse">Penthouse</option>
</select>
</div>
{{-- Desciption --}}
<div class="mb-4 xl:mb-8 w-full">
<label class="block text-gray-500 text-base font-bold mb-2" for="description">
Description*
</label>
<textarea class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="description" name="description">
{{ old('description') }}
</textarea>
<span class="error description-error"></span>
</div>
{{-- Featured Image --}}
<div class="mb-4 xl:mb-8 w-full xl:w-1/2 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="feat_image_path">
Featured Image*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="feat_image_path" name="feat_image_path" type="file" value="{{ old('feat_image_path') }}" required>
<span class="error feat_image_path-error"></span>
</div>
{{-- Gallery Images --}}
<div class="mb-4 xl:mb-8 w-full xl:w-1/2 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="bathrooms">
Gallery Images
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" type="file" name="file[]" id="file" required="" multiple>
<span class="error file-error"></span>
</div>
{{-- Submit --}}
<div class=" mb-4 xl:mb-8 mx-auto w-48">
<input class="py-2 bg-green-300 hover:bg-green-200 text-white w-full font-bold rounded shadow" data-resource="" value="Submit Property" type="submit">
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
The AJAX script:
$(document).ready(function() {
$("#create_property_form").click(function(e) {
e.preventDefault();
let _token = $("input[name='_token']").val();
let title = $("input[name='asking_price']").val();
let latitude = $("input[name='latitude']").val();
let longitude = $("input[name='longitude']").val();
let description = $("textarea[name='description']").val();
let feat_image_path = $("textarea[name='feat_image_path']").val();
$.ajax({
url: "{{ url('/properties/create') }}"
, type: 'POST'
, data: {
_token: _token
, title: title
, latitude: latitude
, longitude: longitude
, description: description
, feat_image_path: feat_image_path
}
success: function(data) {
console.log(data.error)
if ($.isEmptyObject(data.error)) {
alert(data.success);
} else {
printErrorMsg(data.error);
}
}
});
});
function printErrorMsg(msg) {
$.each(msg, function(key, value) {
console.log(key);
$('.' + key + '_err').text(value);
});
}
});
I have one route for the resource controller:
Route::resource('properties', 'App\Http\Controllers\User\PropertyController');
My goal is to only show errors, when no error I add everything in the DB.
Here is the store method:
public function store(Request $request)
{
// Validate input
$validator = Validator::make($request->all(),[
'title' => 'required|unique:properties|min:10 max:50',
'asking_price' => 'required|numeric|min:10000|max:1000000000',
'street' => 'required|min:3',
'number' => 'required',
'city' => 'required|min:3',
'latitude' => 'required|between:9,12',
'longitude' => 'required|between:9,12',
'built_in' => 'required|numeric',
'area_size_indoor' => 'required|numeric',
'area_size_outdoor' => 'required|numeric',
'bedrooms' => 'required|numeric',
'bathrooms' => 'required|numeric',
'description' => 'required|min:100',
'feat_image_path' => 'required|image|dimensions:min_width=1500,min_height=800|max:2500',
]);
if ($validator->passes()) {
return response()->json(['success'=>'Added new records.']);
}
return response()->json(['error'=>$validator->errors()]);
// Generate random number for filename
$random = rand(1111,9999) * rand(1, 9);
// Validate Featured Image
if($request->hasFile('feat_image_path'))
{
// Make a full size imaye
ImageIvn::make($request->feat_image_path)->resize(1500,800)->save(public_path('img/' . $random . '_feat.jpg'))
->resize(400,300)->save(public_path('img/' . $random . '_feat_thumb.jpg'));
}
// Store Property
$property = new Property([
'title' => $request->title,
'slug' => Str::slug($request->title),
'user_id' => Auth::id(),
'street' => $request->street,
'number' => $request->number,
'zip_code' => $request->zip_code,
'city' => $request->city,
'asking_price' => $request->asking_price,
'status' => 'For Sale',
'location_id' => $request->location_id,
'property_type' => $request->property_type,
'latitude' => $request->latitude,
'longitude' => $request->longitude,
'built_in' => $request->built_in,
'area_size_indoor' => $request->area_size_indoor,
'area_size_outdoor' => $request->area_size_outdoor,
'bedrooms' => $request->bedrooms,
'bathrooms' => $request->bathrooms,
'description' => $request->description,
'feat_image_path' => 'img/' . $random . '_feat.jpg',
]);
$property->save();
/**
* Uploaded gallery images are stored with the use of the property ID as FK
*/
// Validate Gallery Images
if($request->hasFile('file'))
{
$request->validate([
'file.*' => 'image'
]);
$files = $request->file('file');
// Generate images
foreach($files as $file) {
// Generate random number for filename
$rand = $property->id . '-' . rand(99,999) * rand(99,999);
// Create Full size image
ImageIvn::make($file)->resize(1200,900)->save(public_path('img/' . $rand . '_full.jpg'));
// Save in DB
$image = new Image([
'property_id' => $property->id,
'image_path' => 'img/' . $rand . '_full.jpg',
'size' => 'full',
]);
$image->save();
// Create thumbnail size image
ImageIvn::make($file)->resize(1200,900)->save(public_path('img/' . $rand . '_thumb.jpg'));
// Store in DB
$image = new Image([
'property_id' => $property->id,
'image_path' => 'img/' . $rand . '_thumb.jpg',
'size' => 'thumb',
]);
$image->save();
}
}
return $this->index()->with(["message" => "Property " . $property->name . " is added"]);
}
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.
I have a single file for creating and updating the category data.
while creating category, i am using v-model in title to also create slug in the same form.
works well when creating but i am facing issue with update / edit form part.
below is my code :
<input class="form-input mt-1 block w-full" name="name" v-model="title" v-on:keyup="getSlug" placeholder="Category Title" value="{{ $category->name ?? '' }}">
adding whole blade file code for reference:
#extends('layouts.backend.app')
#php
if(isset($record) && $record != null){
$edit = 1;
} else {
$edit = 0;
}
#endphp
#section('content')
<section id="app" class="container mx-auto">
<div class="flex items-center justify-between">
<h1 class="text-2xl font-bold">
#if($edit) Edit #else Create #endif Category Form
</h1>
Back
</div>
<div class="border rounded mt-8 p-8">
<form action="#if($edit) {{route('category.update', $record->id)}} #else {{route('category.store')}} #endif" method="POST">
#csrf
<label class="block mb-4">
<span class="text-gray-700 font-bold">Name</span>
<input class="form-input mt-1 block w-full" name="name" v-model="title" v-on:keyup="getSlug" placeholder="Category Title" value="{{ $category->name ?? '' }}">
#error('name')
<span class=" text-red-400 invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
#enderror
</label>
<label class="block mb-4">
<span class="text-gray-700 font-bold">Slug</span>
<input
class="form-input mt-1 block w-full"
name="slug"
id="slug"
v-model="slug"
placeholder="Slug / Pretty URL">
#error('slug')
<span class=" text-red-400 invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
#enderror
</label>
<label class="block mb-8">
<span class="text-gray-700 font-bold">Banner</span>
<input
class="form-input mt-1 block w-full"
name="banner"
value="#if($edit) {{$record->banner}} #else https://source.unsplash.com/random #endif"
placeholder="Banner / URL">
</label>
<div class="flex justify-between">
<button class="px-4 py-2 border bg-gray-200 text-gray-900 rounded" type="submit">Submit</button>
<button class="px-4 py-2 border bg-red-400 text-white rounded" type="rest">Reset</button>
</div>
</form>
</div>
</section>
#endsection
as you can see the title input is use to create the slug on keyup event. now the given code don't use the data from database for pre populating the edit form title input field. because i am using v-model="title" which is in my app.js and is null at the moment.
How to either assign v-model="title" my current value from database.
This is not a vue component. its a laravel blade file. Kindly guide me for this.
Thanks
You can move the app.js code to the Blade view and populate title with the Blade expression
#extends('layouts.backend.app')
#php
if(isset($record) && $record != null){
$edit = 1;
} else {
$edit = 0;
}
#endphp
#section('content')
<section id="app" class="container mx-auto">
<div class="flex items-center justify-between">
<h1 class="text-2xl font-bold">
#if($edit) Edit #else Create #endif Category Form
</h1>
Back
</div>
<div class="border rounded mt-8 p-8">
<form action="#if($edit) {{route('category.update', $record->id)}} #else {{route('category.store')}} #endif"
method="POST">
#csrf
<label class="block mb-4">
<span class="text-gray-700 font-bold">Name</span>
<input class="form-input mt-1 block w-full" name="name" v-model="title" v-on:keyup="getSlug"
placeholder="Category Title" value="{{ $category->name ?? '' }}">
#error('name')
<span class=" text-red-400 invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
#enderror
</label>
<label class="block mb-4">
<span class="text-gray-700 font-bold">Slug</span>
<input class="form-input mt-1 block w-full" name="slug" id="slug" v-model="slug"
placeholder="Slug / Pretty URL">
#error('slug')
<span class=" text-red-400 invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
#enderror
</label>
<label class="block mb-8">
<span class="text-gray-700 font-bold">Banner</span>
<input class="form-input mt-1 block w-full" name="banner"
value="#if($edit) {{$record->banner}} #else https://source.unsplash.com/random #endif"
placeholder="Banner / URL">
</label>
<div class="flex justify-between">
<button class="px-4 py-2 border bg-gray-200 text-gray-900 rounded" type="submit">Submit</button>
<button class="px-4 py-2 border bg-red-400 text-white rounded" type="rest">Reset</button>
</div>
</form>
</div>
</section>
{{-- Place the script here, after closing the section with id of app --}}
<script>
const app = new Vue({
el: '#app',
data() {
return {
title: '{{ $category->name }}'
}
},
methods: {
getSlug() {
this.title = this.title.toLowerCase()
.replace(/ /g,'-')
.replace(/[^\w-]+/g,'');
}
}
});
</script>
#endsection
Hope this helps
In The End, I went back to the old style of doing things.
code as below:
getSlug() {
var title = document.getElementById('title').value;
document.getElementById('slug').value = title.replace(/\s+/g, '-').toLowerCase().trim();
},
and replaced v-model with id tag on the input field.