Kamu pasti pernah melihat sebuah form yang memungkinkan pengguna untuk mengisikan kategori yang ada di dalam sebuah combobox, dan kita memungkinkan untuk memilih sub kategori. Teknik ini disebut chaining combobox, linked combobox, atau dalam bahasa Indonesianya boleh disebut dengan combobox berantai, combobox bertingkat.

Membuat Combobox Bertingkat dengan CakePHP

Sudah sekian lama saya tidak buat tutorial di Jagocoding.com, karena sibuk kerja dan pekerjaan lainnya. Tetapi, walaupun sibuk, saya berusaha untuk menyempatkan waktu untuk mengisi konten di situs tercinta ini. Insya Allah untuk ke depannya saya mulai aktif lagi mengisi konten, tidak hanya mengecek traffict, komentar, dan email dari pengguna Jagocoding.com saja, he he he..

Ok, tutorial berikut ini adalah, yang pasti, selalu, saya sajikan tutorial untuk pengguna CakePHP, Karena CakePHP is The Best PHP Framework, yang mana kita bisa membuat aplikasi sangat rapid/cepat dan bersih (clean) dibandingkan dengan framework lain.

Kamu pasti pernah melihat sebuah form yang memungkinkan pengguna untuk mengisikan kategori yang ada di dalam sebuah combobox, dan kita memungkinkan untuk memilih sub kategori. Teknik ini disebut chaining combobox, linked combobox, atau dalam bahasa Indonesianya boleh disebut dengan combobox berantai, combobox bertingkat. Banyak penamaan yang lain untuk istilah ini. Di dalam tutorial ini, kita akan mempelajari bagaimana cara membuat combobox tersebut dengan menggunakan metode AJAX. Pada tutorial ini kita akan memakai jQuery untuk Javascriptnya dan CakePHP untuk Framework yang akan kita pakai.

Untuk contoh kasus pada tutorial ini, kita akan membuat sebuah combobox berantai untuk memilih kategori yang mempunyai sub kategori, dan sub kategori tersebut mempunyai sub kategori juga.

Yang harus pertama kali dibuat adalah database. Kita akan buat terlebih dahulu sebuah database bernama categories. Copy script berikut ini di SQL editor kamu, kita akan buat table yang berisi data kategori-kategori berantai.

--
-- Struktur dari tabel `categories`
--

CREATE TABLE IF NOT EXISTS `categories` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `category` varchar(30) NOT NULL,
  `parent_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=13 ;

--
-- Dumping data untuk tabel `categories`
--

INSERT INTO `categories` (`id`, `category`, `parent_id`) VALUES
(1, 'Kamera', 0),
(2, 'Komputer', 0),
(3, 'Kamera Pocket', 1),
(4, 'Kamera SLR', 1),
(5, 'Kamera Polaroid', 1),
(6, 'Hardware', 2),
(7, 'Software', 2),
(8, 'Mother Board', 6),
(9, 'Graphic Card/VGA', 6),
(10, 'Hardisk', 6),
(11, 'Microsoft Windows 8', 7),
(12, 'Adobe Photoshop CS6', 7);

 

Ada pertanyaan? Ya, apa itu parent_id? U got the point!

Parent Id digunakan di sini sebagai id kategori yang akan dijadikan induk dari kategori tersebut, sehingga dengan begitu setiap kategori yang mempunyai parent_id yang sama, maka kategori tersebut merupakan kelompok dari kategori yang disebut parent itu. Ketika kita trace, maka Adobe Photoshop adalah sub kategori dari Software, karena Software mempunyai id = 7, dan software adalah sub kategori dari komputer, yaitu mempunyai id = 2. Jadi, selain kita pelajari mengenai combobox bertingkat, saya akan share juga mengenai apa itu list threaded, yang artinya data berantai/tree, dan sangat erat kaitannya nanti jika diimplementasikan terhadap combobox bertingkat.

Controller

Buatlah sebuah controller baru bernama: CategoriesController yang berisi kode sebagai berikut:

<?php

class CategoriesController extends Controller {

    var $uses = array('Category');
}

 

Controller - Function Index()

Kita akan membutuhkan function untuk menampilkan form. Buatlah sebuah function di dalam CategoriesController yaitu function index(). Buatlah function dengan kode seperti berikut ini:

    function index() {
        $category_options = $this->Category->find('list', array(
            'fields' => array(
                'id', 'category'
            ),
            'conditions' => array(
                'parent_id' => 0
            )
                ));
        $this->set('category_options',$category_options);
    }

 

$this->Category->find('list') adalah kode dari CakePHP yang berfungsi untuk mendapatkan data dari model Category dengan format list yang digunakan untuk combobox. Field id digunakan untuk value dari combobox, dan field category digunakan sebagai display field dari combobox. Conditions yaitu diambil kategori utama, yaitu parent_id = 0.

View - /Categories/index.ctp

Setelah itu, kita buat view untuk function index(), yaitu index.ctp, dan simpan di dalam folder Categories di view. Isi dengan kode berikut ini:

<h2>Pilih Kategori</h2>

<?php
echo $this->Form->create('Category');
echo $this->Form->input('category1', array('id' => 'Category1', 'label' => 'Kategori', 'options' => $category_options, 'empty' => 'Semua Kategori'));
echo $this->Form->input('category2', array('id' => 'Category2', 'label' => 'Sub Kategori 1', 'options' => array(), 'empty' => 'Semua Kategori'));
echo $this->Form->input('category3', array('id' => 'Category3', 'label' => 'Sub Kategori 2', 'options' => array(), 'empty' => 'Semua Kategori'));
echo $this->Form->input('category_id', array('id' => 'CategoryId', 'type' => 'text'));
echo $this->Form->submit('Simpan');
echo $this->Form->end();
?>

Perhatikan element input yang terakhir, yaitu input yang id-nya "CategoryId". Itu dibuat untuk menampung data dan yang akan disubmit oleh form dan disimpan ke database. Sedangkan input field yang lain (Category1, Category2, Category3) itu hanya untuk memanipulasi struktur kategori dengan diimplementasikan menjadi combobox berantai yang kita bahas ini. Jadi, ketiga input field tersebut tidak disimpan ke dalam database.

Sekarang, kita akan buat function-function javascript untuk membuat teknik Combobox bertingkat ini.

Javascript

Sekarang kita akan buat kode javascriptnya, jangan lupa jQuery sudah terinstal dan sudah diload terebih dahulu oleh aplikasi kamu. Jika jQuery sudah ada, silakan tambahkan javascript berikut ini di file index.ctp dan letakkan di atas kode di atas.

<script type="text/javascript">
    function getSubCat(element,parent_id){
        $.ajax({
            url: "<?php echo $this->Html->url(array('action' => 'ajax_get_sub_cat')); ?>",
            data: {parent_id: parent_id},
            success: function(html){
                $(element).html(html);
                getCategoryValue();
            }
        });
    }
    
    function getCategoryValue(){
        if($("#Category3").val()!=''){
            $("#CategoryId").val($("#Category3").val());
        }else if($("#Category2").val()!=''){
            $("#CategoryId").val($("#Category2").val());
        }else if($("#Category1").val()!=''){
            $("#CategoryId").val($("#Category1").val());
        }else{
            $("#CategoryId").val('');
        }
    }
    
    function resetSubCat(element){
        $(element).html('<option value="">Semua Kategori</option>');
    }
</script>

Sekarang saya akan menjelaskan semua function yang ada pada kode di atas.  Kode ini saya buat dinamis, sehingga kita tidak membatasi berapa jumlah sub kategori yang akan digunakan.

function getSubCat()

Function ini saya buat dinamis, sehingga dibuat satu function saja. Jadi, walaupun ada 10 sub kategori, function dibuat cuma satu saja dan dipanggil sebanyak 10 kali. Function ini memanggil file dengan metode ajax, dan mengirimkan variable parent_id sehingga akan mengeluarkan callback berupa html yaitu option-option combobox yang berisi data categories yang parent_id-nya adalah variable yang dikirim tersebut.

function getCategoryValue()

Function ini berfungsi untuk mengeset nilai ke dalam input field category_id yang akan dikirimkan dan dimasukkan ke dalam database. Dicek satu persatu dari setiap combobox sehingga menghasilkan nilai yang sesuai dan dimasukkan ke dalam field $("#CategoryId")

function resetSubCat()

Function ini sengaja saya buat, karena memang ada kejadian ketika sudah muncul sub kategori yang kedua, ketiga, dan seterusnya dan kita mengubah kategori utama, maka nilai dari sub kategori - sub kategori itu belum direset ulang. Jadi, function ini adalah function untuk reset ulang nilai combobox dari sub sub kategori.

 

Setelah function-function javascript dibuat, terapkan function-function javascript tersebut pada setiap element input pada event onchange, sehingga kodenya diubah menjadi seperti berikut ini (perhatikan pada event onchange):

<h2>Pilih Kategori</h2>

<?php
echo $this->Form->create('Category');
echo $this->Form->input('category1', array('id' => 'Category1', 'label' => 'Kategori', 'options' => $category_options, 'empty' => 'Semua Kategori', 'onchange' => 'getSubCat("#Category2", this.value); resetSubCat("#Category2"); resetSubCat("#Category3");'));
echo $this->Form->input('category2', array('id' => 'Category2', 'label' => 'Sub Kategori 1', 'options' => array(), 'empty' => 'Semua Kategori', 'onchange' => 'getSubCat("#Category3", this.value)'));
echo $this->Form->input('category3', array('id' => 'Category3', 'label' => 'Sub Kategori 2', 'options' => array(), 'empty' => 'Semua Kategori','onchange'=>'getCategoryValue()'));
echo $this->Form->input('category_id', array('id' => 'CategoryId', 'type' => 'text'));
echo $this->Form->submit('Simpan');
echo $this->Form->end();
?>

Selanjutnya kita buat controller untuk mendapatkan callback ajax yang sudah kita panggil tadi. Ikuti terus, hanya di Jagocoding.com, hehe..

Controller - Function ajax_get_sub_cat()

Buatlah function baru pada controller CategoriesController dengan nama function ajax_get_sub_cat(). Selengkapnya di bawah ini:

    function ajax_get_sub_cat(){
        $this->layout = 'ajax';
        $category_options = $this->Category->find('all', array(
            'fields' => array(
                'id', 'category'
            ),
            'conditions' => array(
                'parent_id' => $this->params['url']['parent_id']
            )
                ));
        $this->set('category_options',$category_options);        
    }

Seperti yang sudah kita bahas di atas, function akan mengambil variable berupa variable request url yang didefinisikan di file view yaitu variable parent_id, yang akan menjadi conditions untuk menampilkan data categories.

Ok, selanjutnya kita buat file view untuk function ini.

View - /Categories/ajax_get_sub_cat.ctp

Sederhana, file ini kita buat dan masukkan kode di bawah ini:

<option value="">Semua Kategori</option>
<?php foreach ($category_options as $c): ?>
    <option value="<?php echo $c['Category']['id']; ?>"><?php echo $c['Category']['category']; ?></option>
<?php endforeach; ?>

 

Okee oke saya tahu sebagian ada yang malas membaca dari awal, hehe..

Ya udah, karena saya termasuk salah satu orang paling baik sedunia, jadi saya kasih deh kode lengkapnya dan (bahkan) source codenya. Baik kan? Tapi kamu harus tetep baca, karena membaca adalah salah satu kunci dari kecerdasan.

 


Controller - CategoriesController.php

<?php

class CategoriesController extends Controller {

    var $uses = array('Category');
    function index() {
        $category_options = $this->Category->find('list', array(
            'fields' => array(
                'id', 'category'
            ),
            'conditions' => array(
                'parent_id' => 0
            )
                ));
        $this->set('category_options',$category_options);
    }
    
    function ajax_get_sub_cat(){
        $this->layout = 'ajax';
        $category_options = $this->Category->find('all', array(
            'fields' => array(
                'id', 'category'
            ),
            'conditions' => array(
                'parent_id' => $this->params['url']['parent_id']
            )
                ));
        $this->set('category_options',$category_options);        
    }

}

View - /Categories/index.ctp

<?php echo $this->Html->script('jquery-1.9.1.min'); ?>
<script type="text/javascript">
    function getSubCat(element,parent_id){
        $.ajax({
            url: "<?php echo $this->Html->url(array('action' => 'ajax_get_sub_cat')); ?>",
            data: {parent_id: parent_id},
            success: function(html){
                $(element).html(html);
                getCategoryValue();
            }
        });
    }
    
    function getCategoryValue(){
        if($("#Category3").val()!=''){
            $("#CategoryId").val($("#Category3").val());
        }else if($("#Category2").val()!=''){
            $("#CategoryId").val($("#Category2").val());
        }else if($("#Category1").val()!=''){
            $("#CategoryId").val($("#Category1").val());
        }else{
            $("#CategoryId").val('');
        }
    }
    
    function resetSubCat(element){
        $(element).html('<option value="">Semua Kategori</option>');
    }
</script>

<h2>Pilih Kategori</h2>

<?php
echo $this->Form->create('Category');
echo $this->Form->input('category1', array('id' => 'Category1', 'label' => 'Kategori', 'options' => $category_options, 'empty' => 'Semua Kategori', 'onchange' => 'getSubCat("#Category2", this.value); resetSubCat("#Category2"); resetSubCat("#Category3");'));
echo $this->Form->input('category2', array('id' => 'Category2', 'label' => 'Sub Kategori 1', 'options' => array(), 'empty' => 'Semua Kategori', 'onchange' => 'getSubCat("#Category3", this.value)'));
echo $this->Form->input('category3', array('id' => 'Category3', 'label' => 'Sub Kategori 2', 'options' => array(), 'empty' => 'Semua Kategori','onchange'=>'getCategoryValue()'));
echo $this->Form->input('category_id', array('id' => 'CategoryId', 'type' => 'text'));
echo $this->Form->submit('Simpan');
echo $this->Form->end();
?>

View - /Categories/ajax_get_sub_cat.ctp

<option value="">Semua Kategori</option>
<?php foreach ($category_options as $c): ?>
    <option value="<?php echo $c['Category']['id']; ?>"><?php echo $c['Category']['category']; ?></option>
<?php endforeach; ?>

 

Ok, tutorial selesai. Selamat belajar ya, jangan lupa jika ada pertanyaan, silakan komentar saja di bawah

Stand By With Me, 
cheyuz@jagocoding.com

 

About Author

Cecep Yusuf

Hi, my name is Cecep Yusuf. However, in the virtual world I am more likely to use the name Cheyuz, which is an abbreviation of two words "Cecep" and "Yusuf". I am founder of Jagocoding.com, u can view more of me in Cheyuz.com


Comment & Discussions

  • Assalamu'alaikum Kang Mau tanya nih, saya udah nyaman bgt kerja pake cakePhp Tapi saat udh develop dengan aplikasi yg mulai kompleks ko saya rasa webnya agak lambat ya. Saya udh set debug jadi 0, recursive -1, field saat query database saya ngga set *(all), tapi masih aja lambat ya. Saya baca baca ada yang ngebahas memory cache, query cache, sama view cache. Tapi itu gmana ya saya ga ngerti ?. Soalnya web ini cepet bgt :) Dari yang saya sebutkan diatas, ada lagi ngga tips buat optimasi cakephp, terus memory cache di cakephp kaya gmana ya ? Thanks :)

  • Iya mas dari segi ORM sudah saya optimasi, dan di cake 2.3.x saya rasa belum pernah pake $uses, Hhhee :p <br> Tapi saya penasaran di MemoryCache, saya liat disini http://phpmaster.com/speeding-up-your-cakephp-websites/ dan http://www.dereuromark.de/2012/02/13/what-really-speeds-up-your-cakephp-app/ , untuk yang lainnya ngerti tinggal memori cache itu. Tapi boleh share ngga optimasi ORM yang biasa gunakan.

  • Ida Yani (Guest)
    maaf gan ane mau nanya, ane punya 2 combobox, 1 combobox kelas yang ke dua jurusan dan 1 textbox tarif tapi belum terkoneksi ke database misal kita pilih combo box 1 dan 2 maka muncul data harga ditextbox gimana ya gan mohon pencerahannya ^^

  • terima kasih untuk artikel bagusnya..

    menurut saya tabel kategori masih belum dapat dikatakan normal dikarenakan terdapat fungsi

    id menentukan category dan parent_id dan parent_id menentukan category
    ini dikenal dengan adanya ketergantungan transitiv.

    sebaiknya dibuat menjadi 3 tabel dengan struktur
    kategory(id,category)
    sub_category(id,sub_category,id_kategori)
    sub_category2(id,sub_category2,id_sub_category)

    maka datanya akan lebih bagus.
    jika melihat dari struktur tabel categories dari mas Cecep, akan timbul pertanyaan
    "bagaimana cara menambahkan data kategori master ? "

    CMIIW,,

  • pass di klik "simpan" data nya udah disave ke database atau belum? kalau belum, gimana caranya biar bisa di input ke database... makasih~

  • Please LOGIN before if you want to give the comment.