المقدمة
في پست سابق أريتكم كيف تصنع سحب البحث باستخدام Alpine.js وHTMX ثم أريتكم كيف يمكننا تشغيل "Cross-Site Request Forgery protection" باستخدام AntiforgeryRequestToken في ASP.NET Core مع JavaScript باستخدام HTMX لتطبيق مخزن ثقب دونات. واحدة من القضايا outstanding كانت كيفية تحميل الصفحات
المشكلة
المشكلة كانت أنني كنت أستخدم HTMX AJAX للقيام بتحميل الصفحة التي طلبتها بعد أن قمت باختيار النتيجة من صفحة السحب
selectResult(result) {
htmx.ajax('get', result.url, {
target: '#contentcontainer', // The container to update
swap: 'innerHTML', // Replace the content inside the target
}).then(function() {
history.pushState(null, '', result.url);
window.scrollTo({
top: 0,
behavior: 'smooth'
});
});
المشكلة كانت أنه بينما سيقوم هذا بتحميل الصفحة اليمنى و تحديث الURL المعروض مع واحد جديد , قد مزعج الزر الخلفي . كما أن الصفحة WASN' T حقاً تم تحميلها في التاريخ بصورة صحيحة .
كما هو الحال مع آخر مقالة عن الزر الخلفي للشنينغان هذا شيء أردت إصلاحه
الحل
كما هو الحال في السابق، كان الحل هو أن نترك HTMX يتعامل مع هذا مباشرة. لفعل ذلك قمت بتحديث نموذجي الذي أستخدمه لنتائج البحث.
_typeahead.cshtml
<div x-data="window.mostlylucid.typeahead()" class="relative" id="searchelement" x-on:click.outside="results = []">
@Html.AntiForgeryToken()
<label class="input input-sm bg-neutral-500 bg-opacity-10 input-bordered flex items-center gap-2">
<input
type="text"
x-model="query"
x-on:input.debounce.200ms="search"
x-on:keydown.down.prevent="moveDown"
x-on:keydown.up.prevent="moveUp"
x-on:keydown.enter.prevent="selectHighlighted"
placeholder="Search..."
class="border-0 grow input-sm text-black dark:text-white bg-transparent w-full"/>
<i class="bx bx-search"></i>
</label>
<!-- Dropdown -->
<ul x-show="results.length > 0"
id="searchresults"
class="absolute z-100 my-2 w-full bg-white dark:bg-custom-dark-bg border border-1 text-black dark:text-white border-neutral-600 rounded-lg shadow-lg">
<template x-for="(result, index) in results" :key="result.slug">
<li :class="{
'dark:bg-blue-dark bg-blue-light': index === highlightedIndex,
'dark:hover:bg-blue-dark hover:bg-blue-light': true
}"
class="cursor-pointer text-sm p-2 m-2">
<!-- These are the key changes.-->
<a
x-on:click="selectResult(index)"
@* :href="result.url" *@
:hx-get="result.url"
hx-target="#contentcontainer"
hx-swap="innerHTML"
hx-push-url="true"
x-text="result.title"
>
</a>
<-- End of changes -->
</li>
</template>
</ul>
</div>
سوف ترون أنني الآن أنتج على نحو صحيح الروابط HTMX في هذا بلاك الشيفرة. يسمح لنا باستخدام سلوك HT MX الصحيح.
typeahead.js
لتشغيل هذا في شفرة جاواScript الخلفية خاصتي قمت بإضافة ما يلي إلى طريقة بحثي (مظهرة من الأسفل). this.$nextTick هو بناء ألبين .js الذي يؤجل هذا حتى قام ألبين بإنهاء معالجة النموذج الذي عرضته سابقاً .
ثم أستخدم htmx.process() على عنصر البحث الذي سيضمن أن خصائص HTMX تعمل كما هو متوقع.
.then(data => {
this.results = data;
this.highlightedIndex = -1; // Reset index on new search
this.$nextTick(() => {
htmx.process(document.getElementById('searchresults'));
});
})
typeahead.js search
search() {
if (this.query.length < 2) {
this.results = [];
this.highlightedIndex = -1;
return;
}
let token = document.querySelector('#searchelement input[name="__RequestVerificationToken"]').value;
console.log(token);
fetch(`/api/search/${encodeURIComponent(this.query)}`, { // Fixed the backtick and closing bracket
method: 'GET', // or 'POST' depending on your needs
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': token // Attach the AntiForgery token in the headers
}
})
.then(response => {
if(response.ok){
return response.json();
}
return Promise.reject(response);
})
.then(data => {
this.results = data;
this.highlightedIndex = -1; // Reset index on new search
this.$nextTick(() => {
htmx.process(document.getElementById('searchresults'));
});
})
.catch((response) => {
console.log(response.status, response.statusText);
if(response.status === 400)
{
console.log('Bad request, reloading page to try to fix it.');
window.location.reload();
}
response.json().then((json) => {
console.log(json);
})
console.log("Error fetching search results");
});
}
selectHighlighted() {
if (this.highlightedIndex >= 0 && this.highlightedIndex < this.results.length) {
this.selectResult(this.highlightedIndex);
}
},
selectResult(selectedIndex) {
let links = document.querySelectorAll('#searchresults a');
links[selectedIndex].click();
this.$nextTick(() => {
this.results = []; // Clear the results
this.highlightedIndex = -1; // Reset the highlighted index
this.query = ''; // Clear the query
});
}
هذا يتم اختياره من خلال النقر على الروابط في نتائج البحث.
<a
x-on:click="selectResult(index)"
:hx-get="result.url"
hx-target="#contentcontainer"
hx-swap="innerHTML"
hx-push-url="true"
x-text="result.title"
>
</a>
والذي سيقوم بعد ذلك بتحميل الصفحة و تحديث URL بصورة صحيحة.
لدي أيضاً برمجة في الصندوق الأصلي الذي يسمح لك باستخدام مفاتيح السهم وتدخل .
<label class="input input-sm bg-neutral-500 bg-opacity-10 input-bordered flex items-center gap-2">
<input
type="text"
x-model="query"
x-on:input.debounce.200ms="search"
x-on:keydown.down.prevent="moveDown"
x-on:keydown.up.prevent="moveUp"
x-on:keydown.enter.prevent="selectHighlighted"
placeholder="Search..."
class="border-0 grow input-sm text-black dark:text-white bg-transparent w-full"/>
<i class="bx bx-search"></i>
</label>
ستلاحظون أن هذا يحتوي على كل البرمجة اللازمة لتتمكنوا من الضغط فقط على "إدخال" والانتقال إلى الصفحة المختارة
في الختام
مجرد تحديث سريع لكتابة البحث الموجودة لتحسين تجربتك المستخدمة عند استخدام البحث. مرة أخرى هذا هو مستخدم صغير يواجه التغيير ولكن فقط يحسن تجربته المستخدمة; الذين كمطور للويب هم اهتمامك الأولي M SK2 بجانب الحصول على المال :)).