article

Friday, May 12, 2023

React js Laravel 10 REST API Show Product List with pagination Next Prev

React js Laravel 10 REST API Show Product List with pagination Next Prev

Download Laravel App

composer create-project --prefer-dist laravel/laravel my-app
C:\xampp\htdocs\laravel10project>composer create-project laravel/laravel laravel10project

Connecting our Database

open .env file root directory.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laraveldb
DB_USERNAME=root
DB_PASSWORD=

Create Model and Migration

C:\xampp\htdocs\laravel\laravelproject>php artisan make:model Product -m

A new file named Product.php will be created in the app directory and database/migrations directory to generate the table in our database
app/Models/Product.php
//app/Models/Product.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    use HasFactory;

    protected $fillable = [
        'name', 
        'image', 
        'description'
    ];
}
database\migrations\create_products_table.php
//database\migrations\create_products_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('image');
            $table->text('description');
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('products');
    }
};
Database Migration
php artisan migrate

C:\xampp\htdocs\laravel\laravel10project>php artisan migrate
Migration table created successfully.
check database table
Create Controller and Request
C:\xampp\htdocs\laravel\laravel10project>php artisan make:controller ProductController -r

app\Http\Controllers\ProductController.php
//app\Http\Controllers\ProductController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Models\Product;
use App\Http\Requests\ProductStoreRequest;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Storage; //php artisan storage:link = php artisan storage:link = http://127.0.0.1:8000/storage/1.jpg

class ProductController extends Controller
{
    public function index()
    {
       //$products = Product::all(); // All Product
      
       $products = Product::paginate(4);

       // Return Json Response
       return response()->json([
            'results' => $products
       ],200);
    }
  
    public function store(ProductStoreRequest $request)
    {
        try {
            $imageName = Str::random(32).".".$request->image->getClientOriginalExtension();
      
            // Create Product
            Product::create([
                'name' => $request->name,
                'image' => $imageName,
                'description' => $request->description
            ]);
      
            // Save Image in Storage folder
            Storage::disk('public')->put($imageName, file_get_contents($request->image));
      
            // Return Json Response
            return response()->json([
                'message' => "Product successfully created."
            ],200);
        } catch (\Exception $e) {
            // Return Json Response
            return response()->json([
                'message' => "Something went really wrong!"
            ],500);
        }
    }
}
Next, create a Request

C:\xampp\htdocs\laravel\laravel10project>php artisan make:request ProductStoreRequest
app\Http\Requests\ProductStoreRequest.php
//app\Http\Requests\ProductStoreRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class ProductStoreRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        //return false;
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, \Illuminate\Contracts\Validation\Rule|array|string>
     */
    public function rules(): array
    {
        if(request()->isMethod('post')) {
            return [
                'name' => 'required|string|max:258',
                'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
                'description' => 'required|string'
            ];
        } else {
            return [
                'name' => 'required|string|max:258',
                'image' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
                'description' => 'required|string'
            ];
        }
    }
 
    public function messages()
    {
        if(request()->isMethod('post')) {
            return [
                'name.required' => 'Name is required!',
                'image.required' => 'Image is required!',
                'description.required' => 'Descritpion is required!'
            ];
        } else {
            return [
                'name.required' => 'Name is required!',
                'description.required' => 'Descritpion is required!'
            ];   
        }
    }
}
Routes
All API requests will need the header Accept: application/json.
open routes/api.php and update the following code
routes\api.php
//routes\api.php
<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProductController;

Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});

Route::get('products', [ProductController::class, 'index']); 
Route::post('products', [ProductController::class, 'store']); 
generate symbolic links C:\xampp\htdocs\laravel\laravel10project>php artisan storage:link

Run C:\xampp\htdocs\laravel\laravel10project>php artisan serve
Starting Laravel development server: http://127.0.0.1:8000

open postman new request

GET api/products Index All products return.
GET : http://127.0.0.1:8000/api/products

POST api/products Store Create a new product.
POST : http://127.0.0.1:8000/api/products
body
key value
name Iphone 13
image iphone.jpg = file
description product description

React JS
https://create-react-app.dev/

Create Project
C:\react-js>npx create-react-app myreactdev

Run
C:\react-js\myreactdev> npm start

https://github.com/axios/axios

Installing the Axios Client
$ npm install axios

C:\reactdev\myreactdev>npm install axios
C:\react-js\myreactdev\src\App.js
//C:\react-js\myreactdev\src\App.js
import React, { useEffect, useState } from "react";
import axios from "axios";
// Component
import Navbar from "./Component/Navbar";
import ProductList from "./Component/ProductList";
 
function App() {
  const [products, setProducts] = useState([]);
  const [info, setInfo] = useState({});
  const url = "http://127.0.0.1:8000/api/products";
 
  const fetchProducts = (url) => {
    axios
      .get(url)
      .then((data) => {
        setProducts(data.data.results.data);
        //console.log(data.data.results.data);
        setInfo(data.data.results);
        //console.log(data.data.results.next_page_url);
      })
      .catch((error) => {
        console.log(error);
      });
  };
   
  const handleNextPage = () => {
    fetchProducts(info.next_page_url);
    window.scrollTo(0, 0);
  };
 
  const handlePreviousPage = () => {
    fetchProducts(info.prev_page_url);
    window.scrollTo(0, 0);
  };
   
  useEffect(() => {
    fetchProducts(url);
  }, []);
 
 
  return (
    <>
      <Navbar brand="Cairocoders" />
 
      <div className="container py-5"><p><h2>React js Laravel 10 REST API Show Product List with pagination Next Prev</h2></p>
        <nav>
 
          <ul className="pagination justify-content-center">
            {info.prev_page_url ? (
              <li className="page-item">
                <button className="page-link" onClick={handlePreviousPage}>
                  Previous
                </button>
              </li>
            ) : null}
            {info.next_page_url ? (
              <li className="page-item">
                <button className="page-link" onClick={handleNextPage}>
                  Next
                </button>
              </li>
            ) : null}
          </ul>
 
        </nav>
      </div>
       
      <ProductList products={products} />
 
      <div className="container pb-5">
        <nav>
          <ul className="pagination justify-content-center">
            {info.prev_page_url ? (
              <li className="page-item">
                <button className="page-link" onClick={handlePreviousPage}>
                  Previous
                </button>
              </li>
            ) : null}
            {info.next_page_url ? (
              <li className="page-item">
                <button className="page-link" onClick={handleNextPage}>
                  Next
                </button>
              </li>
            ) : null}
          </ul>
        </nav>
      </div>
       
    </>
  );
}
 
export default App;
C:\react-js\myreactdev\src\Component\Navbar.js
//C:\react-js\myreactdev\src\Component\Navbar.js
import React from "react";

const Navbar = ({ brand }) => {
  return (
    <nav className="navbar navbar-dark bg-dark">
      <div className="container">
        <a className="navbar-brand text-uppercase" href="/">
          {brand}
        </a>
      </div>
    </nav>
  );
};

export default Navbar;
C:\react-js\myreactdev\src\Component\ProductList.js
//C:\react-js\myreactdev\src\Component\ProductList.js
import React from "react";

const ProductList = ({ products }) => {
  return (
    <div className="container">
      <div className="row">
        {products.map((item, index) => (
          <div key={index} className="col-lg-3 col-md-6 col-sm-12 mb-4">
            <div className="card" style={{ minWidth: "200px" }}>
				<img src={`http://127.0.0.1:8000/storage/${item.image}`} alt="Product list" className="card-img-top" />
              <div className="card-body">
                <h5 className="card-title">{item.name}</h5>
                <hr />
                <p className="card-text">Description: {item.description}</p>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

export default ProductList;
react-js\myreactdev\src\Index.css
//react-js\myreactdev\src\index.css
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
    "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background-color: #000000;
  overflow-x: hidden;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
    monospace;
}
h2 {
	color:#fff;	
}		
react-js\myreactdev\public\index.html
//react-js\myreactdev\public\index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"/>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>
Run C:\react-j\myreactdev>npm start
http://localhost:3000/

Related Post