WordPress ejemplo paginador con VueJS y WP REST API

4 minutos

WordPress

En el siguiente ejemplo vamos a realizar un paginador en Javascript para WordPress a través de WP REST API, solucionando el problema de obtener más artículos desde el punto de vista del Front-End. De este modo evitaremos el uso de PHP y los navegantes disfrutarán de resultados rápidos.

Para una elaboración rápida se usarnán algunas librerías externas, totalmente opcionales, vinculadas en los ejemplos por medio de CDNs:

  • VueJS para el renderizado y gestión de eventos.
  • Axios a la hora de realizar una petición GET por AJAX.

Quiero agradecer a Valentina Rubane Evseeva por la base del código, sin su aportación no hubiera sido posible el artículo.

Demo

... esperando recibir mas entradas ...

HTML

Dividimos el documento en la sección donde irán apareciendo los artículos, el lugar que mostrará el cargador y el botón para cargar la siguiente página.

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
    <title>Paginador WP REST API</title>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>

<body>
    <div id="app">
        <!-- Bucle de contenido de entrada que se quiere rendirizar -->
        <div v-for="post in posts">
            <a :href="post.link">
                {{ post.title.rendered }}
            </a>
        </div>
        <!-- Fin Bucle -->

        <!-- Loading -->
        <div v-if="loading">
            ... esperando recibir mas entradas ...
        </div>
        <!-- Fin Loading -->

        <!-- Ver mas entradas-->
        <button role="button" @click.prevent="getMorePosts" v-if="isMorePages">
            Más entradas
        </button>
        <!-- Fin ver mas entradas-->
    </div>
</body>

</html>

Javascript

En los comentarios puede ver que hace cada sección, pero en resumidas se realiza una petición y se calcula que elementos del array recibido quiero incluir.

document.addEventListener('DOMContentLoaded', () => {

    // Constantes de WP REST API ENDPOINTS
    const URL_ENDPOINT_POSTS = '/wp-json/wp/v2/posts?per_page=';
    const URL_ENDPOINT_OFFSET = '&offset=';
    const HEADER_TOTAL_POSTS = 'x-wp-total';

    new Vue({
        el: '#app',
        data: {
            // Numero de entradas por "pagina"
            NUM_RESULTS: 5,
            // Numero de primeras entradas que debemos ignorar, ya que WP permite mostrar como maximo 100 entradas en una llamada
            numOffset: 0,
            // Numero de pagina que necesitaremos para hacer calculo
            pag: 1,
            // Numero total de entradas que necesitaremos para hacer calculo
            totalPosts: 0,
            posts: [],
            loading: false
        },
        mounted() {
            // obtenemos primeras entradas al entrar en la pagina
            axios
                // Aqui realmente no necesitamos poner numero de offset
                .get(this.getEndPoint)
                .then(response => {
                    this.posts = response.data;
                    // obtenemos el numero total de entradas, el dato que recibimos es un integro
                    this.totalPosts = response.headers[HEADER_TOTAL_POSTS];
                });
        },
        computed: {
            isMorePages: function() {
                return this.pag * this.NUM_RESULTS / this.totalPosts < 1;
            },
            getEndPoint: function() {
                return `${URL_ENDPOINT_POSTS}${this.NUM_RESULTS}${URL_ENDPOINT_OFFSET}${this.numOffset}`;
            }
        },
        methods: {
            // Optenemos mas entradas y las añadimos a las entradas que hemos obtenido al entrar en la pagina
            getMorePosts: function() {
                // sumamos 1 a pag con cada click
                this.pag += 1;
                // sumamos numero de resultados que hemos establicido y cuya suma ignaremos con cada click
                this.numOffset += this.NUM_RESULTS;
                this.loading = true;
                axios.get(this.getEndPoint)
                    .then(response => {
                        // sumamos nuevas entradas a las que hemos obtenido anteriormente
                        this.posts = this.posts.concat(response.data);
                    })
                    .finally(() =>
                        this.loading = false
                    );
            }
        }
    });
});

Ejemplo completo

Todo unido quedaría de la siguiente manera.

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
    <title>Paginador WP REST API</title>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>

<body>
    <div id="app">
        <!-- Bucle de contenido de entrada que se quiere rendirizar -->
        <div v-for="post in posts">
            <a :href="post.link">
                {{ post.title.rendered }}
            </a>
        </div>
        <!-- Fin Bucle -->

        <!-- Loading -->
        <div v-if="loading">
            ... esperando recibir mas entradas ...
        </div>
        <!-- Fin Loading -->

        <!-- Ver mas entradas-->
        <button role="button" @click.prevent="getMorePosts" v-if="isMorePages">
            Más entradas
        </button>
        <!-- Fin ver mas entradas-->
    </div>
    <script>
      document.addEventListener('DOMContentLoaded', () => {

          // Constantes de WP REST API ENDPOINTS
          const URL_ENDPOINT_POSTS = '/wp-json/wp/v2/posts?per_page=';
          const URL_ENDPOINT_OFFSET = '&offset=';
          const HEADER_TOTAL_POSTS = 'x-wp-total';

          new Vue({
              el: '#app',
              data: {
                  // Numero de entradas por "pagina"
                  NUM_RESULTS: 5,
                  // Numero de primeras entradas que debemos ignorar, ya que WP permite mostrar como maximo 100 entradas en una llamada
                  numOffset: 0,
                  // Numero de pagina que necesitaremos para hacer calculo
                  pag: 1,
                  // Numero total de entradas que necesitaremos para hacer calculo
                  totalPosts: 0,
                  posts: [],
                  loading: false
              },
              mounted() {
                  // obtenemos primeras entradas al entrar en la pagina
                  axios
                      // Aqui realmente no necesitamos poner numero de offset
                      .get(this.getEndPoint)
                      .then(response => {
                          this.posts = response.data;
                          // obtenemos el numero total de entradas, el dato que recibimos es un integro
                          this.totalPosts = response.headers[HEADER_TOTAL_POSTS];
                      });
              },
              computed: {
                  isMorePages: function() {
                      return this.pag * this.NUM_RESULTS / this.totalPosts < 1;
                  },
                  getEndPoint: function() {
                      return `${URL_ENDPOINT_POSTS}${this.NUM_RESULTS}${URL_ENDPOINT_OFFSET}${this.numOffset}`;
                  }
              },
              methods: {
                  // Optenemos mas entradas y las añadimos a las entradas que hemos obtenido al entrar en la pagina
                  getMorePosts: function() {
                      // sumamos 1 a pag con cada click
                      this.pag += 1;
                      // sumamos numero de resultados que hemos establicido y cuya suma ignaremos con cada click
                      this.numOffset += this.NUM_RESULTS;
                      this.loading = true;
                      axios.get(this.getEndPoint)
                          .then(response => {
                              // sumamos nuevas entradas a las que hemos obtenido anteriormente
                              this.posts = this.posts.concat(response.data);
                          })
                          .finally(() =>
                              this.loading = false
                          );
                  }
              }
          });
      });
    </script>
</body>

</html>

Comentarios

{{ comments.length }} comentarios

Nuevo comentario

Nueva replica  {{ formatEllipsisAuthor(replyComment.author) }}

Acepto la política de Protección de Datos.

Escribe el primer comentario

Tal vez también te interese...