[Yii Framework] Select Data From Dialog

Control apa yang anda gunakan untuk memasukkan data yang berasa dari master? yah, lebih tepat nya hubungannya 1 to many lah.. Kadang orang-orang menggunakan radio button, tetapi kebanyakan orang menggunakan dropdownlist.. Lalu bagaimana jika data nya sangat banyak sehingga orang pusing kalo pake dropdownlist?? Ada autocomplete kok,, jadi sekalinya kita ngetik, data master akan di filter dengan sendiri nya… hmmm.. pilihan tepat…  Tapi bagaimana jika dalam suatu tabel master memiliki banyak filter untuk memudahkan user?

Misal nih.. kita ingin select wilayah hingga level kelurahan. Untuk memudahkan user, kita ingin agar dapat memilih suatu kelurahan dengan filter berdasarkan provinsi, kabupaten/kota, kecamatan, hingga kelurahan… Tentunya auto complete menjadi kurang cocok dalam kasus ini.. Karena itu solusi yang digunakan biasa nya adalah menggunakan dialog yang menampilkan tabel master, dan dari dialog tersebut kita dapat melakukan filter langsung sesuai field-field yang kita inginkan.. Kemudian setelah menemukan datanya.. kita tinggal memilih data yang ada di dialog dan done… data pun masuk ke dalam field..

Yah, kalo dari penjelasan di atas masih membingungkan.. anda bisa lihat gambaran apa yang ingin saya paparkan dari gambar berikut :

pada form kita menyediaakn fitur untuk user memilih wilayah.. Setelah user memilih “Pilih Wilayah”, maka akan muncul dialog seperti berikut :

User dapat mem-filter data di atas dengan menggunakan filter yang tersedia dan juga dapat melihat dengan pagination.. Jika data nya sudah di temukan, maka user tinggal memilih data tersebut dengan klik link “Pilih” yang ada pada masing-masing row. Kemudian data yang dipilih pun akan masuk ke dalam field :

Okeh, sekarang bagaimana cara membuatnya?

Perttama-tama pada form anda tambahkanlah control seperti berikut :

 <div class="row">
   <?php echo $form->labelEx($model,'wilayah'); ?>
   <?php 
      echo $form->hiddenField($model,'wilayah'); 
      echo CHtml::textField('wilayah_text','',array('size'=>60)); 
      echo Chtml::ajaxLink('Pilih Wilayah',Yii::app()->createUrl('namaController/namaAction'),
         array('update'=>'#wilayahfield'),array("id"=>'wilayah'));
   ?>
   <div id="wilayahfield" style="visibility: hidden;"></div>
   <?php echo $form->error($model,'wilayah'); ?>
 </div>

Pada tampilan di atas, kita membuat membuat sebuah tipe inputan “hidden” untuk nilai “wilayah” dan satu buah textfield dengan nama “wilayah_text”. Kenapa hidden? ini sama seperti kasus auto increment. Kita sebenarnya menginput kode dari suatu tabel master ke dalam database kita, tetapi kita ingin menampilkan pada user bukan kode nya, tapi isi dari tabel tersebut. Untuk itu kita menyediakan sebuah textfield yang tidak akan disimpan guna menampilkan data dari tabel master, dan field wilayah kita buat tipe hidden yang menyimpan kode dari tabel master, dibuat hidden karena user tidak perlu tahu dan agar tak membingungkan user.

Selain itu kita juga menyediakan sebuah ajaxlink yang isinya akan memanggil sebuah action dan dimana ketika sukses hasil dari ajaxlink tersebut akan mengupdate tag html yang memiliki id = “wilayahfield”.

Kemudian setelah membuat itu pada form, kita kemudian membuat action pada suatu controller yang akan berjalan ketika di request setelah memilih tombol ajaxlink di atas.. Jadi pada controller anda masukkan code berikut :

public function actionNamaaction()
{
  $model=new Demography('search');
  $model->unsetAttributes(); // clear any default values
  if(isset($_GET['Demography']))
     $model->attributes=$_GET['Demography'];
   $this->renderPartial('getwilayah',array(
      'model'=>$model,
   ),false,true);

   Yii::app()->end();
 }

Kemudian pada view, buat sebuah file getwilayah.php lalu buat code berikut

<?php
 $this->beginWidget('zii.widgets.jui.CJuiDialog', array(
   'id' => 'bandsdialog3',
   'options' => array(
   'autoOpen' => true,
   'title' => 'Pilih Wilayah',
   'modal' => false,
   'width' => '600',
   ))
 );
 $this->widget('zii.widgets.grid.CGridView', array(
   'id'=>'user-grid',
   'dataProvider'=>$model->search(),
   'filter'=>$model,
   'columns'=>array(
       'propinsi',
       'kota',
       'kecamatan',
       'kelurahan',
       'kodepos',
        array(
           'header'=>'Pilih',
           'type'=>'raw',
           'value'=>'CHtml::link("Pilih","",array(
               "onClick"=>CHtml::ajax(array(
               "url"=>Yii::app()->createUrl("namaController/selectwilayah",array("id"=>$data->primaryKey)),
               "dataType"=>"json",
               "success"=>"function(data){
                     $(\"#Namamodel_wilayah\").val(data.satu);
                     $(\"#wilayah_text\").val(data.dua);
                     $(\"#bandsdialog3\").remove();
                }")
            ),"id"=>"child".$data->primaryKey,"style"=>"cursor:pointer;"))',
         ),
       ),
  ));
  $this->endWidget('zii.widgets.jui.CJuiDialog');
 ?>

Okeh, kode di atas akan menampilkan cgridview dimana dapat kita lakukan filter, pagination, juga dapat kita pilih nilainya.. Cara memilih nilainya sendiri juga menggunakan AJAX.. disana kita memanggil sebuah action dari sebuah controller dimana memiliki sebuah parameter dengan primary key data yang telah terpilih.. kemudian setelah sukses dijalankan, AJAX terssebut akan mengupdata field dengan id “Namamodel_wilayah”, “wilayah_text” dan menghapus “bandsdialog3”.

Nah, sekarang kita tinggal membuat action yang di request oleh ajax di atas… Untuk itu pada controller buatlah sebuah action seperti berikut :

public function actionSelectdemografi($id)
 {
   $satu='';
   $dua='';

    $model=Namamodel::model()->findByPk($id);
    $satu=$model->primaryKey;
    $dua=$model->propinsi.' - '.$model->kota.' - '.$model->kecamatan.' - '.$model->kelurahan;
    echo CJSON::encode(array
    (
       'satu'=>$satu,
       'dua'=>$dua,
    ));
    Yii::app()->end();
 }

Kode di atas akan mengembalikan 2 buah nilai, yang pertama nilai isi dari tabel wilayah dan yang kedua mengembalikan primary key…

 

Selesai…

Selamat mencoba… Semoga membantu… 😀

[Yii Framework] AJAX (Dependent Dropdownlist) in Multi Value / Grid Form

Biasanya kita menggunakan extension Jappendo untuk mengatasi masalah input one to many atau penginputan banyak data sekaligus.. Selama menggunakan JAppendo, kesulitan saya adalah ketika ingin menerapkan AJAX pada masing-masing inputan yang ada. Sebagai contoh adalah masalah penerapan dependent dropdownlist seperti gambar berikut :

Saya memiliki tabel provinsi dan tabel kabupaten/kota. Inputan di atas bisa saya modifikasi ingin menginput 5 row, 7 row, dll pokoknya bisa saya tambah dan kurangi.. Jika di jappendo kita sudah bisa membuat hal tersebut tentunya.. Tapi permasalahannya adalah jumlah kabupaten di Indonesia adalah ratusan. Sehingga saya ingin ketika saya memilih provinsi maka yang tampil pada kolom kabupaten adalah kabupaten dari provinsi yang telah saya pilih saja.. Dan itu harus berlaku untuk semua row yang ada dimana hasilnya nanti adalah seperti gambar berikut :

Anda dapat lihat pada gambar di atas bahwa masing-masing row menampilkan list kabupaten yang berbeda sesuai dari Provinsi yang telah terpilih masing-masing..  Salah satu buktinya adalah dropdownlist yang berbeda-beda panjangnya..

Okeh, itulah permasalahan yang akan kita bahas. Lalu bagaimana cara mengimplementasikannya?? Pada kasus ini, saya harus selingkuh dari Jappendo untuk berpaling pada jqrelcopy. Hal pertama yang harus kita lakukan adalah mendownload terlebih dahulu extension jqrelcopy lalu masukkan ke dalam folder extension seperti biasa. Kemudian mari kita definisikan jqrelcopy pada code tampilan kita :

 <?php 
   $this->widget('ext.jqrelcopy.JQRelcopy',array(
    'id' => 'copylink',
    'removeText' => 'Remove',   // text yang akan muncul pada link remove
    'removeHtmlOptions' => array('style'=>'color:red'),
    'options' => array(
          'copyClass'=>'newcopy',
          'limit'=>5,  // batas row yang diizinkan pada jqrelcopy
          'clearInputs'=>true,
          'excludeSelector'=>'.skipcopy',
     )
   ));
 ?>

 <a id="copylink" href="#" rel=".yangdicopy">Tambah</a>   // link yang akan digunkan untuk menambahkan row baru. Pada code ini terdapat attirbute (rel=".yangdicopy") yang artinya ketika kita meng klik pada link ini maka akan meng copy tampilan class "yangdicopy"

 <div class="row yangdicopy">
 <?php echo CHtml::dropDownList('provinsi[]','',
         CHtml::listData(ModelProvinsi::model()->findAll(),'kode_daerah', 'nama_daerah'),
         array(
          'onChange' => CHtml::ajax(array(
            'type'=>'POST',
            'dataType'=>'json',
             'url'=>array('namaController/namaAction'),  // action yang dipanggil pada perintah AJAX
            'data' => "js:{haha:$(this).val(),idnya:$(this).attr('id')}",  // memberikan nilai provinsi yang dikirim dan mengirim row yang ke berapa yang sedang digunakan
            'success'=>"function(data){
               var kabu='#kabupaten'+data.idnya;  // mendefinisikan row kabupaten mana yang akan di edit. Ini kita definisikan sendiri dengan algoritma yang kita buat
               $(kabu).html(data.satu);  // menginput daftar kabupaten pada row kabupaten yang terpilih
             }",
          )),'empty'=>'Pilih Provinsi',
      )); ?>
     <?php echo CHtml::dropDownList('kabupaten[]','',array(),array('empty'=>'-- Pilih Kabupaten --')); ?>
 </div>

Code di atas adalah code yang tersaji di halaman tampilan kita.  Seblumnya, kenapa kita tidak menggunakan JAppendo pada kasus ini ? karena jappendo tidak membedakan nama control yang ada pada row. Misal row pertama memiliki id=kabupaten, row ke 2 juga id=kabupaten, row ke 7 juga id=kabupaten sehingga kita kesulitan untuk mengidentifikasinya. Sedangkan pada jqrelcopy tidak pada row pertama id=kabupaten, row ke-2 id=kabupaten2, row ke-7 id=kabupaten7. Nah, dengan begitu kita paling tidak bisa tahu mana yang membedakan masing-masing row.

Pada code di atas sendiri kita menangkap id dari control “provinsi” yang sedang kita pilih. Jadi paling tidak kita tahu kita sekrang sedang memilih provinsi, provinsi2, provinsi7 atau yang mana? Sehingga jika provinsi3 yang dipilih, maka perubahan akan terjadi pada control “kabupten3”. Untuk itulah saya mengirimkan nilai id dari control yang kita pilih ke controller. Kemudian kita lakukan pendeteksian nomornya pada controllernya. Berikut controller yang kita panggil dari AJAX sebelumnya :

public function actionKab()
 {
    $satu='';
    $idnya='';
    if(isset($_POST['haha']))
    {
       $datanya=ModelKabupaten::model()->findAllByAttributes(array('kode_provinsi'=>$_POST['haha'])); // memanggil semua list kabuaten yang dimiliki provinsi yang telah dipilih
       $list=CHtml::listData($datanya,'kode_kab','nama_kab');

       foreach($list as $value=>$name) // menginput semua kabupaten yang telah terpilih untuk dimasukkan ke sebuah nilai
       {
          $satu.=CHtml::tag('option',
             array('value'=>$value),CHtml::encode($name),true);
       }
    }
    if(isset($_POST['idnya']))
    {
       if(strlen($_POST['idnya'])>8)
       {
          $idnya=substr($_POST['idnya'],8); // mengambil angka yang ada pada control yang telah kita pilih. Nama dari id yang dikirim nantinya adalah provinsi/provinsi1/provinsi3/prorinsi100. Kita ingin mengambil nilai yang ada di belakang kata provinsi saja. Maka dari itu kita substring dengan start mulai dari huruf ke-8. Yang artinya kita akan mendapatkan angkanya saja..
      }
      else
      {
          $idnya='';
      }
    }

    echo CJSON::encode(array // mengkonversi nilai yang sudah ada ke dalam format JSON
    (
       'satu'=>$satu,
       'idnya'=>$idnya,
    ));
    Yii::app()->end();
 }

Yak itulah dia codingnya.. Walau harus di akal-akali terlebih dahulu tapi paling tidak bisa berjalan sesuai keinginan kita..

Selesai.. Selamat mencoba..

Semoga membantu… 🙂

[Yii Framework] Auto Save Data By Time

Anda pernah ng blog di wordpress atau blogspot? yah.. jika anda membuat sebuah postingan baru, maka postingan anda akan selalu disimpan secara otomatis oleh sistem mereka walaupun anda belum menekan tombol save. Nah, bagaimana cara membuatnya pada Yii Framework untuk website anda? Berikut caranya :

Pertama buatlah sebuah tabel beserta genarate model dan operasi CRUD nya pada Yii Framework. Setelah itu pada view anda akan ada tampilan file create.php, view.php, update.php, dan lain-lain.. Karena kita ingin ingin melakukan otomatis penyimpanan berdasarkan waktu, maka pada file “create.php”, tambahkan code berikut :

<script type="text/javascript">
  setInterval(
     function(){
        var statusnya=$("#statuta").val(); // mengetahui status apakah sedang ada fungsi autosave yang sedang berjalan
        if(statusnya!="on")  // jika tidak ada fungsi yang berjalan, maka jalankan fungsi
        {
           $("#btn-save").attr("disabled",true);  // selama fungsi berjalan, user tidak bisa menekan tombol save
           var data1 = $("#Namamodel_data1").val();  // menangkap nilai dari form input
           var data2 = $("#Namamodel_data2").val();
           $.ajax({
              url: "<?php echo Yii::app()->createUrl('namaController/namaAction')?>",  // memanggil sebuah fungsi untuk autosave
              type:"post",
              dataType :"json",
              data:{"data1" : data1,"data2":data2},
              beforeSend: function() {
                    $("#statuta").val("on");
              },
              success : function(data){
                    $("#statuta").val("off");
                    if(data.satu.length > 0){
                       window.location=data.satu;  // jika data berhasil disimpan, maka akan redirect
                    }
                    else{
                       $("#btn-save").attr("disabled",false);
                    }
              },
          });
       }
    }, 
    15000  // operasi auto save dilakukan 15 detik sekali
  );
</script>

Lalu pada form anda akan ada code form seperti berikut :

<?php echo CHtml::hiddenField('statuta','');?>
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
   'enableAjaxValidation'=>true,
)); ?>
    <?php echo CHtml::submitButton('Save',array('id'=>'btn-save')); ?>
    <p class="note">Fields with <span class="required">*</span> are required.</p>
    <?php echo $form->errorSummary($model); ?>
    <table class="nostyle">
       <tbody>
         <tr>
            <td class="va-top"><?php echo $form->labelEx($model,'data1'); ?></td>
            <td><?php echo $form->textArea($model,'data1',array('rows'=>6, 'cols'=>50)); ?>
            <?php echo $form->error($model,'data1'); ?></td>
        </tr>
        <tr>
           <td class="va-top"><?php echo $form->labelEx($model,'data2'); ?></td>
           <td><?php echo $form->textArea($model,'data2',array('rows'=>6, 'cols'=>50)); ?>
           <?php echo $form->error($model,'data2'); ?></td>
        </tr>
      </tbody>
    </table>
<?php $this->endWidget(); ?>
</div>

Penjelasan : Penjelasan code di atas dapat anda lihat pada script tersebut.

Nah, kemudian kita buat sebuah fungsi pada controller yang telah di panggil via AJAX pada code di atas. Pada sebuah controller, buatlah code berikut :

public function actionNamaaction()
{
  $satu='';
  $model=new Namamodel;
 
  $model->data1 = $_POST['data1'];
  $model->data2 = $_POST['data2'];
 
  if($model->save())
  {
      $satu=$this->createUrl('update',array('id'=>$model->id));
  }
 
  echo CJSON::encode(array
  (
     'satu'=>$satu,
  ));
  Yii::app()->end();
}

 

Pada code di atas, kita menyimpan data yang telah kita input pada form sebelumnya. Nah, setelah data sudah disimpan, page akan langsung di redirect halaman “update” untuk data yang telah tersimpan tadi…

 

Selesai.. Selamat mencoba…

Semoga membantu… 🙂

[Yii Framework] Redirect Page With Ajax

Ketika menjalankan ajax, sejauh ini masih tidak dimungkinkan melakukan redirect page secara langsung dari fungsi yang diakses AJAX secara langsung lewat controller. Lalu bagaimana mengatasinya ? Pada controller anda, lemparlah link yang akan menjadi tujuan redirect ke AJAX variabel :

 public function actionNamaaction()
 {
    $satu='';
    $satu=$this->createUrl('update',array('id'=>$model->id)); 
    echo CJSON::encode(array
    (
       'satu'=>$satu,
    ));
    Yii::app()->end();
 }

Penjelasan : kita menyimpan informasi link yang akan dituju ke dalam variabel $satu
Lalu pada ajax, buatlah code seperti berikut :

 $.ajax({
   url: "<?php echo Yii::app()->createUrl('namacontroller/namaaction')?>",
   type:"post",
   dataType :"json",
   success : function(data){
        if(data.satu.length > 0)
        {
           window.location=data.satu;
        }
    },
 });

Pada fungsi di atas, ketika operasi ajax telah sukses dan variabel “satu” panjang nilainya lebih besar dari 0, maka akan di redirect sesuai request pada action yang ada pada controller..

 

Selesai.. Selamat mencoba..

Semoga membantu… 🙂