Advertisement
  1. Code
  2. Coding Fundamentals
  3. AJAX

Membangun Startup Anda: Formulir Ajax Dinamis untuk Penjadwalan

Scroll to top
Read Time: 12 min
This post is part of a series called Building Your Startup With PHP.
Building Your Startup: Preparing for Reminders
Building Your Startup: Sending Reminders

() translation by (you can also view the original English article)

Final product imageFinal product imageFinal product image
What You'll Be Creating

Tutorial ini adalah bagian dari serial Membangun Startup Anda dengan PHP di Envato Tuts+. Dalam seri ini, saya membimbing Anda melalui peluncuran startup dari konsep ke kenyataan menggunakan aplikasi Meeting Planner saya sebagai contoh di kehidupan nyata. Setiap langkah di sepanjang jalan, saya akan merilis kode Meeting Planner sebagai contoh sumber terbuka yang bisa Anda pelajari. Saya juga akan membahas masalah bisnis terkait startup saat mereka muncul.

Perkenalan

Dalam tutorial hari ini, saya akan memandu Anda melalui rangkaian awal perubahan menyeluruh pada antarmuka penjadwalan rapat. Tujuan saya adalah menggunakan Ajax untuk membuat semua aktivitas penjadwalan umum yang mungkin dilakukan tanpa refresh halaman. Beberapa aspek ini ternyata sederhana dan yang lainnya cukup rumit. Dalam episode ini, saya akan fokus pada bagian-bagian yang mudah: bagaimana membangun permintaan UX Ajax pada aplikasi Yii berbasis PHP Anda.

Pada bagian kedua, saya akan membahas hal-hal yang lebih sulit—melakukan debug Ajax dan menginisialisasi ulang widget Bootstrap setelah pemuatan halaman awal. Saya juga akan membagikan bagaimana saya menggunakan konsol pengembang browser Google Chrome untuk membantu saya mengidentifikasi kode yang rusak.

Terus terang, sementara pembaruan awal berjalan dengan baik, saya mengalami banyak rintangan dan kesulitan yang ada saat dimana saya pikir saya mungkin harus menyerah pada tujuan untuk rilis beta.

Anehnya, akan ada jalur kode yang sepertinya membuat saya hampir selesai dan kemudian menemukan hambatan yang tidak dapat diatasi—dan saya harus memulai lagi dengan pendekatan baru. Akhirnya, saya berhasil menyelesaikan penjadwalan penuh melalui Ajax untuk rilis beta.

Ikuti sepanjang hari ini saat saya membimbing Anda melalui bagian inti dari pekerjaan itu.

Jika Anda belum mencoba Meeting Planner, lanjutkan dan jadwalkan pertemuan pertama Anda dengan kemampuan interaktif baru. Saya berpartisipasi dalam thread komentar di bawah ini, jadi katakan pada saya apa yang Anda pikirkan! Anda juga bisa menghubungi saya di Twitter @reifman. Saya sangat tertarik jika Anda ingin menyarankan fitur baru atau topik untuk tutorial masa depan.

Sebagai pengingat, semua kode untuk Meeting Planner ditulis dalam Framework Yii2 untuk PHP. Jika Anda ingin mempelajari lebih lanjut tentang Yii2, lihat seri paralel kami Pemrograman dengan Yii2.

Memperlancar UX Penjadwalan

Tujuan utama saya untuk tahap produk ini adalah untuk menerapkan semua fitur penjadwalan kunci dengan Ajax dan untuk menghilangkan penyegaran halaman yang saat ini diperlukan untuk mengedit subjek, menambahkan peserta, menambahkan waktu tanggal dan tempat dan catatan.

Latar Belakang

Karena saya telah membangun beberapa Ajax ke situs sebelumnya, saya memiliki beberapa gagasan tentang apa yang akan berjalan dengan baik dan apa yang akan sulit.

Bergabunglah dengan saya saat saya melewati elemen awal ajaxifikasi penjadwalan.

Mengedit Subjek Pertemuan

Startups Ajax - The Meeting Subject Panel Loaded via AjaxStartups Ajax - The Meeting Subject Panel Loaded via AjaxStartups Ajax - The Meeting Subject Panel Loaded via Ajax

Saya mulai dengan mengedit panel subjek pertemuan karena terdiri dari beberapa field statis, satu masukan dan satu textarea. Namun, field subjek menggunakan widget jQuery Typeahead. Widget bisa memperumit masalah karena Anda harus bisa menginisialisasi mereka dengan pemikiran Ajax.

Dalam kasus ini, saya mengisi awal formulir yang disembunyikan dan memuat perpustakaan widget bersamaan dengannya. Tidak ada kerumitan nyata untuk itu. Pada episode berikutnya, Anda akan melihat bahwa widget Bootstrap Switch pada panel tanggal dan tempat membuat ini lebih sulit.

Preloading Semua JavaScript

Jadi, untuk menyederhanakan ajaxifikasi setiap panel penjadwalan (peserta, subjek, waktu tanggal, tempat dan catatan), saya akan memuatnya di depan dan memperluas isi awal dari meeting.js.

Saya juga memperluas definisi MeetingAsset.php untuk memasukkan JavaScript lebih banyak:

1
<?php
2
namespace frontend\assets;
3
use yii\web\AssetBundle;
4
5
class MeetingAsset extends AssetBundle
6
{
7
    public $basePath = '@webroot';
8
    public $baseUrl = '@web';
9
    public $css = [
10
      'css/bootstrap-combobox.css',
11
    ];
12
    public $js = [
13
      'js/meeting.js',
14
      'js/meeting_time.js',
15
      'js/jstz.min.js',
16
      'js/bootstrap-combobox.js',
17
      'js/create_place.js',
18
    ];
19
    public $depends = [
20
        'yii\web\YiiAsset',
21
        'yii\bootstrap\BootstrapAsset',
22
    ];
23
}

MeetingAsset dimuat oleh file Meeting view.php:

1
<?php
2
use yii\helpers\BaseHtml;
3
use yii\helpers\Html;
4
use yii\widgets\DetailView;
5
use yii\widgets\ListView;
6
use common\components\MiscHelpers;
7
use frontend\assets\MeetingAsset;
8
MeetingAsset::register($this);

Memuat Panel Subjek

Detail subjek dan pertemuan merupakan bagian parsial _panel_what.php. Di bawah ini, saya mengaturnya untuk disembunyikan saat memuat #editWhat:

1
<?php
2
    if ($model->has_subject || $model->subject == \frontend\models\Meeting::DEFAULT_SUBJECT) {
3
      ?>
4
      <div id="collapseWhat" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingWhat">
5
        <div class="panel-body">
6
          <div id="showWhat">
7
          <?php if (empty($model->message)) {
8
            echo Html::encode($this->title);
9
            // note: required because couldn't prevent extra space

10
          } else {
11
            echo Html::encode($this->title).': '.Html::encode($model->message).'&nbsp;';
12
          } ?>
13
          </div>
14
          <div id="editWhat" class="hidden">
15
            <?= $this->render('_form', [
16
                'model' => $model,
17
                'subjects' =>  $model->defaultSubjectList(),
18
            ]) ?>
19
          </div>
20
        </div>
21
      </div>
22
      <?php
23
    } else {
24
      ?>

Saya mengaitkan tombol edit (dengan ikon pensil) di _panel_what.php untuk memanggil fungsi pengalih showWhat() JavaScript untuk menampilkan atau menyembunyikan formulir pengeditan. Inilah kodenya:

1
<?php
2
        if ($model->isOrganizer() && $model->status <= Meeting::STATUS_CONFIRMED) {
3
          //['update', 'id' => $model->id]

4
            echo Html::a('', 'javascript:void(0);', ['class' => 'btn btn-primary glyphicon glyphicon-pencil',
5
            'title'=>'Edit','onclick'=>'showWhat();']);
6
          }
7
        ?>
8
      

Fungsi showWhat() dari meeting.js ditunjukkan di bawah ini:

1
// show the message at top of what subject panel

2
function showWhat() {
3
  if ($('#showWhat').hasClass( "hidden")) {
4
    $('#showWhat').removeClass("hidden");
5
    $('#editWhat').addClass("hidden");
6
  }else {
7
    $('#showWhat').addClass("hidden");
8
    $('#editWhat').removeClass("hidden");
9
    $('#meeting-subject').select();
10
  }
11
};
12
13
function cancelWhat() {
14
  showWhat();
15
}

Inilah bagian atas /frontend/views/meeting/_form.php yang menyembunyikan dan menampilkannya. Di sinilah field masukan dan textarea muncul:

1
<?php
2
use yii\helpers\Html;
3
use yii\widgets\ActiveForm;
4
use \kartik\typeahead\TypeaheadBasic;
5
use common\components\MiscHelpers;
6
/* @var $this yii\web\View */
7
/* @var $model frontend\models\Meeting */
8
/* @var $form yii\widgets\ActiveForm */
9
?>
10
<div class="meeting-form">
11
    <?php $form = ActiveForm::begin(); ?>
12
        <div class="row">
13
          <div class="col-md-6">
14
    <?php
15
    echo $form->field($model, 'subject')->widget(TypeaheadBasic::classname(), [
16
    'data' => $subjects,
17
    'options' => ['placeholder' => Yii::t('frontend','what\'s the subject of this meeting?'),
18
    'id'=>'meeting-subject',
19
      //'class'=>'input-large form-control'

20
    ],
21
    'pluginOptions' => ['highlight'=>true],
22
]);
23
?>
24
  </div>
25
</div>

Memperbarui Subjek dan Rincian Pertemuan Melalui Ajax

Saat pengguna memperbarui formulir pertemuan, Ajax berikut dipanggil:

1
// meeting subject panel

2
function updateWhat(id) {
3
  // ajax submit subject and message

4
  $.ajax({
5
     url: $('#url_prefix').val()+'/meeting/updatewhat',
6
     data: {id: id,
7
        subject: $('#meeting-subject').val(),
8
        message: $('#meeting-message').val()
9
      },
10
     success: function(data) {
11
       $('#showWhat').text($('#meeting-subject').val());
12
       showWhat();
13
     }
14
  });
15
}

Fungsi actionUpdatewhat ada di dalam MeetingController.php:

1
    public function actionUpdatewhat($id,$subject='',$message='') {
2
      Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
3
      if (!Meeting::isAttendee($id,Yii::$app->user->getId())) {
4
        return false;
5
      }
6
      $m=Meeting::findOne($id);
7
      $m->subject = $subject;
8
      $m->message = $message;
9
      $m->update();
10
      return true;
11
    }

Perhatikan Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; yang mengonfigurasi metode Yii untuk mengembalikan JSON, bukan HTML.

Fungsi Meeting:isAttendee() adalah pemeriksaan otentikasi untuk memastikan pengguna yang login adalah seorang peserta sebelum memperbarui data rapat.

Apa yang Telah Saya Pelajari Sejauh Ini

Seperti yang Anda lihat, dibutuhkan sedikit kode untuk meng-ajax-kan semua potongan ini.

Salah satu tantangannya adalah menjadi manusia yang berusaha beralih di antara begitu banyak file sekaligus dan dua bahasa yang berbeda. PHP dan JavaScript memiliki cara yang berbeda dalam melakukan sesuatu. Misalnya, menggabungkan string dilakukan dengan periode di PHP dan tanda tambah di JavaScript. Beralih cepat antar bahasa terkadang mencoba membangun string parameter kueri dapat menyebabkan kesalahan.

Ada juga kebutuhan akan pemeriksaan keamanan intensif dalam fungsi Ajax berbasis PHP saya. Dalam tutorial hari ini, Anda melihat awal dari ini, tapi saya harus menambahkan pemeriksaan lebih teliti sebelum membuat kodenya sepenuhnya hidup.

Dan akhirnya, saat melangkah, saya mencoba menggunakan kembali notasi dan pendekatan struktural sehingga semua kode memiliki komposisi dan terminologi yang serupa dengannya—walaupun bekerja dengan elemen data yang berbeda.

Mengirimkan Catatan Pertemuan

Startups Ajax - The Meeting Notes Panel Loaded via AjaxStartups Ajax - The Meeting Notes Panel Loaded via AjaxStartups Ajax - The Meeting Notes Panel Loaded via Ajax

Catatan pertemuan juga field textarea statis. Namun, mungkin ada thread yang terus berlanjut yang perlu diperbarui di halaman saat seseorang ditambahkan (misalnya bukan hanya subjek pertemuan tunggal). Dan penting untuk memberi tahu pengguna bahwa kita akan memberi tahu peserta tentang catatan tersebut.

Sebagai contoh, saya telah menghilangkan tombol submit UX dalam penjadwalan sehingga perencanaan cepat dan efisien. Pengguna Meeting Planner yang baru sering bingung dengan hal ini jadi saya telah menambahkan peringatan untuk memberi tahu mereka bahwa kita akan mengurusnya.

Startups Ajax - Meeting Notes Ajax Success AlertStartups Ajax - Meeting Notes Ajax Success AlertStartups Ajax - Meeting Notes Ajax Success Alert

Mengkodekan Notes Melalui Ajax

Pertama, ada _panel.php untuk catatan Pertemuan. Saya membuat peringatan kesalahan tersembunyi yang bisa ditampilkan melalui jQuery sesuai kebutuhan. Saya berencana untuk menyederhanakan dan membakukan ini di masa depan, termasuk mempermudah penggunaan pelokalan untuk pesan.

Pada contoh di bawah ini, kedua noteMessage1 dan noteMessage2 dimuat sebagai tersembunyi.

1
<?php
2
use yii\helpers\Html;
3
use yii\bootstrap\Collapse;
4
?>
5
<div id="noteMessage" class="alert-info alert fade in hidden">
6
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
7
<span id="noteMessage1">
8
<?= Yii::t('frontend',"Thanks for your note. We'll automatically share it with other participants.")?></span>
9
<span id="noteMessage2">
10
<?= Yii::t('frontend','Please be sure to type a note.')?></span>
11
</div>
12
<div class="panel panel-default">
13
  <!-- Default panel contents -->
14
  <div class="panel-heading" role="tab" id="headingNote" >
15
    <div class="row">
16
      <div class="col-lg-10 col-md-10 col-xs-10"><h4 class="meeting-view">
17
        <a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseNote" aria-expanded="true" aria-controls="collapseNote"><?= Yii::t('frontend','Notes') ?></a></h4>
18
        <span class="hint-text"><?= Yii::t('frontend','send a message to others') ?></span>
19
      </div>
20
      <div class="col-lg-2 col-md-2 col-xs-2" >
21
        <div style="float:right;">
22
        <?= Html::a('', 'javascript:void(0);',
23
        ['class' => 'btn btn-primary glyphicon glyphicon-plus',
24
        'title'=>'Edit','onclick'=>'showNote();']); ?>
25
      </div>
26
      </div>
27
    </div>
28
  </div>
29
  <div id="collapseNote" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingNote">
30
    <div class="panel-body nopadding">
31
      <div id="editNote" class="hidden">
32
        <?= $this->render('_form', [
33
            'model' => $model,
34
        ]) ?>
35
      </div>
36
    </div>
37
    <div id ="noteThread" class="nopadding">
38
      <?= $this->render('_thread', [
39
          'model' => $model,
40
          'noteProvider'=>$noteProvider,
41
      ]) ?>
42
  </div>
43
</div>
44
</div>

Inilah jQuery yang mencari catatan kosong, menampilkan kesalahan yang sesuai atau mengirimkan konten melalui Ajax untuk meminta pembaruan thread catatan, dan menampilkan peringatan sukses:

1
function updateNote(id) {
2
  note = $('#meeting-note').val();
3
  if (note =='') {
4
    displayAlert('noteMessage','noteMessage2');
5
    return false;
6
  }
7
  // ajax submit subject and message

8
  $.ajax({
9
     url: $('#url_prefix').val()+'/meeting-note/updatenote',
10
     data: {id: id,
11
      note: note},
12
     success: function(data) {
13
       $('#editNote').addClass("hidden");
14
       $('#meeting-note').val('');
15
       updateNoteThread(id);
16
       displayAlert('noteMessage','noteMessage1');
17
       return true;
18
     }
19
     // to do - error display flash

20
  });
21
}
22
23
function updateNoteThread(id) {
24
  // ajax submit subject and message

25
  $.ajax({
26
     url: $('#url_prefix').val()+'/meeting-note/updatethread',
27
     data: {id: id},
28
     type: 'GET',
29
     success: function(data){
30
        $('#noteThread').html(data); // data['responseText']

31
    },
32
    error: function(error){
33
    }
34
  });
35
}

Salah satu yang harus dilakukan adalah untuk penanganan kesalahan di Ajax. Tidak mudah melakukan ini dan membutuhkan arsitektur yang cukup rinci di mana pun untuk mendukung hal ini—untuk saat ini, saya telah terus maju tanpa menangani kesalahan seperti ini.

Inilah fungsi JavaScript displayAlert() yang saya gunakan kembali dan dibangun di atasnya untuk semua panel dan pesan peringatan mereka:

1
  function displayAlert(alert_id,msg_id) {
2
    // which alert box i.e. which panel alert

3
    switch (alert_id) {
4
      case 'noteMessage':
5
        // which msg to display

6
        switch (msg_id) {
7
          case 'noteMessage1':
8
          $('#noteMessage1').removeClass('hidden'); // will share the note

9
          $('#noteMessage2').addClass('hidden');
10
          $('#noteMessage').removeClass('hidden').addClass('alert-info').removeClass('alert-danger');
11
          break;
12
          case 'noteMessage2':
13
          $('#noteMessage1').addClass('hidden');
14
          $('#noteMessage2').removeClass('hidden'); // no note

15
          $('#noteMessage').removeClass('hidden').removeClass('alert-info').addClass('alert-danger');
16
          break;
17
        }
18
      break;
19
      case 'participantMessage':
20
        // which msg to display

21
        $('#participantMessageTell').addClass('hidden'); // will share the note

22
        $('#participantMessageError').addClass('hidden');
23
        $('#participantMessageOnlyOne').addClass("hidden");
24
        $('#participantMessageNoEmail').addClass("hidden");
25
        switch (msg_id) {
26
          case 'participantMessageTell':
27
          $('#participantMessageTell').removeClass('hidden'); // will share the note

28
          $('#participantMessage').removeClass('hidden').addClass('alert-info').removeClass('alert-danger');
29
          break;
30
          case 'participantMessageError':
31
          $('#participantMessageError').removeClass("hidden");
32
          $('#participantMessage').removeClass("hidden").removeClass('alert-info').addClass('alert-danger');
33
          break;
34
          case 'participantMessageNoEmail':
35
          $('#participantMessageNoEmail').removeClass("hidden");
36
          $('#participantMessage').removeClass("hidden").removeClass('alert-info').addClass('alert-danger');
37
          break;
38
          case 'participantMessageOnlyOne':
39
          $('#participantMessageOnlyOne').removeClass("hidden");
40
          $('#participantMessage').removeClass("hidden").removeClass('alert-info').addClass('alert-danger');
41
          break;
42
        }
43
      break;
44
      case 'placeMessage':
45
        // which msg to display

46
        $('#placeMsg1').addClass('hidden'); // will share the note

47
        $('#placeMsg2').addClass('hidden'); // will share the note

48
        $('#placeMsg3').addClass('hidden'); // will share the note

49
        switch (msg_id) {
50
          case 'placeMsg1':
51
            $('#placeMsg1').removeClass('hidden'); // will share the note

52
            $('#placeMessage').removeClass('hidden').addClass('alert-info').removeClass('alert-danger');
53
          break;
54
          case 'placeMsg2':
55
            $('#placeMsg2').removeClass('hidden'); // will share the note

56
            $('#placeMessage').removeClass('hidden').removeClass('alert-info').addClass('alert-danger');
57
          break;
58
        }
59
      break;
60
      case 'timeMessage':
61
        // which msg to display

62
        $('#timeMsg1').addClass('hidden'); // will share the note

63
        $('#timeMsg2').addClass('hidden'); // will share the note

64
        //$('#timeMsg3').addClass('hidden'); // will share the note

65
        switch (msg_id) {
66
          case 'timeMsg1':
67
            $('#timeMsg1').removeClass('hidden'); // will share the note

68
            $('#timeMessage').removeClass('hidden').addClass('alert-info').removeClass('alert-danger');
69
          break;
70
          case 'timeMsg2':
71
            $('#timeMsg2').removeClass('hidden'); // will share the note

72
            $('#timeMessage').removeClass('hidden').removeClass('alert-info').addClass('alert-danger');
73
          break;
74
        }
75
      break;
76
    }
77
  }

Memperbarui Thread dari Catatan

Saat pengguna mengirimkan catatan baru, actionUpdatethread() dari MeetingNoteController.php dipanggil melalui Ajax. Inilah PHP-nya:

1
public function actionUpdatethread($id) {
2
      Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
3
      $m=Meeting::findOne($id);
4
      $noteProvider = new ActiveDataProvider([
5
          'query' => MeetingNote::find()->where(['meeting_id'=>$id]),
6
          'sort'=> ['defaultOrder' => ['created_at'=>SORT_DESC]],
7
      ]);
8
      $result =  $this->renderPartial('_thread', [
9
          'model' =>$m,
10
          'noteProvider' => $noteProvider,
11
      ]);
12
      return $result;
13
    }

Saya bereksperimen sesekali dengan mengembalikan item konten terakhir (yaitu catatan terbaru) dan memasukkan di atas item sebelumnya. Namun, ini terbukti merepotkan, terutama dengan tanggal dan tempat yang muncul dalam baris tabel.

Untuk saat ini, saya mengganti keseluruhan pembaruan thread dari isi dan mengganti panel penuh melalui Ajax. Ini bagian _thread.php yang memuat semua catatan, termasuk yang baru:

1
<?php
2
use yii\widgets\ListView;
3
use yii\helpers\Html;
4
if ($timeProvider->count>0):
5
?>
6
<table class="table">
7
  <?= ListView::widget([
8
         'dataProvider' => $timeProvider,
9
         'layout' => '{items}',
10
         'itemView' => '_list',
11
     ]) ?>
12
</table>
13
<?php endif; ?>

Saya berharap itu cukup untuk dipelajari dan dicoba hari ini.

Saya benar-benar menghabiskan sekitar lima sampai tujuh hari pengkodean yang panjang termasuk semalaman untuk menyelesaikan semua kode di balik kedua episode ini dan episode yang akan datang. Saya belum pernah melakukan semalaman selama bertahun-tahun. Meski begitu, hasilnya sudah menginspirasi.

Jadi apa selanjutnya?

Saya harap ini sangat membantu untuk melihat dasar-dasar pengembangan Ajax untuk Yii dan PHP. Saya tentu belajar banyak melalui proses ini, dan perubahannya membuat penjadwalan pertemuan sangat cepat dan mudah dari sebelumnya.

Di episode berikutnya, saya akan mengulas fitur yang tersisa menambahkan waktu tanggal dan tempat dan menggunakan alat debugging Browser Google Chrome untuk membantu saya.

Sementara Anda menunggu episode berikutnya, jadwalkan pertemuan pertama Anda dan cobalah fitur penjadwalan Ajax. Juga, saya akan menghargai jika Anda membagikan pengalaman Anda di bawah komentar ini, dan saya selalu tertarik dengan saran Anda. Anda juga bisa menghubungi saya di Twitter @reifman secara langsung.

Rilis pratinjau Meeting Planner sekarang hidup. Tidak apa-apa sekarang untuk membaginya dengan teman dan kolega Anda untuk digunakan.

Akhirnya, saya mulai bereksperimen dengan WeFunder berdasarkan penerapan peraturan crowdfunding SEC yang baru. Anda bisa mengikuti profil kami di sana jika Anda mau. Saya juga akan menulis lebih banyak tentang ini di tutorial masa depan.

Perhatikan tutorial yang akan datang di serial Membangun Startup Anda dengan PHP.

Tautan Terkait

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.