Render Laravel Component via Ajax method

Hôm nay mình chia sẻ với mọi người sử dụng một kỷ thuật một cách linh hoạt hơn, đó là dùng Blade View Component trong Laravel (8,9,10) 

VD: Khi bạn làm việc với một project thường hay sử dụng gọi Ajax rất nhiều, trong các Ajax có trả về một chuổi html để hiển thị ngoài web, ta thường viết html trong php hoặc nối chuổi html trong javascript , rồi append hay load lại thẻ div nào đó

// load html when call ajax
$("#load").html(result);

// append html to id or class
$(".load").append(result)

Ok hôm nay mình sử dụng Blade View Component trong Laravel , cũng giống vậy, nhưng nó linh hoạt hơn nhiều, tại sao mình nói vậy, vì bạn có thể viết code xử lý trong đó, maintain hơn, tuỳ biến , linh động, có thể tái sử dụng lại 

Tiện ích:

+ Ta có thể using model trong view component

+ Gọi các Service Provider trong đây

+ Xử lý các câu lệnh Eloquent

VD: mình có một View Component như sau:

<?php

namespace App\View\Components;

use Illuminate\View\Component;
use App\Repositories\Interfaces\CategoryRepositoryInterface;
use App\Repositories\Interfaces\UserRepositoryInterface;
use App\Repositories\Interfaces\ProductRepositoryInterface;
use Illuminate\Support\Facades\App;
class FormOption extends Component
{

    public $category_id;
    public $categoryRepository;
    public $userRepository;
    public $product_id;
    /**
     * Create a new component instance.
     *
     * @return void
     */
    public function __construct($category_id,CategoryRepositoryInterface $cate, UserRepositoryInterface $userRepository,$product_id=NULL)
    {
        $this->category_id = $category_id;
        $this->categoryRepository = $cate;
        $this->userRepository = $userRepository;
        $this->product_id = $product_id;
    }

    /**
     * Get the view / contents that represent the component.
     *
     * @return \Illuminate\Contracts\View\View|\Closure|string
     */
    public function render()
    {
       $categories = $this->categoryRepository->getCategoryFeature($this->category_id);

       $custom_feature_id = $this->userRepository->get_custom_features_id(Auth()->user()->id);
       
       $category = $this->categoryRepository->find($this->category_id);
       
       $category_custom_feature =  $category->custom_features->find( $custom_feature_id);

       return view('components.form-option', compact('categories','category_custom_feature'));
    }
}

Bạn thấy đoạn code trên mình xử lý hiển thị các option (tính năng) của một sản phẩm , giống như select option vậy đó

Bạn có thể tạo View component bằng cầu lệnh

php artisan make:component FormOption

Nó sẽ tạo cho bạn một class trong App/View/Component/FormOption.php

Đồng thời tạo một Blade trong resources/views/components/form-option.blade.php : Chính vì thế bạn có thể viết html trong file này, giúp chúng ta dễ quản lý code và sau này dễ sửa, maintain hơn

@foreach ($categories as $category)
    <div class="item bg-gray-100 p-2 flex flex-row items-center mb-1">
        <label for="" class="text-sm w-[70%] font-bold">{{ $category->name }}</label>
        <select name="{{ $category->slug }}"
            class="w-[30%] bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
            <option value="">Choose</option>
            @foreach ($category->childrenFeatures()->get() as $value)
                <option value="{{ $value->id }}">{{ $value->name }}</option>
            @endforeach
        </select>
        <span class="delete-element-option text-red-600 p-2 cursor-pointer"><i class="fas fa-times-circle"></i></span>
    </div>
@endforeach


{{-- show user custom feature --}}
@if($category_custom_feature)
    @foreach ($category_custom_feature as $category)
    <div class="item bg-gray-100 p-2 flex flex-row items-center mb-1">
        <label for="" class="text-sm w-[70%] font-bold">{{ $category->name }}</label>
        <select name="{{ $category->slug }}"
            class="w-[30%] bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
            <option value="">Choose</option>
            @foreach ($category->childrenCustomFeatures()->get() as $value)
                <option value="{{ $value->id }}">{{ $value->name }}</option>
            @endforeach
        </select>
        <span class="delete-element-option text-red-600 p-2 cursor-pointer"><i class="fas fa-times-circle"></i></span>
    </div>
    @endforeach
@endif

Vậy làm sao để gọi chúng trong Controller , nó cũng khá đơn giản thôi, bạn chỉ cần using nó vào Controller là được , sử dụng như sau:

<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Category;
use App\Repositories\Interfaces\CategoryRepositoryInterface;
use App\Repositories\Interfaces\UserRepositoryInterface;
use App\Repositories\Interfaces\ProductRepositoryInterface;
use App\Repositories\Interfaces\FeatureRepositoryInterface;
use App\Repositories\Interfaces\CustomFeatureRepositoryInterface;
use App\Http\Requests\CategoryPostRequest;
use App\View\Components\FormFeature;
use App\View\Components\FormOption;
use App\View\Components\FormOptionEdit;
use App\View\Components\SelectOption;

use Illuminate\Support\Facades\Validator;

class CategoryController extends Controller
{
    protected $cateRepo;
    protected $userRepo;
    protected $categories;
    protected $productRepo;
    protected $featureRepo;
    protected $customFeatureRepo;

    public function __construct(
        CategoryRepositoryInterface $cateRepo,
    UserRepositoryInterface $userRepo,
    ProductRepositoryInterface $productRepo,
    FeatureRepositoryInterface $featureRepo,
    CustomFeatureRepositoryInterface $customFeatureRepo
    )
    {
        $this->cateRepo = $cateRepo;
        $this->userRepo = $userRepo;
        $this->categories = $this->cateRepo->getCategory();
        $this->productRepo = $productRepo;
        $this->featureRepo = $featureRepo;
        $this->customFeatureRepo = $customFeatureRepo;
    }
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return view('pages.category.list')->with(array("categories"=>$this->cateRepo->getAllCategory()));
    }


    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function get_category_product_id($id, $product_id=NULL)
    {
        $product = $this->productRepo->find($product_id);
        /* get category , product da chon */
        $category_child_third_id = $product->category_id;//child catetory 03
        $category_child_two_id = $this->cateRepo->getColumn("category_id",$category_child_third_id)->category_id;
        $category_child_one_id = $this->cateRepo->getColumn("category_id",$category_child_two_id)->category_id;

        if($product_id!=NULL && $product && $category_child_one_id==$id):
            $features = $this->featureRepo->getAll()->whereNull('feature_id');
            $custom_features = $this->customFeatureRepo->getAll()->whereNull('custom_feature_id');
          
            $arr_product_features_id = [];
            $arr_product_custom_features_id = [];
            foreach($product->features as $value) $arr_product_features_id[] = $value->id;
            foreach($product->custom_features as $value) $arr_product_custom_features_id[] = $value->id;  
            $component = new FormOptionEdit($features,$custom_features,$arr_product_features_id,$arr_product_custom_features_id,$product_id);
         
            return $component->render();
        elseif($product_id!=NULL && $product):
          
           
             $component = new FormOption($id,$this->cateRepo, $this->userRepo);
            return $component->render(); 
        
        endif;  
    }


}

Bạn chú ý đoạn code trên mình có gọi class FormOption sau đó return render() nó

 $component = new FormOption($id,$this->cateRepo, $this->userRepo);
  return $component->render(); 

Giờ bạn đã đã có một function get_category_product_id thì bạn có thể gọi đến nó thông qua route rồi

    Route::get('categories/{id}/product/{product_id?}',[App\Http\Controllers\Admin\CategoryController::class,'get_category_product_id'])->name('categories.get_category_product_id');

Bạn có thể gõ trên đường dẫn http://localhost/categories/1/product , chính vì thế mà bạn có thể call nó bằng Ajax , lệnh xử dụng call ajax cũng đơn giản mình viết tượng chưng như dưới đây

//*--load form option*/
                let form_options = function(option_id) {
                    $.ajax({
                        method: "GET",
                        url: "/categories/" + option_id,
                        beforeSend: function() {
                            $(".show-loading").show();
                        },
                        success: function(result) {
                            // console.log(result);
                            $(".load-form-option").html(result)
                        },
                        complete: function() {
                            $(".show-loading").hide();
                        }
                    })
                }
                $(".select-form-option").change(function() {
                    let option_id = $(this).val();
                    if (option_id == -1) {
                        $(".load-form-option").html("")
                    } else {
                        form_options(option_id);
                    }
                });

Vậy là xong, nói chung nó cũng khá đơn giản ah. mà mình làm như vậy nó dễ quản lý sao này. Các bạn có thể sử dụng cách này thử nhé

Bài Viết Liên Quan

Messsage

Ủng hộ tôi bằng cách click vào quảng cáo. Để tôi có kinh phí tiếp tục phát triển Website!(Support me by clicking on the ad. Let me have the money to continue developing the Website!)