😅[COMMON] validator->fails, ajax, unique full (ok)

https://www.itsolutionstuff.com/post/laravel-9-ajax-form-validation-exampleexample.html

Example 1.1 cơ bản

C:\xampp\htdocs\test\routes\web.php

<?php
use App\Http\Controllers\PostController;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
 */
Route::get('/', function () {
  return view('welcome');
});
Route::controller(PostController::class)->group(function () {
  Route::get('posts', 'index');
  Route::post('posts', 'store')->name('posts.store');
});

C:\xampp\htdocs\test\app\Http\Controllers\PostController.php

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Post;
use Illuminate\Support\Facades\Validator;
class PostController extends Controller
{
  /**
   * Write code on Method
   *
   * @return response()
   */
  public function index()
  {
    $posts = Post::get();
    return view('posts', compact('posts'));
  }
  /**
   * Write code on Method
   *
   * @return response()
   */
  public function store(Request $request)
  {
    $validator = Validator::make($request->all(),
    [
      'title' => 'required|unique:posts',
      'body' => 'required',
    ],[
      'title.unique' => "Error 😒"
    ]);
    if ($validator->fails()) {
      return response()->json(['error' => $validator->errors()->all()]);
    }
    Post::create([
      'title' => $request->title,
      'body' => $request->body,
    ]);
    return response()->json(['success' => 'Post created successfully.']);
  }
}

C:\xampp\htdocs\test\database\migrations\2022_05_05_040656_create_posts_table.php

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePostsTable extends Migration {
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up() {
    Schema::create('posts', function (Blueprint $table) {
      $table->id();
      $table->string('title');
      $table->text('body');
      $table->timestamps();
    });
  }
  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down() {
    Schema::dropIfExists('posts');
  }
}

C:\xampp\htdocs\test\app\Models\Post.php

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model {
  use HasFactory;
  /**
   * Write code on Method
   *
   * @return response()
   */
  protected $fillable = [
    'title', 'body',
  ];
}

C:\xampp\htdocs\test\resources\views\posts.blade.php

<!DOCTYPE html>
<html>
	<head>
		<title>Laravel 9 Ajax Post Request Example - ItSolutionStuff.com</title>
		<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
		<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"></script>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
		<meta name="csrf-token" content="{{ csrf_token() }}" />
	</head>
	<body>
		<div class="container">
			<div class="card bg-light mt-3">
				<div class="card-header"> Laravel 9 Ajax Post Request Example - ItSolutionStuff.com </div>
				<div class="card-body">
					<table class="table table-bordered mt-3">
						<tr>
							<th colspan="3">
								List Of Posts
								<button type="button" class="btn btn-success float-end" data-bs-toggle="modal" data-bs-target="#postModal"> Create Post</button>
							</th>
						</tr>
						<tr>
							<th>ID</th>
							<th>Title</th>
							<th>Body</th>
						</tr> 
						@foreach($posts as $post) 
							<tr>
								<td>{{ $post->id }}</td>
								<td>{{ $post->title }}</td>
								<td>{{ $post->body }}</td>
							</tr> 
						@endforeach
					</table>
				</div>
			</div>
		</div>
		<!-- Modal -->
		<div class="modal fade" id="postModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
			<div class="modal-dialog">
				<div class="modal-content">
					<div class="modal-header">
						<h5 class="modal-title" id="exampleModalLabel">Create Post</h5>
						<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
					</div>
					<div class="modal-body">
						<form>
							<div class="alert alert-danger print-error-msg" style="display:none">
								<ul></ul>
							</div>
							<div class="mb-3">
								<label for="titleID" class="form-label">Title:</label>
								<input type="text" id="titleID" name="name" class="form-control" placeholder="Name" required="">
							</div>
							<div class="mb-3">
								<label for="bodyID" class="form-label">Body:</label>
								<textarea name="body" class="form-control" id="bodyID"></textarea>
							</div>
							<div class="mb-3 text-center">
								<button class="btn btn-success btn-submit">Submit</button>
							</div>
						</form>
					</div>
				</div>
			</div>
		</div>
	</body>
	<script type="text/javascript">
		$.ajaxSetup({
			headers: {
				'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
			}
		});
		$(".btn-submit").click(function(e) {
			e.preventDefault();
			var title = $("#titleID").val();
			var body = $("#bodyID").val();
			$.ajax({
				type: 'POST',
				url: "{{ route('posts.store') }}",
				data: { title: title, body: body },
				success: function(data) {
					if ($.isEmptyObject(data.error)) {
						alert(data.success);
						location.reload();
					} else {
						printErrorMsg(data.error);
					}
				}
			});
		});
		function printErrorMsg(msg) {
			$(".print-error-msg").find("ul").html('');
			$(".print-error-msg").css('display', 'block');
			$.each(msg, function(key, value) {
				$(".print-error-msg").find("ul").append('<li>' + value + '</li>');
			});
		}
	</script>
</html>

Example 1.2 Update trường title, body duy nhất bằng ajax (ok)

C:\xampp8\htdocs\plugindev\routes\web.php

<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
  return view('welcome');
});
Route::controller(PostController::class)->group(function () {
  Route::get('posts', 'index');
  Route::post('posts', 'store')->name('posts.store');
  Route::put('posts/{id}', 'update')->name('posts.update');
});

C:\xampp8\htdocs\plugindev\app\Http\Controllers\PostController.php

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Post;
use Illuminate\Support\Facades\Validator;
class PostController extends Controller
{
  /**
   * Write code on Method
   *
   * @return response()
   */
  public function index()
  {
    $posts = Post::get();
    return view('posts', compact('posts'));
  }
  /**
   * Write code on Method
   *
   * @return response()
   */
  public function store(Request $request)
  {
    $validator = Validator::make(
      $request->all(),
      [
        'title' => 'required|unique:posts',
        'body' => 'required|unique:posts',
      ],
      [
        'title.required' => "title.required 😒",
        'title.unique' => "title.unique 😒",
        'body.required' => "body.required 😒",
        'body.unique' => "body.unique 😒"
      ]
    );
    if ($validator->fails()) {
      return response()->json(['error' => $validator->errors()->all()]);
    }
    Post::create([
      'title' => $request->title,
      'body' => $request->body,
    ]);
    return response()->json(['success' => 'Post created successfully.']);
  }
  public function update(Request $request, $id)
  {
    $post = Post::find($id);
    $datas = $request->all();
    $titleC = 'required';
    $bodyC = 'required';
    $forTitle = $datas['forTitle'];
    $forBody = $datas['forBody'];
    $title = $datas['title'];
    $body = $datas['body'];
    if ($forTitle == 'true') {
      $titleC = 'required|unique:posts';
    }
    if ($forBody == 'true') {
      $bodyC = 'required|unique:posts';
    }
    $validator = Validator::make(
      $datas,
      [
        'title' => $titleC,
        'body' => $bodyC,
      ],
      [
        'title.required' => "title.required 😒",
        'title.unique' => "title.unique 😒",
        'body.required' => "body.required 😒",
        'body.unique' => "body.unique 😒"
      ]
    );
    if ($validator->fails()) {
      return response()->json(['error' => $validator->errors()->all()]);
    }
    $post->title = $title;
    $post->body = $body;
    $post->save();
  }
}

C:\xampp8\htdocs\plugindev\resources\views\posts.blade.php

<!DOCTYPE html>
<html>
<head>
  <title>Laravel 9 Ajax Post Request Example - ItSolutionStuff.com</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
    integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous">
  </script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
  <meta name="csrf-token" content="{{ csrf_token() }}" />
</head>
<body>
  <div class="container">
    <div class="card bg-light mt-3">
      <div class="card-header">
        Laravel 9 Ajax Post Request Example - ItSolutionStuff.com
      </div>
      <div class="card-body">
        <table class="table table-bordered mt-3">
          <tr>
            <th colspan="3">
              List Of Posts
              <button type="button" class="btn btn-success float-end" data-bs-toggle="modal" data-bs-target="#postModal">
                Create Post
              </button>
            </th>
          </tr>
          <tr>
            <th>ID</th>
            <th>Title</th>
            <th>Body</th>
          </tr>
          @foreach($posts as $post)
          <tr>
            <td>{{ $post->id }}</td>
            <td>{{ $post->title }}</td>
            <td>{{ $post->body }} <button type="button" class="btn btn-success float-end" data-bs-toggle="modal" data-bs-target="#postModalEdit{{ $post->id }}">Edit Post</button></td>
          </tr>
          @endforeach
        </table>
        @foreach($posts as $post2)
        <!-- Modal Edit-->
        <div class="modal fade" id="postModalEdit{{ $post2->id }}" tabindex="-1" aria-labelledby="exampleModalEditLabel{{ $post2->id }}" aria-hidden="true">
          <div class="modal-dialog">
            <div class="modal-content">
              <div class="modal-header">
                <h5 class="modal-title" id="exampleModalEditLabel{{ $post2->id }}">Create Post</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
              </div>
              <div class="modal-body">
                <form>
                  @method('PUT')
                  <div class="alert alert-danger print-error-msg{{ $post2->id }}" style="display:none">
                    <ul></ul>
                  </div>
                  <div class="mb-3">
                    <label for="titleID{{ $post2->id }}" class="form-label">Title:</label>
                    <input type="text" id="titleID{{ $post2->id }}" name="name" class="form-control" placeholder="Name" required value="{{ $post2->title }}">
                  </div>
                  <div class="mb-3">
                    <label for="bodyID{{ $post2->id }}" class="form-label">Body:</label>
                    <textarea name="body" id="bodyID{{ $post2->id }}" class="form-control">{{ $post2->body }}</textarea>
                  </div>
                  <div class="mb-3 text-center">
                    <button class="btn btn-success btn-submit-put" data-id="{{ $post2->id }}" data-url="{{ route('posts.update',$post2->id) }}" data-title="{{ $post2->title }}" data-body="{{ $post2->body }}">Submit</button>
                  </div>
                </form>
              </div>
            </div>
          </div>
        </div>
        @endforeach
      </div>
    </div>
  </div>
  <!-- Modal -->
  <div class="modal fade" id="postModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModalLabel">Create Post</h5>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
        <div class="modal-body">
          <form>
            <div class="alert alert-danger print-error-msg" style="display:none">
              <ul></ul>
            </div>
            <div class="mb-3">
              <label for="titleID" class="form-label">Title:</label>
              <input type="text" id="titleID" name="name" class="form-control" placeholder="Name" required="">
            </div>
            <div class="mb-3">
              <label for="bodyID" class="form-label">Body:</label>
              <textarea name="body" class="form-control" id="bodyID"></textarea>
            </div>
            <div class="mb-3 text-center">
              <button class="btn btn-success btn-submit" data-url="{{ route('posts.store') }}">Submit</button>
            </div>
          </form>
        </div>
      </div>
    </div>
  </div>
</body>
<script type="text/javascript">
  $.ajaxSetup({
      headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
      }
    });
    function printErrorMsg (msg) {
      $(".print-error-msg").find("ul").html('');
      $(".print-error-msg").css('display','block');
      $.each( msg, function( key, value ) {
          $(".print-error-msg").find("ul").append('<li>'+value+'</li>');
      });
    }
    $(".btn-submit").click(function(e){
      e.preventDefault();
      var title = $("#titleID").val();
      var body = $("#bodyID").val();
      var url = $(this).data("url");
      $.ajax({
        type:'POST',
        url: url,
        data:{title, body},
        success:function(data){
        if($.isEmptyObject(data.error)){
          alert(data.success);
          location.reload();
        }else{
          printErrorMsg(data.error);
        }
        }
      });
    });
    $(".btn-submit-put").click(function(e){
      e.preventDefault();
      var url = $(this).data("url");
      var getId = $(this).data("id");
      var getTitle = $(this).data("title");
      var getBody = $(this).data("body");
      var formData = $(this).closest('form').serializeArray();
      var title = formData[1].value;
      var body = formData[2].value;
      var forTitle = false;
      var forBody = false;
      if(getTitle != title) {
        forTitle = true;
      }
      if(getBody != body) {
        forBody = true;
      }
      $.ajax({
        type:'PUT',
        url: url,
        data:{title, body,forTitle,forBody},
        success:function(data){
          if($.isEmptyObject(data.error)){
            alert("タグが登録されました。");
            location.reload();
          }else{
            printErrorMsgPut(data.error,getId);
          }
        }
      });
      function printErrorMsgPut (msg,getId) {
        $(".print-error-msg"+getId).find("ul").html('');
        $(".print-error-msg"+getId).css('display','block');
        $.each( msg, function( key, value ) {
          $(".print-error-msg"+getId).find("ul").append('<li>'+value+'</li>');
        });
      }
    });
</script>
</html>

Example 2. cmstest.com

C:\xampp8\htdocs\marinesTeam26CMS\app\Models\Tag.php

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Tag extends Model
{
  use HasFactory, SoftDeletes;
  public $timestamps = false;
  protected $table = 'tag';
  protected $primaryKey = 'id';
  protected $fillable = [
    'tag_id',
    'tag_name',
    'created_at',
    'create_user',
    'updated_at',
    'update_user',
    'deleted_at',
    'delete_user'
  ];
  public function movies() {
    return $this->belongsToMany(Movie::class, 'tag_movie');
  }
}

C:\xampp8\htdocs\marinesTeam26CMS\database\migrations\2022_12_09_022743_create_tag_table.php

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateTagTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('tag', function (Blueprint $table) {
          $table->increments('id');
          $table->integer('tag_id')->unique();
          $table->string('tag_name')->unique();
          $table->dateTime('created_at')->nullable();
          $table->string('create_user')->nullable();
          $table->dateTime('updated_at')->nullable();
          $table->string('update_user')->nullable();
          $table->dateTime('deleted_at')->nullable();
          $table->string('delete_user')->nullable();
        });
    }
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('tag');
    }
}

C:\xampp8\htdocs\marinesTeam26CMS\database\factories\TagFactory.php

<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class TagFactory extends Factory
{
  private static $order = 1;
  /**
   * Define the model's default state.
   *
   * @return array
   */
  public function definition()
  {
    return [
      'tag_id' => self::$order++,
      'tag_name' => $this->faker->text(10),
      'created_at' => $this->faker->dateTime(),
      'create_user' => $this->faker->name(),
      'updated_at' => $this->faker->dateTime(),
      'update_user' => $this->faker->name(),
      'deleted_at' => null,
      'delete_user' => $this->faker->name()
    ];
  }
}

C:\xampp8\htdocs\marinesTeam26CMS\app\Http\Controllers\TagController.php

<?php
namespace App\Http\Controllers;
use App\Models\Tag;
use App\Models\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use Illuminate\Support\Facades\Validator;
class TagController extends Controller
{
  public function __construct()
  {
    $this->middleware('auth');
  }
  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function index(Request $request)
  {
    $allrequest = $request->all();
    if (array_key_exists("createUpdateAt", $allrequest)) {
      $createUpdateAt = $allrequest['createUpdateAt'];
      $descAsc = $allrequest['descAsc'];
      $datas = Tag::orderBy($createUpdateAt, $descAsc);
    }
    $datas = isset($datas) ? $datas->paginate(20) : Tag::paginate(20);
    $permission = Auth::user()->permission;
    return view('page.tag')->with(compact('datas', 'permission', 'allrequest'));
  }
  /**
   * Show the form for creating a new resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function create()
  {
    //
  }
  /**
   * Store a newly created resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @return \Illuminate\Http\Response
   */
  public function store(Request $request)
  {
    $allrequest = $request->all();
    $tag = new Tag();
    $tag->tag_id = $allrequest['tag_id'];
    $tag->tag_name = $allrequest['tag_name'];
    $validator = Validator::make($request->all(),
    [
      'tag_id' => 'required|integer|unique:tag',
      'tag_name' => 'required|unique:tag',
    ],[
      'tag_id.required' => "タグIDがまだ入力されていません。タグIDを入力してください。",
      'tag_id.integer' => "タグ ID は整数でなければなりません。",
      'tag_id.unique' => "タグIDがもう存在しました。新しいタグIDを入力してください。",
      'tag_name.required' => "タグ名刺がまだ入力されていません。タグ名刺をを入力してください。",
      'tag_name.unique' => "タグ名刺がもう存在しました。新しいタグ名刺を入力してください。",
    ]);
    if ($validator->fails()) {
      return response()->json(['error' => $validator->errors()->all()]);
    }
    $tag->created_at = Carbon::now();
    $tag->create_user = Auth::user()->user_name;
    $tag->save();
    return redirect()->route('tag.index');
  }
  /**
   * Update the specified resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  \App\Models\Tag  $tag
   * @return \Illuminate\Http\Response
   */
  public function update(Request $request, $tag)
  {
    $tag = Tag::find($tag);
    $datas = $request->all();
    $tag->tag_id = $datas['tag_id'];
    $tag->tag_name = $datas['tag_name'];
    $forUId = $datas['forUId'];
    $forUName = $datas['forUName'];
    $tagid = 'required|integer';
    $tagname = 'required';
    if($forUId == 'true') {
      $tagid = 'required|unique:tag';
    }
    if ($forUName == 'true') {
      $tagname = 'required|unique:tag';
    }
    $tag->updated_at = Carbon::now();
    $tag->update_user = Auth::user()->user_name;
    $permission = Auth::user()->permission;
    $validator = Validator::make($request->all(),
    [
      'tag_id' => $tagid,
      'tag_name' => $tagname,
    ],[
      'tag_id.required' => "タグIDがまだ入力されていません。タグIDを入力してください。",
      'tag_id.integer' => "タグ ID は整数でなければなりません。",
      'tag_id.unique' => "タグIDがもう存在しました。新しいタグIDを入力してください。",
      'tag_name.required' => "タグ名刺がまだ入力されていません。タグ名刺をを入力してください。",
      'tag_name.unique' => "タグ名刺がもう存在しました。新しいタグ名刺を入力してください。",
    ]);
    if ($validator->fails()) {
      return response()->json(['error' => $validator->errors()->all()]);
    }
    if ($permission == "1" && array_key_exists("checkper", $datas) && $datas['checkper'] == 'on') {
      $tag->deleted_at = Carbon::now();
      $tag->delete_user = Auth::user()->user_name;
    }
    $tag->save();
  }
  /**
   * Remove the specified resource from storage.
   *
   * @param  \App\Models\Tag  $tag
   * @return \Illuminate\Http\Response
   */
  public function destroy(Tag $tag)
  {
    //
  }
}

C:\xampp8\htdocs\marinesTeam26CMS\resources\views\templates\apps.blade.php

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  <link rel="icon" type="image/x-icon" href="{{ secure_asset('images/favicon.ico') }}">
  <title>TEAM26 CMS</title>
  <meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, shrink-to-fit=no'
    name='viewport' />
  <meta name="csrf-token" content="{{ csrf_token() }}">
  <link href="{{ secure_asset('css/app.css') }}" rel="stylesheet" type="text/css">
  <script type="text/javascript" src="{{ secure_asset('js/app.js') }}"></script>
  @include('inner.style')
  @yield('style')
  <style type="text/css">
    .envname svg {
      height: 30px;
    }
    nav.navbar.navbar-expand-lg.navbar-absolute.fixed-top.navbar-transparent {
      padding-top: 0;
      padding-bottom: 0;
    }
    a.navbar-brand.px-3 {
      margin-right: 0;
    }
    .rounded-4 {
      border-radius: 9rem !important;
      font-size: 12px;
      padding: 3px 5px;
    }
    span.navbar-brand {
      margin-bottom: -12px;
    }
    .main-panel>.content .navbar {
      border-bottom: 0.5px solid #000;
    }
    a.btn.btn-block.btn-fill.w-100.text-start {
      font-size: 12px;
    }
    .d-flex.w-100.justify-content-between.align-items-center.px-4 {
      padding: 10px 0;
    }
    .sidebar .logo,
    .off-canvas-sidebar .logo {
      padding: 10px 18px;
    }
    ul.pagination.d-flex.justify-content-center {
      align-items: center;
      margin-top: 20px;
    }
    .col-custom a.btn:after {
      content: ">";
      position: absolute;
      top: 50%;
      right: 20px;
      transform: translate(0, -50%);
    }
    .container-fluid--custom>.items {
      padding: 0 1rem;
    }
    .sidebar {
      background-color: #000;
      color: #fff;
    }
    .sidebar .logo:after {
      width: calc(100% - 45px);
      left: 50%;
      transform: translateX(-50%);
    }
    div.button,
    div.flat-button {
      background-color: #fff;
    }
    .container-fluid--after:after {
      content: none !important;
    }
    .bg-loggedin {
      background-color: #e0e0e0 !important;
    }
    .container-fluid--after:after {
      content: none !important;
    }
    .btn-pink {
      background-color: #d12b63;
      border: 1px solid #d12b63;
    }
    .swatch-pink {
      color: #fff;
      background-color: #d12b63;
    }
    .table > tbody, table > tbody {
      background-color: #fff;
    }
    .form {
      background-color: #fff;
    }
    .btn-outline-pink {
      --bs-btn-color: var(--bs-pink);
      --bs-btn-border-color: var(--bs-pink);
      --bs-btn-hover-color: #fff;
      --bs-btn-hover-bg: var(--bs-pink);
      --bs-btn-hover-border-color: transparent;
      --bs-btn-focus-shadow-rgb: 220, 53, 69;
      --bs-btn-active-color: #fff;
      --bs-btn-active-bg: var(--bs-pink);
      --bs-btn-active-border-color: transparent;
      --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
      --bs-btn-disabled-color: var(--bs-pink);
      --bs-btn-disabled-bg: transparent;
      --bs-btn-disabled-border-color: var(--bs-pink);
      --bs-gradient: none;
    }
    .list >label {
      display: inline-block;
      padding-right: 12px;
      margin-right: 12px;
    }
    .team-content p {
      font-size: 0.8571em;
    }
    label.btn-outline-pink {
      width: 100px;
    }
    #preview-image-before-upload {
      max-width: 250px;
      object-fit: cover;
    }
    #preview-image-before-upload.active {
      margin-right: 20px;
    }
    .envname span.text-dark {
      background-color: transparent !important;
      color: #000 !important;
    }
    #navbarDropdownsub .dropdown-item:hover,
    #navbarDropdownsub .dropdown-item:active {
      background-color: transparent !important;
    }
    .btn-radius-custom .btn-info {
      border-radius: 30px;
      position: relative;
    }
    .btn-radius-custom .btn-info:after {
      content: ">";
      position: absolute;
      top: 50%;
      right: 10px;
      transform: translate(0, -50%);
    }
    .col-custom {
      flex: 0 0 20%;
      max-width: 20%;
      padding: 0px 12px;
      min-width: 200px;
    }
    .footer {
      padding: 15px 0;
    }
  </style>
</head>
<body>
  <div class="wrapper ">
    @include('inner.sidebar')
    <div class="main-panel">
      @include('inner.navbar')
      @yield('content')
      @include('inner.footer')
    </div>
  </div>
  @include('inner.script')
  @yield('script')
  @yield('script-add')
  <script>
    $(function () {
      $(".parent a").click(function (e) {
        var elems = $(this).closest('li');
        elems.toggleClass("mainactive");
        if (elems.find('.submenu').length) {
            $(".submenu:first", elems).toggle();
        }
    });
    });
  </script>
</body>
</html>

C:\xampp8\htdocs\marinesTeam26CMS\resources\views\page\tag.blade.php

@extends('templates.apps')
@section('title', '動画管理')
@section('style')
<style type="text/css">
  .container-top .form {
    margin: 30px 0px 10px 0;
    border: 1px solid #ccc;
    padding: 10px 15px
  }
  .container-top .form table {
    display: table;
    width: 100%;
    font-size: 12px;
  }
  .container-top .form table td {
    vertical-align: middle;
    padding: 10px 0px
  }
  .container-top .form .w-30 {
    width: 30%
  }
  .container-top .form .list label {
    display: inline-flex;
    padding-right: 20px;
    align-items: center
  }
  .container-top .form .list label input {
    width: 20px;
    height: 20px;
    margin-right: 5px
  }
  .container-top .form .list label input[type="checkbox"] {
    accent-color: grey
  }
  .container-top .button {
    margin: 20px 0px;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center
  }
  .container-top .btn {
    width: max-content;
    min-width: 120px;
    height: 40px;
    border-radius: 5px;
    font-size: 14px;
    cursor: pointer;
    margin: 0px 10px
  }
  .container-top .btn-black {
    background: #000;
    color: #fff
  }
  .container-top .btn-pink {
    background-color: #d12b63;
    border: 1px solid #d12b63;
    color: #fff;
    min-width: 280px
  }
  .container-top .team-content {
    margin: 10px 0px;
    padding: 10px 0;
  }
  .container-top .switch {
    position: relative;
    display: inline-block;
    width: 50px;
    height: 23px
  }
  .container-top .switch input {
    opacity: 0;
    width: 0;
    height: 0
  }
  .container-top .slider {
    position: absolute;
    cursor: pointer;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: #333;
    -webkit-transition: .4s;
    transition: .4s
  }
  .container-top .slider:before {
    position: absolute;
    content: "";
    height: 15px;
    width: 15px;
    left: 4px;
    bottom: 4px;
    background-color: white;
    -webkit-transition: .4s;
    transition: .4s
  }
  .container-top input:checked+.slider {
    background-color: #00c39f
  }
  .container-top input:focus+.slider {
    box-shadow: 0 0 1px #00c39f
  }
  .container-top input:checked+.slider:before {
    -webkit-transform: translateX(25px);
    -ms-transform: translateX(25px);
    transform: translateX(25px)
  }
  .container-top .slider.round {
    border-radius: 34px
  }
  .container-top .slider.round:before {
    border-radius: 50%
  }
  .team-content .dropdown {
    display: flex;
    margin-bottom: 20px
  }
  .team-content .dropdown select {
    min-width: 120px;
    margin-right: 15px;
    border-radius: 0;
    padding-left: 5px
  }
  .team-content .dropdown button {
    margin: 0
  }
  .team-content .note {
    text-align: center;
    font-size: 12px;
    margin-bottom: 20px
  }
  .team-content table {
    display: table;
    border: 1px solid #ccc;
  }
  .team-content table td,
  .team-content table th {
    padding: 15px;
    vertical-align: middle;
    border: 1px solid #ccc;
    line-height: 1.5
  }
  .team-content table th {
    text-align: center
  }
  .team-content table td:first-child {
    text-align: center;
    width: 50px
  }
  .team-content table td:nth-child(2) {
    width: 65px;
    text-align: center
  }
  .team-content table td:nth-child(3) {
    width: 160px;
    padding: 5px;
  }
  .team-content table td:nth-child(3) .img {
    max-width: 100%;
  }
  .team-content table td:last-child {
    text-align: center
  }
  .team-content table td img {
    width: 100%
  }
  .team-content table .text h3 a {
    display: inline-block;
    margin: 10px 0px;
    color: #0064e1;
    font-weight: bold;
    border-bottom: 1px solid #0064e1
  }
  .team-content table .tags {
    margin-bottom: 10px
  }
  .team-content table .tags a, .team-content table .tags span {
    display: inline-block;
    font-size: 12px;
    color: #333;
    border: 1px solid #333;
    padding: 2px 5px;
    border-radius: 30px
  }
  .team-content table .time {
    display: flex;
    align-items: center;
    font-size: 12px
  }
  .team-content table .time .time-custom {
    flex: 0 0 50%;
    max-width: 50%;
    display: flex;
    align-items: center;
    border: 1px solid #ccc
  }
  .team-content table .time .time-custom span {
    display: block;
    background-color: #ccc;
    padding: 5px 10px
  }
  .team-content table .time .time-custom p {
    padding-left: 10px
  }
  .custom-select {
    display: inline-block;
    width: 100%;
    height: calc(2.25rem + 2px);
    padding: 0.375rem 1.75rem 0.375rem 0.75rem;
    line-height: 1.5;
    color: #495057;
    vertical-align: middle;
    background-size: 8px 10px;
    border: 1px solid #ced4da;
    border-radius: 0.25rem;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
  }
  .custom-select {
    position: relative;
    -webkit-box-flex: 1;
    -ms-flex: 1 1 auto;
    flex: 1 1 auto;
    width: 1%;
    margin-bottom: 0;
  }
  .custom-select:not(:first-child), .input-group>.form-control:not(:first-child) {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
  }
  .modal-content > .alert {
    margin-top: -20px;
  }
</style>
@endsection
@section('content')
<div class="content">
  <main class="main py-4">
    <div class="container-fluid">
      <nav class="ps-0 navbar bg-secondary bg-loggedin bg-gradient bg-opacity-75 text-white">
        <div class="ps-0 container-fluid">
          <span class="navbar-brand text-dark"><span style=" font-weight: 700; ">動画管理</span> | タグ設定</span>
        </div>
      </nav>
    </div>
    <div class="container-fluid container-top">
      <div class="button bg-transparent">
        <button class="btn btn-pink" data-bs-toggle="modal" data-bs-target="#exampleModal" type="submit">タグ作成</button>
      </div>
      <div class="team-content">
        <p>表示順</p>
        <form action="{{ route('tag.index') }}" method="GET">
          <div class="dropdown">
            <select  name="createUpdateAt">
              <option value="id" @if(in_array("id", $allrequest)) selected @endif>ID</option>
              <option value="tag_id" @if(in_array("tag_id", $allrequest)) selected @endif>タグID</option>
              <option value="tag_name" @if(in_array("tag_name", $allrequest)) selected @endif>タグ名</option>
              <option value="created_at" @if(in_array("created_at", $allrequest)) selected @endif>登録日時</option>
            </select>
            <select name="descAsc">
              <option value="asc" @if(in_array("asc", $allrequest)) selected @endif>昇順</option>
              <option value="desc" @if(in_array("desc", $allrequest)) selected @endif>降順</option>
            </select>
            <button class="btn btn-black" type="submit">ソート</button>
          </div>
        </form>
        <div class="note" id="note">{{ $datas->firstItem() }}〜{{ $datas->lastItem() }}/{{ $datas->total() }}件</div>
        <table>
          <tbody>
            <tr>
              <th style=" width: 60px; ">ID</th>
              <th style=" width: 60px; ">タグID</th>
              <th style=" width: 300px">タグ名</th>
              <th style=" width: 180px; ">登録日時</th>
              <th style=" width: 70px; ">編集</th>
            </tr>
            @foreach ($datas as $key => $data)
              <tr>
                <td>{{$key+ $datas->firstItem()}}</td>
                <td>{{ $data->tag_id }}</td>
                <td>{{ $data->tag_name }}</td>
                <td>
                  {{$data->created_at}}
                </td>
                <td>
                  <a href="javascript:void(0)" data-bs-toggle="modal" data-bs-target="#exampleModalEdit{{ $data->id }}">編集</a>
                </td>
              </tr>
            @endforeach
          </tbody>
        </table>
        @foreach ($datas as $key2 => $data2)
        <div class="modal fade" id="exampleModalEdit{{ $data2->id }}" tabindex="-1" aria-labelledby="exampleModalLabelEdit" aria-hidden="true">
          <form>
            @method('put')
            <div class="modal-dialog">
              <div class="modal-content pt-5">
                <div class="alert alert-danger print-error-msg{{ $data2->id }}" style="display:none">
                  <ul></ul>
                </div>
                <div class="modal-header border-0 py-1">
                  <h1 class="modal-title fs-5" id="exampleModalLabelEdit">タグ登録</h1>
                  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body p-0">
                    <div class="container">
                      <div class="mb-0 col-xs-11 col-sm-11 col-md-11 col-lg-11">
                        <div class="row g-3 align-items-center mb-3">
                          <div class="col-auto p-0" style=" width: 160px; ">
                            <label for="inputPassword1{{$key2}}" class="col-form-label">タグID</label>
                          </div>
                          <div class="col-auto" style=" width: calc(100% - 160px); ">
                            <input type="text" value="{{ $data2->tag_id }}" name="tag_id" id="inputPassword1{{$key2}}" class="form-control addTagID1" aria-describedby="passwordHelpInline">
                          </div>
                          <span class="errorTagID1" style="color:red;display:none;margin-top:0;">タグIDを入力してください。</span>
                        </div>
                        <div class="row g-3 align-items-center mb-3">
                          <div class="col-auto p-0" style=" width: 160px; ">
                            <label for="inputPassword2{{$key2}}" class="col-form-label">表示タグ名称</label>
                          </div>
                          <div class="col-auto" style=" width: calc(100% - 160px); ">
                            <input type="text"  value="{{ $data2->tag_name }}"  name="tag_name" id="inputPassword2{{$key2}}" class="form-control addTagName1" aria-describedby="passwordHelpInline">
                          </div>
                          <span class="errorTagName1" style="color:red;display:none;margin-top:0;">表示タグ名称を入力してください。</span>
                        </div>
                      </div>
                      @if($permission == 1)
                        <div class="form-check form-check-block text-center my-3">
                          <input class="form-check-input float-none" id="deleteinput" @if($data2->deleted_at) checked @endif type="checkbox" name="checkper">
                          <label for="deleteinput">削除する</label>
                        </div>
                      @endif
                      <div class="form-check form-check-block text-center mb-4">
                        <button class="btn btn-sm swatch-pink btn-outline-pink px-5 btn-submit-put" data-url="{{ route('tag.update',$data2->id) }}" data-id="{{$data2->id}}" data-tagid="{{$data2->tag_id}}" data-tagname="{{$data2->tag_name}}">登録</button>
                      </div>
                    </div>
                </div>
              </div>
            </div>
          </form>
        </div>
        @endforeach
        {!! $datas->appends($_GET)->links('vendor.pagination.custom') !!}
      </div>
    </div>
    <!-- Modal -->
    <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
      <form>
        <div class="modal-dialog">
          <div class="modal-content pt-5">
            <div class="alert alert-danger print-error-msg" style="display:none">
              <ul></ul>
            </div>
            <div class="modal-header border-0 pt-3 pb-2">
              <h1 class="modal-title fs-5" id="exampleModalLabel">タグ登録</h1>
              <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body p-0">
              <div class="container">
                <div class="mb-0 col-xs-11 col-sm-11 col-md-11 col-lg-11">
                    <div class="row g-3 align-items-center mb-3">
                      <div class="col-auto p-0" style=" width: 160px; ">
                        <label for="inputPassword6" class="col-form-label">タグID</label>
                      </div>
                      <div class="col-auto" style=" width: calc(100% - 160px); ">
                        <input type="text" name="tag_id" id="inputPassword6" class="form-control addTagID2" aria-describedby="passwordHelpInline">
                      </div>
                      <span class="errorTagID2" style="color:red;display:none;margin-top:0;">タグIDを入力してください。</span>
                    </div>
                    <div class="row g-3 align-items-center mb-3">
                      <div class="col-auto p-0" style=" width: 160px; ">
                        <label for="inputPassword7" class="col-form-label">表示タグ名称</label>
                      </div>
                      <div class="col-auto" style=" width: calc(100% - 160px); ">
                        <input type="text" name="tag_name" id="inputPassword7" class="form-control addTagName2" aria-describedby="passwordHelpInline">
                      </div>
                      <span class="errorTagName2" style="color:red;display:none;margin-top:0;">表示タグ名称を入力してください。</span>
                    </div>
                </div>
                <div class="form-check form-check-block text-center my-3">
                  <button class="btn btn-sm swatch-pink btn-outline-pink px-5 btn-submit">登録</button>
                </div>
              </div>
            </div>
          </div>
        </div>
      </form>
    </div>
  </main>
</div>
@endsection
@section('script-add')
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<script type="text/javascript">
  $(document).ready(function(){
    $.ajaxSetup({
      headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
      }
    });
    function printErrorMsg (msg) {
      $(".print-error-msg").find("ul").html('');
      $(".print-error-msg").css('display','block');
      $.each( msg, function( key, value ) {
        $(".print-error-msg").find("ul").append('<li>'+value+'</li>');
      });
    }
    $(".btn-submit").click(function(e){
      e.preventDefault();
      var tag_id = $("#inputPassword6").val();
      var tag_name = $("#inputPassword7").val();
      $.ajax({
        type:'POST',
        url:"{{ route('tag.store') }}",
        data:{tag_id, tag_name},
        success:function(data){
        if($.isEmptyObject(data.error)){
          alert("タグが登録されました。");
          location.reload();
        }else{
          printErrorMsg(data.error);
        }
        }
      });
    });
    $(".btn-submit-put").click(function(e){
      e.preventDefault();
      var getId = $(this).data("id");
      var tagId = $(this).data("tagid");
      var forUId = false;
      var forUName = false;
      var tagName = $(this).data("tagname");
      var url = $(this).data("url");
      var formData = $(this).closest('form').serializeArray();
      var tag_id = formData[1].value;
      var tag_name = formData[2].value;
      if(tagId != tag_id) {
        forUId = true;
      }
      if(tagName != tag_name) {
        forUName = true;
      }
      $.ajax({
        type:'PATCH',
        url: url,
        data:{tag_id, tag_name,forUId,forUName},
        success:function(data){
          if($.isEmptyObject(data.error)){
            alert("タグが登録されました。");
            location.reload();
          }else{
            printErrorMsgPut(data.error,getId);
          }
        }
      });
    });
    function printErrorMsgPut (msg,getId) {
      $(".print-error-msg"+getId).find("ul").html('');
      $(".print-error-msg"+getId).css('display','block');
      $.each( msg, function( key, value ) {
        $(".print-error-msg"+getId).find("ul").append('<li>'+value+'</li>');
      });
    }
  });
  </script>
@endsection

Last updated