Pada tulisan ini saya akan membuat series mengenai pemrograman dengan Yii Framework. Series ini akan disusun untuk membuat sebuah program sederhana yang memanfaatkan fitur-fitur umum yang sangat mungkin digunakan di banyak kasus. Tulisan ini akan menggunakan Basic Template Yii2 (yang menurut saya penggunaannya sedikit lebih sulit daripada advance template Yii2).
Secara garis besar (dan mungkin akan bertambah sesuai keperluan yang mungkin terjadi) outline dari seri tulisan ini akan terdiri dari hal berikut.
- Prainstalasi
- Instalasi YiiFramework 2.0
- Login
- Login dengan Database pada Yii2
- Bekerja dengan Gii
- Module pada Yii2
- Layout dasar dan Manipulasinya pada Yii2
- Costum Asset dan Asset Bundle pada Yii2
- Alias pada Yii2
- Bekerja dengan Form
- Timestamp, Blameable, dan Sluggable Behavior pada Yii2
- Menggunakan Rich Text Input CkEditor dan Alternatifnya pada Yii2
- Gridview dan Listview
- SEO Friendly Url dengan slug
- Scenario pada Model Yii2
- Retrieve data pada Yii2
- Relasi Database pada Yii2
- Menggunakan Bootstrap4
- Widget Kartik dan Kartik Gridview
- Select2 dengan Kartik Ekstension
- Dependent Dropdown pada Yii2
- Bekerja dengan Modals
- Membuat Costum Template untuk Gii
- Mengupload File
- Mengupload File dengan Kartik Widget
- Gridview atau Datatables?
- Session dan Cookie pada Yii2
- Menggunakan AdminLTE pada Yii2
- Membuat Themes pada Yii2
- Menggunakan GoogleMaps API pada Yii2
- Menggunakan Socket.io pada Yii2
- Handling Error
- Bekerja dengan AuthClient
- Menggunakan Amazon S3 pada Yii2
- Mengirim Email dengan Swiftmailer pada Yii2
- Middleware pada Yii2
- Mengenal RBAC pada Yii2
- Implementasi RBAC pada Yii2
- Notifikasi Real Time dengan Socket.io pada Yii2
Anda dapat mengunduh dan memantau progress dari series ini lewat repositori Github belajararief-yii2series. Silahkan bintangi (star) untuk dapat lebih mudah memantau perkembangan repositori.
Requirement
Untuk memudahkan anda dalam memahami petunjuk ini, maka beberapa hal yang perlu diperhatikan diantaranya:
- Sistem Operasi yang saya gunakan adalah Windows 10 64bit dengan terminal menggunakan powershell terminal (beberapa command seperti cd dapat berbeda dengan command prompt biasa), namun saya akan berusaha sebisa mungkin mencontohkan perintah pada sistem operasi lain jika memunkinkan.
- Stack yang digunakan adalah Wamp Server (Apache 2.2, MySQL, PHP 7).
- Yii yang digunakan adalah Yii 2.0 dengan catatan jquery yang digunakan bukan jquery3. Beberapa perintah jquery akan berbeda pada jquery3, dan beberapa extensions yang saya gunakan sepertinya belum mendukung jquery3
Modal Bootstrap 4
Modal adalah elemen UI yang muncul di atas aplikasi utama yang biasanya diletakkan pada layer terdepan yang dapat berinteraksi dengan pengguna. Modal secara UX memaksa pengguna untuk menyelesaikan tugas tertentu sebelum kembali pada workflow aplikasi tanpa harus berpindah halaman. Penggunaan modal memang menambah interaksi aplikasi dengan pengguna menjadi lebih dinamis. Tujuan dari penggunaan modal dari sisi UX terutama untuk memfokuskan pengguna pada apa isi dari Modal. Agar penggunaan Modal tidak uverused dan mengganggu pengguna maka beberapa UX designer memiliki panduan dalam penggunaan modal, diantaranya:
- The modal window should have a descriptive title (Modal harus memiliki judul)
- The modal window should have a Cancel/Close button (Modal harus memiliki tombol cancel/close)
- Escape key should close the window (Escape Key harus dapat digunakan untuk menutup modal)
- Close when clicking outside the modal window (Modal tertutup ketika pengguna menekan area di luar Modal)
- Add a drop shadow and a transparent background (tambahkan bayangan dan latar belakang yang transparan)
- Don’t make the modal with too much contents in it. This is confusing (Jangan menambahkan konten yang tidak fokus dan terlalu banyak pada modal)
- Avoid Modal on top Modal, it's not consistent, it's not focused, and it's overly complex (Hindari modal di atas modal, karena itu tidak konsisten, tidak fokus, dan terlalu kompleks)
Dan untungnya Modal pada Bootstrap 4 sudah mendukung best practice dalam penggunaan modal sehingga dapat memaksimalkan pengelaman penggunaan aplikasi kita. Selengkapnya tentang Bootstrap Modal dapat anda baca di link ini.
Eksekusi Modal
Yii2 hadir secara default dengan Bootstrap 3. Namun pada series kita kali ini kita telah mengupgrade aplikasi kita untuk menggunakan Bootstrap 4. Modal merupakan salah satu komponen pada Bootstrap yang akan kita gunakan pada aplikasi kita.
Untuk menggunakan modal pada view maka kita dapat menggunakan kode berikut.
use yii\bootstrap\Modal;
Modal::begin([
'title' => 'Hello world',
'toggleButton' => ['label' => 'click me'],
]);
echo 'Say hello...';
Modal::end();
Kode di atas dimulai dengan method begin untuk memulai wrapper Modal, kemudian lengkapi dengan atribut modal kita mulai dari title, dan toggleButton (jika dibutuhkan). Modal diakhiri dengan method End. Semua tampilan baik itu echo PHP maupun HTML yang ada di antara method begin dan End akan menjadi bagian Body dari modal yang kita buat.
Ajax CRUD Modal
Oke saat ini kita akan mengoptimasi laman administrasi blog kita sehingga operasi CRUD dapat berjalan menggunakan Ajax CRUD Modal. Kita akan memodifikasi operasi pada create, update, dan view sehingga bukannya berpindah halaman, aplikasi akan memunculkan modal yang dipanggil dengan Ajax.
Pertama tambahkan template modal pada halaman app\modules\blog\views\index.php
pada module manajemen blog. Kita akan menggunakan modal dengan ukuran large, dengan id myModal dan set tabindex bernilai false (ini diperlukan agar select2 dapat berjalan dengan baik di Modal).
use yii\bootstrap4\Modal;
// ----------------
Modal::begin([
'title' => 'Modal Title',
'options' => [
'id' => 'myModal',
'tabindex' => false // important for Select2 to work properly
],
'size' => 'modal-lg',
]);
echo '...';
Modal::end();
Selanjutnya kita modifikasi tombol create , update dan view sehingga bagian view akan menjadi seperti ini.
<p>
<?= Html::a('Create Blog', ['create'], [
'class' => 'btn btn-success',
'data-toggle'=>"modal",
'data-target'=>"#myModal",
'data-title'=> "Create Blog",
]) ?>
</p>
// -------------------------------
[
'class' => 'kartik\grid\ActionColumn',
'noWrap' => true,
'template' => '{view} {update} {delete}',
'buttons' => [
'view' => function( $url, $model){
return Html::a('<i class="fas fa-eye"></i>', $url, [
'data-toggle'=>"modal",
'data-target'=>"#myModal",
'data-title'=> "View Post #{$model->id}",
]);
},
'update' => function( $url, $model){
return Html::a('<i class="fas fa-pencil-alt"></i>', $url, [
'data-toggle'=>"modal",
'data-target'=>"#myModal",
'data-title'=> "Update Post #{$model->id}",
]);
},
],
],
Selanjutnya tambahkan JS untuk memanggil halaman tersebut via ajax call.
$this->registerJs(<<<JS
// this will generate Modal from crud
$('#myModal').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget)
var modal = $(this)
var title = button.data('title')
var href = button.attr('href')
modal.find('.modal-title').html(title)
modal.find('.modal-body').html('<i class=\"fas fa-spinner fa-spin\"></i>')
$.post(href)
.done(function( data ) {
modal.find('.modal-body').html(data)
});
})
JS
);
Kemudian modifikasi controller pada app\modules\blog\controllers\BlogController.php
agar ketika sebuah halaman dipanggil dengan ajax maka akan melakukan renderAjax dan pada create dan update memberikan tanda keberhasilan menyimpan.
/**
* Displays a single Blog model.
* @param integer $id
* @return mixed
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionView($id)
{
$request = Yii::$app->request;
$render = "render";
// if ajax request comes, overrider render to renderAjax
if($request->isAjax) $render = "renderAjax";
return $this->{$render}('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Blog model.
* If creation is successful, the browser will be redirected to the 'view' page.
* @return mixed
*/
public function actionCreate()
{
$request = Yii::$app->request;
$render = "render";
// if ajax request comes, overrider render to renderAjax
if($request->isAjax) $render = "renderAjax";
$model = new Blog();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
if($request->isAjax) return 1;
return $this->redirect(['view', 'id' => $model->id]);
}elseif($model->load(Yii::$app->request->post()) && !$model->save()){
if($request->isAjax) return 0;
}
return $this->{$render}('create', [
'model' => $model,
]);
}
/**
* Updates an existing Blog model.
* If update is successful, the browser will be redirected to the 'view' page.
* @param integer $id
* @return mixed
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionUpdate($id)
{
$request = Yii::$app->request;
$render = "render";
// if ajax request comes, overrider render to renderAjax
if($request->isAjax) $render = "renderAjax";
$model = $this->findModel($id);
// if user who update different from user who create, scenario set to editByOther
if($model->created_by != Yii::$app->user->identity->id) $model->scenario = 'editByOther';
if ($model->load(Yii::$app->request->post())) {
// prevent user from change title if that article is not created by them
if($model->created_by != Yii::$app->user->identity->id) $model->title = $model->oldAttributes['title'];
if($model->save()){
if($request->isAjax) return 1;
return $this->redirect(['view', 'id' => $model->id]);
}else{
if($request->isAjax) return 0;
}
}
return $this->{$render}('update', [
'model' => $model,
]);
}
Terakhir modifikasi app\modules\blog\views\_form.php
agar jika halaman tersebut dipanggil via ajax call maka submit akan menunggu status penyimpanan dari server.
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use dosamigos\ckeditor\CKEditor;
use kartik\select2\Select2;
use yii\helpers\ArrayHelper;
/* @var $this yii\web\View */
/* @var $model app\models\Blog */
/* @var $form yii\widgets\ActiveForm */
?>
<div class="blog-form">
<?php $form = ActiveForm::begin(['id' => $model->formName()]); ?>
<?= $form->field($model, 'title')->textInput(['maxlength' => true, 'disabled' => $model->scenario == 'editByOther' ? true : false]) ?>
<?= $form->field($model, 'category_id')->widget(Select2::classname(), [
'data' => ArrayHelper::map($model->categoryList, 'id', 'name'),
'options' => ['placeholder' => 'Select a category ...'],
'pluginOptions' => [
'allowClear' => true
],
]) ?>
<?= $form->field($model, 'body')->widget(CKEditor::class, [
'options' => ['rows' => 6],
'preset' => 'basic'
]) ?>
<div class="form-group">
<?= Html::submitButton('Save', ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
<?php
// when from ajax request, submit button will lock submit button and hide modal if success
if(Yii::$app->request->isAjax) $this->registerJs(<<<JS
$('form#{$model->formName()}').on('beforeSubmit',function(e)
{
var \$form = $(this);
$.post(
\$form.attr("action"), //serialize Yii2 form
\$form.serialize()
)
.done(function(result){
if(result == 1)
{
$("#myModal").modal('hide'); //hide modal after submit
//$(\$form).trigger("reset"); //reset form to reuse it to input
$.pjax.reload({container:'#kv-grid-demo-pjax'});
}else
{
$("#message").html(result);
}
}).fail(function(){
console.log("server error");
});
return false;
});
JS
);
Demikian tulisan ini, semoga bermanfaat dan Happy Coding!