Skip to content

Like.js & Custom REST API Endpoints

Ringkasan

Video ini membahas pembuatan Like.js module untuk handle klik pada like box, serta pembuatan custom REST API endpoints menggunakan register_rest_route(). Kita juga belajar cara programmatically membuat post dengan wp_insert_post() dan mengirim data dari JavaScript ke server.


1. Like.js Module

File: src/modules/Like.js

javascript
import $ from 'jquery';

class Like {
  constructor() {
    this.events();
  }

  events() {
    $(".like-box").on("click", this.ourClickDispatcher.bind(this));
  }

  // Methods
  ourClickDispatcher(e) {
    var currentLikeBox = $(e.target).closest(".like-box");

    if (currentLikeBox.attr("data-exists") == "yes") {
      this.deleteLike(currentLikeBox);
    } else {
      this.createLike(currentLikeBox);
    }
  }

  createLike(currentLikeBox) {
    // Akan diisi nanti
  }

  deleteLike(currentLikeBox) {
    // Akan diisi nanti
  }
}

export default Like;

Import di index.js:

javascript
import Like from './modules/Like';
const like = new Like();

Penjelasan ourClickDispatcher:

KonsepPenjelasan
e.targetElemen yang sebenarnya diklik (bisa icon, angka, atau span)
.closest(".like-box")Naik ke parent/grandparent terdekat yang match selector
.attr("data-exists")Baca atribut HTML secara fresh (bukan cache)
.bind(this)Pertahankan this menunjuk ke class instance

Mengapa .attr() bukan .data()?

javascript
// ❌ jQuery .data() - membaca nilai SEKALI saat page load, lalu di-cache
currentLikeBox.data("exists")

// ✅ jQuery .attr() - selalu membaca nilai TERBARU dari DOM
currentLikeBox.attr("data-exists")

.data() tidak mendeteksi perubahan yang kita buat via .attr(). Untuk toggle like/unlike yang mengubah atribut secara real-time, kita HARUS pakai .attr().


2. Custom REST API Endpoints

Mengapa Custom Endpoint?

Default REST API endpoints (/wp/v2/like) hanya menyediakan CRUD dasar. Fitur like butuh custom logic:

  • User harus login
  • 1 like per user per professor
  • Validasi bahwa ID adalah professor (bukan post/page/campus)

File: inc/like-route.php

php
<?php

add_action('rest_api_init', 'universityLikeRoutes');

function universityLikeRoutes() {
  // Endpoint untuk CREATE like (POST request)
  register_rest_route('university/v1', 'manageLike', array(
    'methods' => 'POST',
    'callback' => 'createLike'
  ));

  // Endpoint untuk DELETE like (DELETE request)
  register_rest_route('university/v1', 'manageLike', array(
    'methods' => 'DELETE',
    'callback' => 'deleteLike'
  ));
}

function createLike($data) {
  // Akan diisi nanti
}

function deleteLike($data) {
  // Akan diisi nanti
}

Include di functions.php:

php
require get_theme_file_path('/inc/like-route.php');

Penjelasan register_rest_route():

ArgumenNilaiPenjelasan
1. Namespace'university/v1'Prefix URL (bisa apa saja)
2. Route'manageLike'Nama endpoint
3. Optionsarray(...)Methods + callback

URL yang Dihasilkan:

POST   /wp-json/university/v1/manageLike  →  createLike()
DELETE /wp-json/university/v1/manageLike  →  deleteLike()

Dua endpoint yang sama URL-nya tapi berbeda method (POST vs DELETE) → WordPress route ke callback yang berbeda.


3. JavaScript AJAX Request

Create Like:

javascript
createLike(currentLikeBox) {
  $.ajax({
    beforeSend: (xhr) => {
      xhr.setRequestHeader('X-WP-Nonce', universityData.nonce);
    },
    url: universityData.root_url + '/wp-json/university/v1/manageLike',
    type: 'POST',
    data: {
      professorId: currentLikeBox.data("professor")
    },
    success: (response) => {
      // Real-time update — dibahas di file berikutnya
      console.log(response);
    },
    error: (response) => {
      console.log(response);
    }
  });
}

Delete Like:

javascript
deleteLike(currentLikeBox) {
  $.ajax({
    beforeSend: (xhr) => {
      xhr.setRequestHeader('X-WP-Nonce', universityData.nonce);
    },
    url: universityData.root_url + '/wp-json/university/v1/manageLike',
    type: 'DELETE',
    data: {
      like: currentLikeBox.attr("data-like")
    },
    success: (response) => {
      console.log(response);
    },
    error: (response) => {
      console.log(response);
    }
  });
}

4. Programmatically Create a Post: wp_insert_post()

File: inc/like-route.php — Fungsi createLike:

php
function createLike($data) {
  if (is_user_logged_in()) {
    $professor = sanitize_text_field($data['professorId']);

    return wp_insert_post(array(
      'post_type' => 'like',
      'post_status' => 'publish',
      'meta_input' => array(
        'liked_professor_id' => $professor
      )
    ));
  } else {
    die("Only logged in users can create a like.");
  }
}

Penjelasan wp_insert_post():

PropertyNilaiPenjelasan
post_type'like'Jenis post yang dibuat
post_status'publish'Status langsung published (default: draft)
post_titleopsionalTitle (WP auto-generate jika kosong)
post_contentopsionalIsi konten
meta_inputarray(...)Custom fields (meta) yang ingin diset

Property meta_input:

php
'meta_input' => array(
  'liked_professor_id' => $professor,    // key => value
  // Bisa tambah field lain jika perlu    
)
  • ACF plugin menggunakan nama yang sama untuk WordPress native meta fields
  • Jadi meta_input bisa langsung mengisi ACF fields!

Return Value:

  • Sukses: ID number dari post baru yang dibuat (misal 142)
  • Gagal: 0 atau WP_Error

Menerima Data dari JavaScript:

php
function createLike($data) {
  // $data berisi semua data yang dikirim dari JavaScript
  // Baik dari property 'data' di $.ajax() maupun query string URL
  $professor = sanitize_text_field($data['professorId']);
}

Penting: Selalu sanitize_text_field() semua input dari client sebelum digunakan!


5. Mengirim Data Professor ID dari JavaScript

Tambah Data Attribute pada HTML:

php
<!-- single-professor.php -->
<span class="like-box" data-professor="<?php the_ID(); ?>" ...>

Akses di JavaScript:

javascript
data: {
  professorId: currentLikeBox.data("professor")
}

Dua Cara Mengirim Data (Equivalent):

javascript
// Cara 1: Property 'data' di $.ajax()
$.ajax({
  url: '...',
  data: { professorId: 123 }
});

// Cara 2: Query string di URL (sama hasilnya)
$.ajax({
  url: '.../manageLike?professorId=123'
});

Cara 1 lebih bersih dan terorganisir.