# Γραμμή φίλτρου: Πρόοδος, σφάλματα και μικρές νίκες

<!--category-- HTMX, ASP.NET, JavaScript -->
<datetime class="hidden">2025-11-10T14:10</datetime>

## Εισαγωγή

Έχω δημιουργήσει μια σωστή γραμμή φίλτρου για τη λίστα blog: γλώσσα, εύρος ημερομηνίας, είδος, και pagination που παραμένει snappy με HTMX.

Κλείνει τώρα, αλλά όπως πάντα, το τελευταίο 20% είναι το πικάντικο κομμάτι: ημερομηνίες, caches, και γιατί αυτό λειτουργεί τοπικά αλλά όχι μετά από μια ανταλλαγή;[Αν θέλετε τη βαθιά κατάδυση με πολλούς κωδικούς και διαγράμματα, δείτε:](/blog/filterbarprogressandissues)

> /blog/filterbar progressandsues

[TOC]

## Θυμηθείτε αυτό το site είναι ένα έργο σε εξέλιξη, αυτό το είδος των πραγμάτων θα συμβεί όταν θα φάτε-σας-own-dogfood!

- TL;DR
- Νέα γραμμή φίλτρου: Γλώσσα + Ταξινόμηση + Εύρος ημερομηνίας
- HTMX μερική swaps κρατήσει τη σελίδα γρήγορη; πίσω / εμπρός εργασίες επειδή πάντα πιέζω την ενημερωμένη URL`/blog/calendar-days`Ημερολόγιο στιγμιότυπα προέρχονται από ένα μικρό
- τελικό σημείο
- Σταθερό: τα όρια ημερομηνίας μειώνονται κατά την αλλαγή γλώσσας/παραγγελίας
- Σταθερό: ημερολόγιο μη αναζωογονητικό μετά τις ανταλλαγές HTMX ή αλλαγές θέματος

## Ο διακομιστής caching τώρα ποικίλλει από όλα τα σχετικά πλήκτρα ερωτήσεων

- Τι λειτουργεί καλά;
- URL-πρώτη συμπεριφορά: Όλες οι αλληλεπιδράσεις ενημερώνουν το URL; μπορείτε να συνδεθείτε βαθιά σε μια κατάσταση φίλτρου`LinkUrl`Pagination διατηρεί τα τρέχοντα φίλτρα (
- είναι ρυθμισμένο στον διακομιστή)

```csharp
// Server: cache and vary for index
[ResponseCache(Duration = 300, VaryByHeader = "hx-request",
  VaryByQueryKeys = new[] { "page", "pageSize", nameof(startDate), nameof(endDate), nameof(language), nameof(orderBy), nameof(orderDir) },
  Location = ResponseCacheLocation.Any)]
[OutputCache(Duration = 3600, VaryByHeaderNames = new[] { "hx-request" },
  VaryByQueryKeys = new[] { nameof(page), nameof(pageSize), nameof(startDate), nameof(endDate), nameof(language), nameof(orderBy), nameof(orderDir) })]
public async Task<IActionResult> Index(int page = 1, int pageSize = 20, DateTime? startDate = null, DateTime? endDate = null,
  string language = MarkdownBaseService.EnglishLanguage, string orderBy = "date", string orderDir = "desc")
{
    var posts = await blogViewService.GetPagedPosts(page, pageSize, language: language, startDate: startDate, endDate: endDate);
    posts.LinkUrl = Url.Action("Index", "Blog", new { startDate, endDate, language, orderBy, orderDir });
    if (Request.IsHtmx()) return PartialView("_BlogSummaryList", posts);
    return View("Index", posts);
}
```

## Flatpickr range defaults to the current quesry values if present and highlights days with posts

### Τα σφάλματα που έφτιαξα (και τα νέα χαρακτηριστικά!)

Ορατότητα και έλεγχος περιεχομένου

- **Η μεγαλύτερη προσθήκη: σωστή διαχείριση μετά την προβολή:**Κρυφές θέσεις`IsHidden`: Τα ταχυδρομεία μπορούν τώρα να σημειωθούν ως κρυφά (
- **σημαία) και δεν εμφανίζεται στις καταχωρήσεις**Προγραμματισμένες εκδόσεις`ScheduledPublishDate`: Posts can have a
- **και εμφανίζονται μόνο μετά από αυτό το χρονικό διάστημα**Καρφιτσωμένες θέσεις`IsPinned`: Θέσεις σημειωμένες με

```csharp
// BlogService now filters appropriately
var now = DateTimeOffset.UtcNow;
postQuery = postQuery.Where(x =>
    !x.IsHidden &&
    (x.ScheduledPublishDate == null || x.ScheduledPublishDate <= now));

// Pinned posts sorted first on page 1
if (isFirstPage)
{
    postQuery = postQuery.OrderByDescending(x => x.IsPinned)
                         .ThenByDescending(x => x.PublishedDate.DateTime);
}
```

### πάντα εμφανίζονται πρώτη στη σελίδα 1 (μεγάλη για ανακοινώσεις)

- **Βελτιώσεις εύρους ημερομηνίας`/blog/date-range`Νέο**τελικό σημείο
- **: Επιστρέφει τις ημερομηνίες min/max σε όλες τις θέσεις (language-aware) έτσι ώστε η επιλογή ημερομηνίας μπορεί να θέσει λογικά όρια**Σαφής βοηθός ετικέτας param`<clear-param>`: Προστέθηκε

```cshtml
<clear-param name="startDate">Clear Date</clear-param>
<clear-param all="true" exclude="language">Clear All Filters</clear-param>
```

### tag helper για να καθαρίσετε εύκολα τις παραμέτρους ερώτημα

- Επιδιορθώνει το σφάλμα
  - Χάνοντας το εύρος της ημερομηνίας κατά την αλλαγή γλώσσας ή παραγγελίας`new URL(window.location.href)`Επιδιόρθωση: Έναρξη από

```js
langSelect.addEventListener('change', async function(){
  const u = new URL(window.location.href);
  u.searchParams.set('language', langSelect.value);
  u.searchParams.set('page','1');
  const [ob,od] = (orderSelect.value||'date_desc').split('_');
  u.searchParams.set('orderBy', ob);
  u.searchParams.set('orderDir', od);
  if(input._flatpickr && input._flatpickr.selectedDates.length===2){
    const [s,e] = input._flatpickr.selectedDates;
    u.searchParams.set('startDate', s.toISOString().substring(0,10));
    u.searchParams.set('endDate',   e.toISOString().substring(0,10));
  }
  applyNavigation(u);
});
```

- Αν το Flatpickr έχει επιλογή, να το επαναλάβετε.
  
  - Το ημερολόγιο δεν αναζωογονεί μετά τις ανταλλαγές HTMX`fp.redraw()`Fix: Καταστροφή/αναδημιουργία Flatpickr σε init, στη συνέχεια, να φέρει στιγμιότυπα για τον ορατό μήνα και κλήση`htmx:afterSwap`.

- ■ ε p i ι p i λ έ ο ν ε p i ε ρ ι λ α β ά ν ο ν τα ι ε p i ι p i λ η ρ ω 1⁄4 έ ν ε ς p i ε ρ ι λ α 1⁄4 έ ν ε ς p i ρ ό σ ω p i ε ς p i ε ρ ι λ α 1⁄4 β ά ν ε ι ς
  
  - Στυλ Dark mode που δεν εφαρμόζονται στο ημερολόγιο`<html class>`Επιδιόρθωση: παρατήρηση`fp.redraw()`και να καλέσετε

## όταν αλλάζει.

```mermaid
sequenceDiagram
  participant User
  participant JS as blog-index.js
  participant HT as HTMX
  participant S as Server

  User->>JS: Change language/order or pick a date range
  JS->>JS: Update URLSearchParams, pushState
  JS->>HT: htmx.ajax('GET', /blog?...)
  HT->>S: GET /blog
  S-->>HT: HTML partial (_BlogSummaryList)
  HT-->>User: Swap #content
```

## Πως μιλάνε τα κομμάτια

HTMX Page Request Detection`pagerequest`Η γραμμή φίλτρου χρησιμοποιεί ένα προσαρμοσμένο

```csharp
public static bool IsPageRequest(this HttpRequest request)
{
    return request.Headers.ContainsKey("pagerequest") &&
           request.Headers["pagerequest"] == "true";
}
```

κεφαλίδα για να βοηθήσει τον διακομιστή να διακρίνει μεταξύ πλήρους φορτίου σελίδας και μερικής ανταλλαγής HTMX:

> **Αυτό επιτρέπει στο χειριστήριο να επιστρέψει μόνο τη μερική προβολή για αιτήματα HTMX και πλήρη προβολή σελίδας για άμεση πλοήγηση.**Σημείωση

## : Το paging tag helper extension και η παράμετρος ερώτημα σαφέστερη Alpine.js συστατικό αξίζουν τη δική τους βαθιά κατάδυση θα τα καλύψω λεπτομερώς σε μια μελλοντική θέση σχετικά με την κατασκευή επαναχρησιμοποιήσιμα συστατικά HTMX/Alpine.

- Ακόμα το κάνω.
- Προεπιλογές γρήγορης ημερομηνίας (Τελευταίες 7/30 ημέρες, Φέτος)
- Τοπικός σπόρος αποθήκευσης για τη γλώσσα

Υποστήριξη πληκτρολογίου στην επιλογή εύρους