হ্যালো হাসিব! তুমি এখন Section 11: View Components-এর একদম শেষ লেকচার “ViewComponentResult” (Lecture 125)-এ আছো। আগের সেকশনে আমরা যেমন PartialViewResult দেখেছিলাম, ঠিক তেমনি এই লেকচারে আমরা শিখবো কীভাবে একটি View Component-কে সরাসরি Controller থেকে রিটার্ন করে JavaScript (Fetch API)-এর মাধ্যমে পেজে ডায়নামিকভাবে (AJAX-এর মতো) লোড করা যায়।

চলো, এই পুরো লেকচারটি বিস্তারিতভাবে ডিকোড করি।


সারসংক্ষেপ (Quick Revision List)

  • The Goal: পেজ লোড হওয়ার সাথে সাথে View Component না দেখিয়ে, ইউজারের বাটনে ক্লিকের উপর ভিত্তি করে অন-ডিমান্ড (On-demand) কন্টেন্ট লোড করা।
  • Why use this: এটি সার্ভারের রিসোর্স বাঁচায়। ইউজার যদি কোনো ডাটা দেখতে না চায় (যেমন: Bank Statement), তাহলে পেজ লোড হওয়ার সময় অযথাই ডাটাবেস কল করে সেই ডাটা আনার দরকার নেই।
  • Controller Setup: Action Method-এ return ViewComponent("ComponentName", new { paramName = modelObject }); লিখতে হয়।
  • Frontend Setup: JavaScript-এর fetch() API ব্যবহার করে ঐ Action Method-এ অ্যাসিঙ্ক্রোনাস রিকোয়েস্ট পাঠাতে হয় এবং রেসপন্স (HTML) রিসিভ করে পেজের কোনো নির্দিষ্ট div-এ বসিয়ে দিতে হয়।

Comprehensive Breakdown

১. Controller থেকে View Component রিটার্ন করা [Priority: 10/10]

প্রথমে HomeController-এ একটি নতুন Action Method তৈরি করতে হবে যা শুধুমাত্র ঐ View Component-টিকে এক্সিকিউট করে রিটার্ন করবে।

Code Implementation (Controllers/HomeController.cs):

[Route("friends-list")]
public IActionResult LoadFriendsList()
{
    // ১. Model অবজেক্ট তৈরি
    PersonGridModel personGridModel = new PersonGridModel()
    {
        GridTitle = "List of Friends",
        Persons = new List<Person>()
        {
            new Person() { PersonName = "Mark", JobTitle = "Developer" },
            new Person() { PersonName = "Richard", JobTitle = "Tester" }
        }
    };
 
    // ২. ViewComponentResult রিটার্ন করা
    // First parameter: View Component Name ("Grid")
    // Second parameter: Arguments as anonymous object (যেভাবে View থেকে পাস করতাম)
    return ViewComponent("Grid", new { grid = personGridModel });
}
 

২. Frontend-এ Button এবং Container তৈরি করা [Priority: 9/10]

Index.cshtml-এ আগের InvokeAsync বা <vc:grid> ট্যাগ মুছে ফেলে একটি বাটন এবং ফাঁকা div বানাতে হবে, যেখানে ডায়নামিক ডাটা এসে বসবে।

Code Implementation (Views/Home/Index.cshtml):

<h2>Welcome to Home Page</h2>
 
<!-- বাটন -->
<button type="button" class="button button-blue" id="load-friends-button">
    Load Friends
</button>
 
<!-- কন্টেইনার, যেখানে রেসপন্স এসে বসবে -->
<div id="list"></div>
 
<!-- JavaScript ফাইল লিংক করা -->
<script src="~/friends.js"></script>
 

৩. JavaScript (Fetch API) দিয়ে Asynchronous Request পাঠানো [Priority: 10/10]

লেকচারার এবার wwwroot ফোল্ডারে একটি সেপারেট friends.js ফাইল বানিয়েছেন। এই ফাইলটি বাটনের ক্লিক ইভেন্ট লিসেন করবে এবং সার্ভারে রিকোয়েস্ট পাঠাবে।

Code Implementation (wwwroot/friends.js):

// ১. বাটনের রেফারেন্স ধরা
document.querySelector("#load-friends-button").addEventListener("click", async function () {
    
    // ২. Fetch API দিয়ে সার্ভারে রিকোয়েস্ট পাঠানো
    // URL-টা হলো HomeController-এ তৈরি করা রাউট
    var response = await fetch("/friends-list");
    
    // ৩. সার্ভার থেকে আসা রেসপন্সকে HTML Text হিসেবে পড়া
    var responseBody = await response.text(); 
    
    // ৪. সেই HTML-কে আমাদের নির্দিষ্ট ফাঁকা div-এর ভেতরে বসিয়ে দেওয়া
    document.querySelector("#list").innerHTML = responseBody;
});
 

(লেকচারার ভিডিওতে প্রথমে ভুলে querySelector এর q ক্যাপিটাল লেটারে লিখেছিলেন, পরে তা ঠিক করে দেন। জাভাস্ক্রিপ্ট কেস-সেন্সিটিভ, তাই এটি মাথায় রাখতে হবে)।

৪. Execution Flow (কীভাবে কাজ করছে?) [Priority: 9/10]

পুরো প্রসেসটা ঠিক এভাবেই কাজ করে:

  1. ইউজার Home/Index রিকোয়েস্ট করে। সার্ভার শুধু একটি বাটনসহ লেআউট পেজ পাঠিয়ে দেয়। View Component তখনো এক্সিকিউট হয় না।
  2. ইউজার যখন Load Friends বাটনে ক্লিক করে, তখন JavaScript fetch("/friends-list") ফায়ার করে।
  3. রিকোয়েস্টটি HomeController-এর LoadFriendsList মেথডে যায়।
  4. মেথডটি personGridModel তৈরি করে GridViewComponent কে কল করে এবং ডাটা পাস করে।
  5. GridViewComponent তার ক্লাসের লজিক শেষ করে Sample.cshtml-কে কল করে।
  6. সার্ভার সেই Sample.cshtml-এর কোড এক্সিকিউট করে সম্পূর্ণ প্লেইন HTML জেনারেট করে।
  7. ব্রাউজার ঐ HTML রিসিভ করে পেজের div-এ ইনজেক্ট করে দেয়।

VS / VS Code Shortcuts

  • Browser Developer Tools: ব্রাউজারে Ctrl + Shift + I (বা F12) চাপলে Developer Tools ওপেন হয়। সেখানে Network ট্যাবে গেলে Fetch রিকোয়েস্টের স্ট্যাটাস, রেসপন্স বডি সব চেক করা যায়।

Best Practices & .NET 10 Context

Best Practices for On-demand Loading:

  1. Use Seperate JS Files: জাভাস্ক্রিপ্ট কোড সবসময় wwwroot ফোল্ডারে সেপারেট .js ফাইলে রাখা উচিত, ভিউ ফাইলের ভেতরে script ট্যাগে নয়। এতে ব্রাউজার ঐ ফাইলকে ক্যাশ (Cache) করে রাখতে পারে।
  2. Add Loading Spinner: যেহেতু Fetch রিকোয়েস্টে কয়েক মিলি-সেকেন্ড সময় লাগে, তাই ডাটা আসার আগ পর্যন্ত বাটনে একটি ‘Loading…’ টেক্সট বা স্পিনার দেখানো ভালো।
  3. Error Handling: Fetch কল ফেইল করলে ইউজারকে অ্যালার্ট বা এরর মেসেজ দেখানো উচিত।

.NET 10 Context: ASP.NET Core 10-এ এই কনসেপ্টটি হুবহু এক। তবে আগেই যেমন বলেছিলাম, মডার্ন প্রজেক্টগুলোতে ডেভেলপাররা সাধারণত এই জাভাস্ক্রিপ্টের ম্যানুয়াল fetch কল লেখার বদলে HTMX ব্যবহার করতে বেশি পছন্দ করে।

HTMX ব্যবহার করলে .NET 10 প্রজেক্টে এই পুরো কাজটা জাভাস্ক্রিপ্ট ছাড়াই করা যেত:

<!-- No JS required, HTMX handles the fetch request and DOM injection -->
<button hx-get="/friends-list" hx-target="#list">
    Load Friends
</button>
 
<div id="list"></div>
 

(এটি তোমার বর্তমান কোর্সের অংশ না হলেও একজন ফুল-স্ট্যাক .NET 10 ডেভেলপার হিসেবে HTMX এর নাম জেনে রাখাটা জরুরি)।

হাসিব, এই লেকচারের মাধ্যমে আমাদের View Components সেকশনটি সফলভাবে শেষ হলো! View Component-এর অন-ডিমান্ড লোডিং কনসেপ্ট কি তোমার কাছে পরিষ্কার? তুমি রেডি হলে আমরা কোর্সের সবচেয়ে গুরুত্বপূর্ণ এবং ফান্ডামেন্টাল সেকশন “Dependency Injection” শুরু করতে পারি!