with Livewire, I only use one component for both create and edit. This is preferable to duplication of everything.
Start with editing an existing record, then work out what needs to be different to handle a new record.
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
Hello everyone, I am using Laravel 12 and livewire 3. I have an question. I use Livewire to create both creation and update components in my projects. My biggest concern is whether there's a need for two separate components. Would a single component be enough? Below are my supplier add and update components. Create livewire:
<?php
namespace App\Livewire\Admin\Supplier;
use App\Models\Suppliers;
use Livewire\Component;
class Create extends Component
{
public $name, $bill_name, $tax_id, $tax_office, $phone, $email, $city, $district, $address, $notes;
public $country = "Türkiye", $country_code = "90", $country_iso_code = "TR/TUR";
public function rules()
{
return [
'name' => 'required|string|max:255',
'bill_name' => 'required|string|max:255',
'tax_id' => 'required|string|min:11|max:11|unique:suppliers,tax_id',
'tax_office' => 'required|string|max:100',
'phone' => 'required|string|max:20|unique:suppliers,phone',
'email' => 'required|email|max:255|unique:suppliers,email',
'country' => 'required|string|max:255',
'country_code' => 'required|string|max:10',
'country_iso_code' => 'required|string|max:10',
'city' => 'required|string|max:255',
'district' => 'required|string|max:255',
'address' => 'required|string|max:255',
'notes' => 'nullable|string',
];
}
public function messages()
{
return [
'name.required' => 'Tedarikçi adı gereklidir.',
'name.string' => 'Tedarikçi adı geçersiz.',
'name.max' => 'Tedarikçi adı en fazla 255 karakter olmalıdır.',
'bill_name.required' => 'Fatura adı gereklidir.',
'bill_name.string' => 'Fatura adı geçersiz.',
'bill_name.max' => 'Fatura adı en fazla 255 karakter olmalıdır.',
'tax_id.required' => 'Vergi kimlik numarası gereklidir.',
'tax_id.string' => 'Vergi kimlik numarası geçersiz.',
'tax_id.min' => 'Vergi kimlik numarası en az 11 karakter olmalıdır.',
'tax_id.max' => 'Vergi kimlik numarası en fazla 11 karakter olmalıdır.',
'tax_office.required' => 'Vergi dairesi gereklidir.',
'tax_office.string' => 'Vergi dairesi geçersiz.',
'tax_office.max' => 'Vergi dairesi en fazla 100 karakter olmalıdır.',
'phone.required' => 'Telefon numarası gereklidir.',
'phone.string' => 'Telefon numarası geçersiz.',
'phone.max' => 'Telefon numarası en fazla 20 karakter olmalıdır.',
'email.required' => 'E-posta adresi gereklidir.',
'email.email' => 'E-posta adresi geçersiz.',
'email.max' => 'E-posta adresi en fazla 255 karakter olmalıdır.',
'country.required' => 'Ülke gereklidir.',
'country.string' => 'Ülke geçersiz.',
'country.max' => 'Ülke en fazla 255 karakter olmalıdır.',
'country_code.required' => 'Ülke kodu gereklidir.',
'country_code.string' => 'Ülke kodu geçersiz.',
'country_code.max' => 'Ülke kodu en fazla 10 karakter olmalıdır.',
'country_iso_code.required' => 'Ülke ISO kodu gereklidir.',
'country_iso_code.string' => 'Ülke ISO kodu geçersiz.',
'country_iso_code.max' => 'Ülke ISO kodu en fazla 10 karakter olmalıdır.',
'city.required' => 'Şehir gereklidir.',
'city.string' => 'Şehir geçersiz.',
'city.max' => 'Şehir en fazla 255 karakter olmalıdır.',
'district.required' => 'İlçe gereklidir.',
'district.string' => 'İlçe geçersiz.',
'district.max' => 'İlçe en fazla 255 karakter olmalıdır.',
'address.required' => 'Adres gereklidir.',
'address.string' => 'Adres geçersiz.',
'address.max' => 'Adres en fazla 255 karakter olmalıdır.',
];
}
public function placeholder()
{
return view('components.admin.loader');
}
public function render()
{
return view('livewire.admin.supplier.create');
}
public function create()
{
$this->validate();
$phone = preg_replace('/[^0-9]/', '', $this->phone);
$saveStatus = Suppliers::create([
'name' => $this->name,
'bill_name' => $this->bill_name,
'tax_id' => $this->tax_id,
'tax_office' => $this->tax_office,
'phone' => $phone,
'email' => $this->email,
'country' => $this->country,
'country_code' => $this->country_code,
'country_iso_code' => $this->country_iso_code,
'city' => $this->city,
'district' => $this->district,
'address' => $this->address,
'is_active' => 1,
'notes' => $this->notes,
]);
if (!$saveStatus) {
$this->dispatch('message', [
'type' => 'warning',
'title' => 'Hata',
'message' => 'Tedarikçi kaydedilemedi.'
]);
return;
}
$this->dispatch('message', [
'type' => 'success',
'title' => 'Başarılı',
'message' => 'Tedarikçi başarıyla kaydedildi.'
]);
return redirect()->route('admin.suppliers.edit', $saveStatus->id);
}
}
create component blade:
<div class="col-12 card">
{{-- Because she competes with no one, no one can compete with her. --}}
<div class="card-body">
<form wire:submit.prevent="create">
<div class="form-row">
<div class="form-group col-md-6">
<label for="name" class="@error('name') text-danger @enderror">Tedarikçi Adı<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('name') border-danger @enderror" id="name"
wire:model="name" placeholder="Tedarikçi Adı">
<div class="text-danger">
@error('name')
{{ $message }}
@enderror
</div>
</div>
<div class="form-group col-md-6">
<label for="bill_name" class="@error('bill_name') text-danger @enderror">Fatura Adı<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('bill_name') border-danger @enderror" id="bill_name"
wire:model="bill_name" placeholder="Fatura Adı">
<div class="text-danger">
@error('bill_name')
{{ $message }}
@enderror
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="phone" class="@error('phone') text-danger @enderror">Telefon<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('phone') border-danger @enderror" id="phone"
wire:model="phone" placeholder="Telefon" oninput="formatPhoneNumber()">
<div class="text-danger">
@error('phone')
{{ $message }}
@enderror
</div>
</div>
<div class="form-group col-md-6">
<label for="email" class="@error('email') text-danger @enderror">E-posta<span
class="text-danger">*</span></label>
<input type="email" class="form-control @error('email') border-danger @enderror" id="email"
wire:model="email" placeholder="E-posta">
<div class="text-danger">
@error('email')
{{ $message }}
@enderror
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="tax_id" class="@error('tax_id') text-danger @enderror">Vergi Kimlik Numarası<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('tax_id') border-danger @enderror" id="tax_id"
wire:model="tax_id" placeholder="Vergi Kimlik Numarası">
<div class="text-danger">
@error('tax_id')
{{ $message }}
@enderror
</div>
</div>
<div class="form-group col-md-6">
<label for="tax_office" class="@error('tax_office') text-danger @enderror">Vergi Dairesi<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('tax_office') border-danger @enderror" id="tax_office"
wire:model="tax_office" placeholder="Vergi Dairesi">
<div class="text-danger">
@error('tax_office')
{{ $message }}
@enderror
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="country" class="@error('country') text-danger @enderror">Ülke<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('country') border-danger @enderror" id="country"
wire:model="country" placeholder="Ülke" readonly>
<div class="text-danger">
@error('country')
{{ $message }}
@enderror
</div>
</div>
<div class="form-group col-md-6">
<label for="country_code" class="@error('country_code') text-danger @enderror">Ülke Kodu<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('country_code') border-danger @enderror" id="country_code"
wire:model="country_code" placeholder="Ülke Kodu" readonly>
<div class="text-danger">
@error('country_code')
{{ $message }}
@enderror
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="country_iso" class="@error('country_iso_code') text-danger @enderror">Ülke ISO Kodu<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('country_iso_code') border-danger @enderror"
id="country_iso" wire:model="country_iso_code" placeholder="Ülke ISO Kodu" readonly>
<div class="text-danger">
@error('country_iso_code')
{{ $message }}
@enderror
</div>
</div>
<div class="form-group col-md-6">
<label for="city" class="@error('city') text-danger @enderror">Şehir<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('city') border-danger @enderror" id="city"
wire:model="city" placeholder="Şehir">
<div class="text-danger">
@error('city')
{{ $message }}
@enderror
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="district" class="@error('district') text-danger @enderror">İlçe<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('district') border-danger @enderror" id="district"
wire:model="district" placeholder="İlçe">
<div class="text-danger">
@error('district')
{{ $message }}
@enderror
</div>
</div>
<div class="form-group col-md-6">
<label for="address" class="@error('address') text-danger @enderror">Adres<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('address') border-danger @enderror" id="address"
wire:model="address" placeholder="Adres">
<div class="text-danger">
@error('address')
{{ $message }}
@enderror
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<label for="notes" class="@error('notes') text-danger @enderror">Notlar</label>
<textarea class="form-control @error('notes') border-danger @enderror" id="notes" rows="3" placeholder="Notlar"
wire:model="notes"></textarea>
<div class="text-danger">
@error('notes')
{{ $message }}
@enderror
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">Kaydet</button>
</form>
</div>
</div>
edit livewire:
<?php
namespace App\Livewire\Admin\Supplier;
use App\Models\Suppliers;
use Livewire\Component;
class Edit extends Component
{
public $id, $name, $bill_name, $tax_id, $tax_office, $phone, $email, $city, $district, $address, $notes, $is_active;
public $country = "Türkiye", $country_code = "90", $country_iso_code = "TR/TUR";
public function rules()
{
return [
'name' => 'required|string|max:255',
'bill_name' => 'required|string|max:255',
'tax_id' => 'required|string|min:11|max:11|unique:suppliers,tax_id,' . $this->id,
'tax_office' => 'required|string|max:100',
'phone' => 'required|string|max:20|unique:suppliers,phone,' . $this->id,
'email' => 'required|email|max:255|unique:suppliers,email,' . $this->id,
'country' => 'required|string|max:255',
'country_code' => 'required|string|max:10',
'country_iso_code' => 'required|string|max:10',
'city' => 'required|string|max:255',
'district' => 'required|string|max:255',
'address' => 'required|string|max:255',
'notes' => 'nullable|string',
];
}
public function messages()
{
return [
'name.required' => 'Tedarikçi adı gereklidir.',
'name.string' => 'Tedarikçi adı geçersiz.',
'name.max' => 'Tedarikçi adı en fazla 255 karakter olmalıdır.',
'bill_name.required' => 'Fatura adı gereklidir.',
'bill_name.string' => 'Fatura adı geçersiz.',
'bill_name.max' => 'Fatura adı en fazla 255 karakter olmalıdır.',
'tax_id.required' => 'Vergi kimlik numarası gereklidir.',
'tax_id.string' => 'Vergi kimlik numarası geçersiz.',
'tax_id.min' => 'Vergi kimlik numarası en az 11 karakter olmalıdır.',
'tax_id.max' => 'Vergi kimlik numarası en fazla 11 karakter olmalıdır.',
'tax_id.unique' => 'Bu vergi kimlik numarası daha önce kullanılmıştır.',
'tax_office.required' => 'Vergi dairesi gereklidir.',
'tax_office.string' => 'Vergi dairesi geçersiz.',
'tax_office.max' => 'Vergi dairesi en fazla 100 karakter olmalıdır.',
'phone.required' => 'Telefon numarası gereklidir.',
'phone.string' => 'Telefon numarası geçersiz.',
'phone.max' => 'Telefon numarası en fazla 20 karakter olmalıdır.',
'phone.unique' => 'Bu telefon numarası daha önce kullanılmıştır.',
'email.required' => 'E-posta adresi gereklidir.',
'email.email' => 'E-posta adresi geçersiz.',
'email.max' => 'E-posta adresi en fazla 255 karakter olmalıdır.',
'email.unique' => 'Bu e-posta adresi daha önce kullanılmıştır.',
'country.required' => 'Ülke gereklidir.',
'country.string' => 'Ülke geçersiz.',
'country.max' => 'Ülke en fazla 255 karakter olmalıdır.',
'country_code.required' => 'Ülke kodu gereklidir.',
'country_code.string' => 'Ülke kodu geçersiz.',
'country_code.max' => 'Ülke kodu en fazla 10 karakter olmalıdır.',
'country_iso_code.required' => 'Ülke ISO kodu gereklidir.',
'country_iso_code.string' => 'Ülke ISO kodu geçersiz.',
'country_iso_code.max' => 'Ülke ISO kodu en fazla 10 karakter olmalıdır.',
'city.required' => 'Şehir gereklidir.',
'city.string' => 'Şehir geçersiz.',
'city.max' => 'Şehir en fazla 255 karakter olmalıdır.',
'district.required' => 'İlçe gereklidir.',
'district.string' => 'İlçe geçersiz.',
'district.max' => 'İlçe en fazla 255 karakter olmalıdır.',
'address.required' => 'Adres gereklidir.',
'address.string' => 'Adres geçersiz.',
'address.max' => 'Adres en fazla 255 karakter olmalıdır.',
];
}
public function render()
{
return view('livewire.admin.supplier.edit');
}
public function update()
{
$this->validate();
$supplier = Suppliers::find($this->id);
if (!$supplier) {
$this->dispatch('message', [
'type' => 'warning',
'title' => 'Hata',
'message' => 'Tedarikçi bulunamadı.'
]);
return;
}
$phone = preg_replace('/[^0-9]/', '', $this->phone);
$saveStatus = $supplier->update([
'name' => $this->name,
'bill_name' => $this->bill_name,
'tax_id' => $this->tax_id,
'tax_office' => $this->tax_office,
'phone' => $phone,
'email' => $this->email,
'country' => $this->country,
'country_code' => $this->country_code,
'country_iso_code' => $this->country_iso_code,
'city' => $this->city,
'district' => $this->district,
'address' => $this->address,
'notes' => $this->notes,
]);
if (!$saveStatus) {
$this->dispatch('message', [
'type' => 'error',
'title' => 'Hata',
'message' => 'Tedarikçi güncellenirken hata oluştu.'
]);
return;
}
$this->dispatch('message', [
'type' => 'success',
'title' => 'Başarılı',
'message' => 'Tedarikçi başarıyla güncellendi.'
]);
}
public function changeActivity()
{
$this->is_active = !$this->is_active;
$supplier = Suppliers::find($this->id);
if (!$supplier) {
$this->dispatch('message', [
'type' => 'warning',
'title' => 'Hata',
'message' => 'Tedarikçi bulunamadı.'
]);
return;
}
if ($supplier->is_active === 1) {
$supplier->is_active = 0;
} elseif ($supplier->is_active === 0) {
$supplier->is_active = 1;
} elseif ($supplier->is_active === 0) {
$supplier->is_active = 1;
}
$saveStatus = $supplier->save();
if (!$saveStatus) {
$this->dispatch('message', [
'type' => 'error',
'title' => 'Hata',
'message' => 'Tedarikçi durumu güncellenirken hata oluştu.'
]);
return;
}
$supplier->is_active = $this->is_active;
$this->dispatch('message', [
'type' => 'success',
'title' => 'Başarılı',
'message' => 'Tedarikçi durumu başarıyla güncellendi.'
]);
}
}
edit blade:
<div class="col-12 card">
{{-- If your happiness depends on money, you will never be happy with yourself. --}}
<div class="card-body">
<form wire:submit.prevent="update">
<div class="form-row">
<div class="form-group col-md-6">
<label for="name" class="@error('name') text-danger @enderror">Tedarikçi Adı<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('name') border-danger @enderror" id="name"
wire:model="name" placeholder="Tedarikçi Adı">
<div class="text-danger">
@error('name')
{{ $message }}
@enderror
</div>
</div>
<div class="form-group col-md-6">
<label for="bill_name" class="@error('bill_name') text-danger @enderror">Fatura Adı<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('bill_name') border-danger @enderror" id="bill_name"
wire:model="bill_name" placeholder="Fatura Adı">
<div class="text-danger">
@error('bill_name')
{{ $message }}
@enderror
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="phone" class="@error('phone') text-danger @enderror">Telefon<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('phone') border-danger @enderror" id="phone"
wire:model="phone" placeholder="Telefon" oninput="formatPhoneNumber()" onfocus="formatPhoneNumber()">
<div class="text-danger">
@error('phone')
{{ $message }}
@enderror
</div>
</div>
<div class="form-group col-md-6">
<label for="email" class="@error('email') text-danger @enderror">E-posta<span
class="text-danger">*</span></label>
<input type="email" class="form-control @error('email') border-danger @enderror" id="email"
wire:model="email" placeholder="E-posta">
<div class="text-danger">
@error('email')
{{ $message }}
@enderror
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="tax_id" class="@error('tax_id') text-danger @enderror">Vergi Kimlik Numarası<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('tax_id') border-danger @enderror" id="tax_id"
wire:model="tax_id" placeholder="Vergi Kimlik Numarası">
<div class="text-danger">
@error('tax_id')
{{ $message }}
@enderror
</div>
</div>
<div class="form-group col-md-6">
<label for="tax_office" class="@error('tax_office') text-danger @enderror">Vergi Dairesi<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('tax_office') border-danger @enderror" id="tax_office"
wire:model="tax_office" placeholder="Vergi Dairesi">
<div class="text-danger">
@error('tax_office')
{{ $message }}
@enderror
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="country" class="@error('country') text-danger @enderror">Ülke<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('country') border-danger @enderror" id="country"
wire:model="country" placeholder="Ülke" readonly>
<div class="text-danger">
@error('country')
{{ $message }}
@enderror
</div>
</div>
<div class="form-group col-md-6">
<label for="country_code" class="@error('country_code') text-danger @enderror">Ülke Kodu<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('country_code') border-danger @enderror" id="country_code"
wire:model="country_code" placeholder="Ülke Kodu" readonly>
<div class="text-danger">
@error('country_code')
{{ $message }}
@enderror
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="country_iso" class="@error('country_iso_code') text-danger @enderror">Ülke ISO Kodu<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('country_iso_code') border-danger @enderror"
id="country_iso" wire:model="country_iso_code" placeholder="Ülke ISO Kodu" readonly>
<div class="text-danger">
@error('country_iso_code')
{{ $message }}
@enderror
</div>
</div>
<div class="form-group col-md-6">
<label for="city" class="@error('city') text-danger @enderror">Şehir<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('city') border-danger @enderror" id="city"
wire:model="city" placeholder="Şehir">
<div class="text-danger">
@error('city')
{{ $message }}
@enderror
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="district" class="@error('district') text-danger @enderror">İlçe<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('district') border-danger @enderror" id="district"
wire:model="district" placeholder="İlçe">
<div class="text-danger">
@error('district')
{{ $message }}
@enderror
</div>
</div>
<div class="form-group col-md-6">
<label for="address" class="@error('address') text-danger @enderror">Adres<span
class="text-danger">*</span></label>
<input type="text" class="form-control @error('address') border-danger @enderror" id="address"
wire:model="address" placeholder="Adres">
<div class="text-danger">
@error('address')
{{ $message }}
@enderror
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<label for="notes" class="@error('notes') text-danger @enderror">Notlar</label>
<textarea class="form-control @error('notes') border-danger @enderror" id="notes" rows="3" placeholder="Notlar"
wire:model="notes"></textarea>
<div class="text-danger">
@error('notes')
{{ $message }}
@enderror
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">Kaydet</button>
@if ($is_active == 1)
<button class="btn btn-success btn-sm" wire:click="changeActivity" type="button">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-unlock-fill" viewBox="0 0 16 16">
<path fill-rule="evenodd"
d="M12 0a4 4 0 0 1 4 4v2.5h-1V4a3 3 0 1 0-6 0v2h.5A2.5 2.5 0 0 1 12 8.5v5A2.5 2.5 0 0 1 9.5 16h-7A2.5 2.5 0 0 1 0 13.5v-5A2.5 2.5 0 0 1 2.5 6H8V4a4 4 0 0 1 4-4" />
</svg>
</button>
@elseif ($is_active == 0)
<button class="btn btn-danger btn-sm" wire:click="changeActivity" type="button">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-lock-fill" viewBox="0 0 16 16">
<path fill-rule="evenodd"
d="M8 0a4 4 0 0 1 4 4v2.05a2.5 2.5 0 0 1 2 2.45v5a2.5 2.5 0 0 1-2.5 2.5h-7A2.5 2.5 0 0 1 2 13.5v-5a2.5 2.5 0 0 1 2-2.45V4a4 4 0 0 1 4-4m0 1a3 3 0 0 0-3 3v2h6V4a3 3 0 0 0-3-3" />
</svg>
</button>
@endif
</form>
</div>
</div>
@script
<script>
$wire.on('message', message => {
let status = message[0]["type"];
let content = message[0]["message"];
let head = message[0]["title"];
if (status == 'success') {
toastr.success(content, head);
} else if (status == 'error') {
toastr.error(content, head);
} else if (status == 'warning') {
toastr.warning(content, head);
} else if (status == 'info') {
toastr.info(content, head);
} else {
toastr.error("Bilinmeyen bir hata oluştu.", "HATA");
}
});
</script>
@endscript
Please or to participate in this conversation.