Search code examples
javascriptnode.jsexpresspug

Express.js Pug.js | Render the same page after fetch POST request with different content


I have a list of article previews that come from a DB and are rendered on the page with a Pug.js mixin.

  each article in articles
     +articlePreview(article.title, article.text, article.imgSrc)

I would like to enable filtering for these previews (sort by title, filter by category etc.), so I'm sending a fetch POST request to an express application. The route makes the appropriate filtering and should render the same page with the filters applied, but the page is not re-rendering.

In pug I have something like this:

        button.filters-btn.filters-title title
            .filters-title-icon
                if (filters.title && filters.title === 'az')
                    span a-z
                else if (filters.title && filters.title === 'za')
                    span z-a
                else 
                    i.arrow.arrow-up 
                    i.arrow.arrow-down
        div(tabindex="0", class="filters-btn filters-category")
            if (filters.category) 
                span= filters.category
                .filters-category-icon
                    button x
            else 
                span category
                .filters-category-icon 
                    i.arrow.arrow-down
            ul(class="filters-category-list")
                li(class=`filters-category-item ${filters.category === 'cooking' ? "filters-category-active" : ''}`) cooking
                li(class=`filters-category-item ${filters.category === 'sport' ? "filters-category-active" : ''}`) sport
                li(class=`filters-category-item ${filters.category === 'travels' ? "filters-category-active" : ''}`) travels
                li(class=`filters-category-item ${filters.category === 'animals' ? "filters-category-active" : ''}`) animals

Clicking on one between .filters-title or one of the elements of the .filters-category-list triggers the fetch call.

In express I simply get the filters from the request, filter the articles and send them back (along with the filters to be shown) via res.render():

app.post("/articles", (req, res) => {
  const articles = [...get data from db and apply filters];
  res.render("../articles/index", {
    title: articles,
    articles,
    filters: req.body.filters,
  })
})

Should I do this all over again without using pug variables and simply create elements in javascript after express has responded? Or there is a way to make the most of Pug.js?


Solution

  • The problem here is you are using fetch to make the POST request. Fetch is used to make an HTTP without navigating (or rendering in your case).

    Instead, use XMLHttpRequest to post the form:

    var xhr = new XMLHttpRequest();
    xhr.open("POST", write_your_uri_here, true);
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.send(JSON.stringify({
        value: value
    }));