How to Differently Style Posts in Particular Categories

How to Differently Style Posts in Particular Categories

Have you ever visited a WordPress website and found that articles in different categories had different styles and designs like different backgrounds, fonts, text colors, …? For example, in a music blog, the articles in the “Blue” category have a dreamy purple background, and the articles in the “Rock” category have a dark color. This is an interesting highlight in the design, making your website more impressive in the eyes of viewers.

Continue reading "How to Differently Style Posts in Particular Categories"

How to Send GET and POST Requests with JavaScript Fetch API

How to Send GET and POST Requests with JavaScript Fetch API

It's a common task for JavaScript developers to send GET and POST requests to retrieve or submit data. There are libraries like Axios that help you do that with beautiful syntax. However, you can achieve the same result with a very similar syntax with Fetch API, which is supported in all modern browsers.

In this post, we'll use the Fetch API to create get() and post() function with a beautiful syntax, much better than the default syntax provided in the Fetch API. We also improve the request performance with a simple caching and we'll take a look at how to use fetch requests with the WordPress REST API. Let's dive in!

JavaScript Fetch API: create GET, POST requests

Why using Fetch API instead of Axios?

Although you can import an external library like Axios to make get and post requests, using the native Fetch API has some benefits:

  • It's native and supported by all modern browsers, no polyfill is needed. You don't have to install an external library and thus, reduce the built file size.
  • It's promise-based, which allows you to use modern async/await syntax for handling asynchronous operations. This makes your code more readable and maintainable.
  • The Fetch API is a web standard, so it's consistent across different browsers. Axios, on the other hand, is a third-party library, and you might need additional configuration or polyfills to ensure consistent behavior across browsers.

Most people love Axios because of its beautiful syntax. But do you know that you can achieve the same thing with just a little code? Let's do that!

Sending Requests with Fetch API

To send a GET request with Fetch API, use the following code:

fetch( 'https://domain.com/path/?param1=value1&param2=value2' )
    .then( response => response.json() )
    .then( response => {
        // Do something with response.
    } );

To send a JavaScript POST request, use the following code:

const params = {
    param1: value1,
    param2: value2; 
};
const options = {
    method: 'POST',
    body: JSON.stringify( params )  
};
fetch( 'https://domain.com/path/', options )
    .then( response => response.json() )
    .then( response => {
        // Do something with response.
    } );

You can see the main difference between GET and POST requests is how the parameters are passed to the fetch call. In most cases, developers expect to pass an object of parameters and send requests in a beautiful syntax like this:

const params = {
    param1: value1,
    param2: value2; 
};

const response = get( url, params );
// or
const response = post( url, params );

To do that, we need some code to transform the original code with fetch to the new syntax.

Creating get and post Functions

Because the codes that send requests are similar between GET and POST, we'll create a common function request to make a request first. And then use it to create get and post functions like this:

const request = ( url, params, method ) => {
    // All logic is here.
};

const get = ( url, params ) => request( url, params, 'GET' );
const post = ( url, params ) => request( url, params, 'POST' );

Now it's time to build the request function.

Note that for each function (get or post), we have different ways to construct parameters: they're in the URL for GET, and in the body for POST. Thanks to URLSearchParams we can transform an object to a query string for the GET request.

Here is the first version:

const request = ( url, params = {}, method = 'GET' ) => {
    let options = {
        method
    };
    if ( 'GET' === method ) {
        url += '?' + ( new URLSearchParams( params ) ).toString();
    } else {
        options.body = JSON.stringify( params );
    }
    
    return fetch( url, options ).then( response => response.json() );
};

const get = ( url, params ) => request( url, params, 'GET' );
const post = ( url, params ) => request( url, params, 'POST' );

The above code returns a promise, and you can use it in your app like this:

get( 'https://domain.com/path', { param1: value1, param2: value2 } )
.then( response => {
    // Do something with response.
} );

You can see it in action on CodeSandbox.

Caching Requests

One problem developers usually need is caching requests, to avoid sending the same request multiple times.

To implement caching, we can create an object to store the data and use it to return the data earlier:

let cache = {};
const request = ( url, params = {}, method = 'GET' ) => {
    // Quick return from cache.
    let cacheKey = JSON.stringify( { url, params, method } );
    if ( cache[ cacheKey ] ) {
        return cache[ cacheKey ];
    }

    let options = {
        method
    };
    if ( 'GET' === method ) {
        url += '?' + ( new URLSearchParams( params ) ).toString();
    } else {
        options.body = JSON.stringify( params );
    }
    
    const result = fetch( url, options ).then( response => response.json() );
    cache[ cacheKey ] = result;

    return result;
};

WordPress REST API

As a WordPress developer, I usually work with the WordPress REST API. While the code above works fine in a general JavaScript app, it needs some changes to work in WordPress.

To send a request to the WordPress API, you need to authenticate the request. Also, the URL for REST requests must contain the WordPress base URL. Here is the updated code:

let cache = {};
const request = ( url, params = {}, method = 'GET' ) => {
    let cacheKey = JSON.stringify( { url, params, method } );
    if ( cache[ cacheKey ] ) {
        return cache[ cacheKey ];
    }

    let options = {
        method,
        headers: { 'X-WP-Nonce': MyApp.nonce }, // Add nonce for WP REST API
    };

    // Setup the rest base URL for requests.
    url = `${ MyApp.restBase }/${ url }`;

    if ( 'GET' === method ) {
        const query = ( new URLSearchParams( params ) ).toString();
        if ( query ) {
            url += MyApp.restBase.includes( '?' ) ? `&${ query }` : `?${ query }`;
        }
    } else {
        options.body = JSON.stringify( params );
    }
    
    const result = fetch( url, options ).then( response => response.json() );
    cache[ cacheKey ] = result;

    return result;
};

To send restBase and nonce to JavaScript, we need to use the wp_localize_script function as follows in your plugin or theme PHP file:

wp_enqueue_script( 'my-app', plugin_dir_url( __FILE__ ) . 'js/app.js', [], '1.0', true );
wp_localize_script( 'my-app', 'MyApp', [
    'restBase' => untrailingslashit( rest_url() ),
    'nonce'    => wp_create_nonce( 'wp_rest' ),
] );

After that, you can make requests like this:

get( 'my-namespace/my-endpoint', { param1: value1, param2: value2 } )
.then( response => {
    // Do something with response.
} );

Conclusion

This post shows you how to make basic GET, POST requests in JavaScript with the Fetch API. It also shows you how to make requests for the WordPress REST API. With little code, we can have a beautiful syntax like in other libraries. You can use this method in your general JavaScript app or in a WordPress plugin. In fact, we use it in our plugins like Meta Box Builder, MB Views, Slim SEO Schema, and Slim SEO Link Manager.

I also wrote an article about modernizing JS code (improving and modernizing a large JavaScript codebase). So if you're interested, you can read it to have a better code.

Happy coding!

How to Create Contributors Lists for Posts

How to Create Contributors Lists for Posts

When creating content, there might be a situation when many users contribute to writing a post. Normally, authors will list their names as contributors. But if you do it manually, that may take time. So why don't you try creating a contributors list automatically to save time? To do it, we can get the list of users who edited the post in Revision, then display it on the posts page.

Continue reading "How to Create Contributors Lists for Posts"

How to Build a Hotel Booking Website Using Meta Box - P2 - Booking Page in Backend

How to Build a Hotel Booking Website Using Meta Box - P2 - Booking Page in Backend

In the first post of this series, we created a page showing all the hotel room’s information. It normally has a button or several call-to-action areas to go to the booking page which allows your customers to make an order. However, ‘cause some businesses have strong direct channels, they want their sales to make booking orders for their customers as well. Along with that, to have you imagine how to create a booking page in the frontend later (which is in the 3rd post), I made this post to show you how to create one in the backend. That is for internal users only.

Continue reading "How to Build a Hotel Booking Website Using Meta Box - P2 - Booking Page in Backend"

Meta Box Updates - Better Performance for Object Fields, MB Core and New Settings Page

Meta Box Updates - Better Performance for Object Fields, MB Core and New Settings Page

Yesterday, we released several improvements for Meta Box: the new version 5.2.0 with better performance for object fields, a new MB Core extension for Core Bundle, and a totally new settings page for Meta Box AIO. Let's see what's new in these improvements.

Continue reading "Meta Box Updates - Better Performance for Object Fields, MB Core and New Settings Page"