Search code examples
phplaravellaravel-livewirelivewires

Laravel livewire - record not created in DB


Good day! Started learning Livewire. I work on a pet-project of a news site. Livewire connected, database connected correctly, migrations created. The output of news categories works correctly. There was a problem creating the form for adding a news category and submitting it.

web.php

Route::group(['prefix' => 'admin', 'as' => 'admin.'], function () {

    Route::get('/newsCategories/show', ShowNewsCategories::class)
        ->name('news.categories.show');
    Route::get('/newsCategories/create', CreateNewsCategory::class)
        ->name('news.categories.create');
});

CreateNewsCategory.php (app/Http/Livewire/Admin/NewsCategories/CreateNewsCategory.php)

<?php

namespace App\Http\Livewire\Admin\NewsCategories;

use App\Models\NewsCategory;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Livewire\Component;

class CreateNewsCategory extends Component
{
    public $name;
    public $order;

    protected $rules = [
        'name' => 'required|string|max:220',
        'order' => 'required'
    ];

    public function create(){
        $this->validate();

        NewsCategory::create([
            'name' => $this->name,
            'order' => $this->order,
        ]);
    }

    /**
     * @return Factory|View|Application
     */
    public function render()
    {
        return view('livewire.admin.news-categories.create-news-category')
            ->extends('layouts.admin.master')
            ->section('content');
    }
}

/resources/views/livewire/admin/news-categories/create-news-category.blade.php

<form wire:submit.prevent="create">
    <div class="form-group">
        <label for="name">Name</label>
        <input type="text" class="form-control" id="name" placeholder="Enter name" wire:model="name">
    </div>

    <div class="form-group">
        <label for="order">Order</label>
        <input type="text" class="form-control" id="order" placeholder="Enter order" wire:model="order">
    </div>

    <button type="submit" class="btn btn-primary" wire:click="create">Create</button>
</form>

NewsCategory.php (/app/Models/NewsCategory.php)

<?php

namespace App\Models;

use Carbon\Carbon;
use Cviebrock\EloquentSluggable\Sluggable;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;


class NewsCategory extends Model
{
    use Sluggable;
    use SoftDeletes;

    protected $table = 'news_categories';

    protected $casts = [
        'order' => 'int'
    ];

    protected $fillable = [
        'order',
        'name',
        'slug'
    ];

    public function articles(): HasMany
    {
        return $this->hasMany(Article::class);
    }

    public function sluggable(): array
    {
        return [
            'slug' => [
                'source' => 'name'
            ]
        ];
    }
}

Result - the page is reloaded, but the record in the database is not created.

I tried to change the 'create' function code to component CreateNewsCategory:

public function create(){
        die($this->name);
}

In all cases the page reloads and nothing happens. Help please


Solution

  • you're using the wire:submit.prevent directive on the form and the wire:click directive on the button. In this case, the create method is being triggered twice when you click the button. You should only use one of these directives.

    <!-- /resources/views/livewire/admin/news-categories/create-news-category.blade.php -->
    <form wire:submit.prevent="create">
        <div class="form-group">
            <label for="name">Name</label>
            <input type="text" class="form-control" id="name" placeholder="Enter name" wire:model="name">
        </div>
    
        <div class="form-group">
            <label for="order">Order</label>
            <input type="text" class="form-control" id="order" placeholder="Enter order" wire:model="order">
        </div>
    
        <button type="submit" class="btn btn-primary">Create</button>
    </form>
    

    Now, the create method should only be called once when the form is submitted.

    For your other issue, if page is being reloaded, may indicates that the form is being submitted traditionally (without Livewire's intervention) rather than being intercepted and handled by Livewire. Inspect the form element to see if it has a wire:id attribute. If it doesn't, Livewire is not initializing properly.

    Be sure that you followed every step in: https://laravel-livewire.com/docs/2.x/quickstart