Membuat kolom kustom

Sebelum membuat jenis kolom baru, pertimbangkan apakah salah satu metode lain untuk menyesuaikan kolom sesuai dengan kebutuhan Anda. Jika aplikasi Anda perlu menyimpan jenis nilai baru, atau Anda ingin membuat UI baru untuk jenis nilai yang ada, Anda mungkin perlu membuat jenis kolom baru.

Untuk membuat kolom baru, lakukan hal berikut:

  1. Terapkan konstruktor.
  2. Daftarkan kunci JSON dan terapkan fromJson.
  3. Menangani inisialisasi UI dan pemroses peristiwa di blok.
  4. Menangani pelepasan pemroses peristiwa (pelepasan UI ditangani untuk Anda).
  5. Terapkan penanganan nilai.
  6. Tambahkan representasi teks dari nilai kolom Anda, untuk aksesibilitas.
  7. Tambahkan fungsi tambahan seperti:
  8. Konfigurasi aspek tambahan kolom Anda, seperti:

Bagian ini mengasumsikan bahwa Anda telah membaca dan memahami konten dalam Anatomi Kolom.

Untuk contoh kolom kustom, lihat demo Kolom Kustom .

Mengimplementasikan konstruktor

Konstruktor kolom bertanggung jawab untuk menyiapkan nilai awal kolom dan secara opsional menyiapkan validator lokal. Konstruktor kolom kustom dipanggil selama inisialisasi blok sumber, terlepas dari apakah blok sumber ditentukan dalam JSON atau JavaScript. Jadi, kolom kustom tidak memiliki akses ke blok sumber selama pembuatan.

Contoh kode berikut membuat kolom kustom bernama GenericField:

class GenericField extends Blockly.Field {
  constructor(value, validator) {
    super(value, validator);

    this.SERIALIZABLE = true;
  }
}

Tanda tangan metode

Konstruktor kolom biasanya menerima nilai dan validator lokal. Nilai bersifat opsional, dan jika Anda tidak meneruskan nilai (atau Anda meneruskan nilai yang gagal validasi class), nilai default superclass akan digunakan. Untuk class Field default, nilai tersebut adalah null. Jika Anda tidak menginginkan nilai default tersebut, pastikan untuk meneruskan nilai yang sesuai. Parameter validator hanya ada untuk kolom yang dapat diedit dan biasanya ditandai sebagai opsional. Pelajari lebih lanjut validator di dokumen Validator.

Struktur

Logika di dalam konstruktor Anda harus mengikuti alur ini:

  1. Panggil konstruktor super yang diwarisi (semua kolom kustom harus diwarisi dari Blockly.Field atau salah satu subkelasnya) untuk menginisialisasi nilai dengan benar dan menetapkan validator lokal untuk kolom Anda.
  2. Jika kolom Anda dapat diserialisasi, tetapkan properti yang sesuai di konstruktor. Kolom yang dapat diedit harus dapat diserialisasi, dan kolom dapat diedit secara default, jadi sebaiknya Anda menyetel properti ini ke benar kecuali jika Anda tahu bahwa properti tersebut tidak boleh diserialisasi.
  3. Opsional: Terapkan penyesuaian tambahan (misalnya, Kolom label memungkinkan class CSS diteruskan, yang kemudian diterapkan ke teks).

JSON dan pendaftaran

Dalam definisi blok JSON, kolom dideskripsikan oleh string (misalnya, field_number, field_textinput). Blockly mempertahankan peta dari string ini ke objek kolom, dan memanggil fromJson pada objek yang sesuai selama konstruksi.

Panggil Blockly.fieldRegistry.register untuk menambahkan jenis kolom Anda ke peta ini, dengan meneruskan class kolom sebagai argumen kedua:

Blockly.fieldRegistry.register('field_generic', GenericField);

Anda juga perlu menentukan fungsi fromJson. Implementasi Anda harus terlebih dahulu menghapus referensi token pelokalan menggunakan replaceMessageReferences, lalu meneruskan nilai ke konstruktor.

GenericField.fromJson = function(options) {
  const value = Blockly.utils.parsing.replaceMessageReferences(
      options['value']);
  return new CustomFields.GenericField(value);
};

Melakukan inisialisasi

Saat kolom Anda dibuat, kolom tersebut pada dasarnya hanya berisi nilai. Inisialisasi adalah tempat DOM dibangun, model dibangun (jika kolom memiliki model), dan peristiwa terikat.

Tampilan On-Block

Selama inisialisasi, Anda bertanggung jawab untuk membuat apa pun yang akan Anda perlukan untuk tampilan dalam blok kolom.

Default, latar belakang, dan teks

Fungsi initView default membuat elemen rect berwarna terang dan elemen text. Jika Anda ingin kolom memiliki keduanya, ditambah beberapa keuntungan tambahan, panggil fungsi initView superclass sebelum menambahkan elemen DOM lainnya. Jika Anda ingin kolom memiliki salah satu, tetapi tidak kedua elemen ini, Anda dapat menggunakan fungsi createBorderRect_ atau createTextElement_.

Menyesuaikan konstruksi DOM

Jika kolom Anda adalah kolom teks generik (misalnya, Text Input), konstruksi DOM akan ditangani untuk Anda. Jika tidak, Anda harus mengganti fungsi initView untuk membuat elemen DOM yang akan Anda perlukan selama rendering kolom Anda di masa mendatang.

Misalnya, kolom dropdown dapat berisi gambar dan teks. Di initView, elemen ini membuat satu elemen gambar dan satu elemen teks. Kemudian, selama render_ elemen aktif ditampilkan dan elemen lainnya disembunyikan, berdasarkan jenis opsi yang dipilih.

Elemen DOM dapat dibuat menggunakan metode Blockly.utils.dom.createSvgElement, atau menggunakan metode pembuatan DOM tradisional.

Persyaratan tampilan di blok kolom adalah:

  • Semua elemen DOM harus berupa turunan dari fieldGroup_ kolom. Grup kolom dibuat secara otomatis.
  • Semua elemen DOM harus tetap berada di dalam dimensi kolom yang dilaporkan.

Lihat bagian Rendering untuk mengetahui detail selengkapnya tentang cara menyesuaikan dan memperbarui tampilan di blok Anda.

Menambahkan Simbol Teks

Jika ingin menambahkan simbol ke teks kolom (seperti simbol derajat kolom Sudut), Anda dapat menambahkan elemen simbol (biasanya terdapat dalam <tspan>) langsung ke textElement_ kolom.

Peristiwa input

Secara default, kolom mendaftarkan peristiwa tooltip dan peristiwa mousedown (untuk digunakan dalam menampilkan editor). Jika Anda ingin memantau jenis peristiwa lain (misalnya, jika Anda ingin menangani penarikan pada kolom), Anda harus mengganti fungsi bindEvents_ kolom.

bindEvents_() {
  // Call the superclass function to preserve the default behavior as well.
  super.bindEvents_();

  // Then register your own additional event listeners.
  this.mouseDownWrapper_ =
  Blockly.browserEvents.conditionalBind(this.getClickTarget_(), 'mousedown', this,
      function(event) {
        this.originalMouseX_ = event.clientX;
        this.isMouseDown_ = true;
        this.originalValue_ = this.getValue();
        event.stopPropagation();
      }
  );
  this.mouseMoveWrapper_ =
    Blockly.browserEvents.conditionalBind(document, 'mousemove', this,
      function(event) {
        if (!this.isMouseDown_) {
          return;
        }
        var delta = event.clientX - this.originalMouseX_;
        this.setValue(this.originalValue_ + delta);
      }
  );
  this.mouseUpWrapper_ =
    Blockly.browserEvents.conditionalBind(document, 'mouseup', this,
      function(_event) {
        this.isMouseDown_ = false;
      }
  );
}

Untuk mengikat ke peristiwa, Anda umumnya harus menggunakan fungsi Blockly.utils.browserEvents.conditionalBind. Metode pengikatan peristiwa ini memfilter sentuhan sekunder selama penarikan. Jika ingin pengendali Anda berjalan bahkan di tengah penarikan yang sedang berlangsung, Anda dapat menggunakan fungsi Blockly.browserEvents.bind.

Membuang

Jika Anda mendaftarkan pemroses peristiwa kustom di dalam fungsi bindEvents_ kolom, pemroses tersebut harus dibatalkan pendaftarannya di dalam fungsi dispose.

Jika Anda menginisialisasi tampilan kolom dengan benar (dengan menambahkan semua elemen DOM ke fieldGroup_), maka DOM kolom akan dihapus secara otomatis.

Penanganan Nilai

→ Untuk mengetahui informasi tentang nilai kolom vs. teksnya, lihat Anatomi kolom.

Urutan validasi

Diagram alur yang menjelaskan urutan validator dijalankan

Menerapkan validator class

Kolom hanya boleh menerima nilai tertentu. Misalnya, kolom angka hanya boleh menerima angka, kolom warna hanya boleh menerima warna, dll. Hal ini dipastikan melalui class dan validator lokal. Validasi class mengikuti aturan yang sama dengan validator lokal, kecuali bahwa validasi ini juga dijalankan di konstruktor dan, oleh karena itu, tidak boleh mereferensikan blok sumber.

Untuk menerapkan validator class kolom, ganti fungsi doClassValidation_.

doClassValidation_(newValue) {
  if (typeof newValue != 'string') {
    return null;
  }
  return newValue;
};

Menangani nilai yang valid

Jika nilai yang diteruskan ke kolom dengan setValue valid, Anda akan menerima callback doValueUpdate_. Secara default, fungsi doValueUpdate_:

  • Menetapkan properti value_ ke newValue.
  • Menetapkan properti isDirty_ ke true.

Jika Anda hanya perlu menyimpan nilai, dan tidak ingin melakukan penanganan kustom apa pun, Anda tidak perlu mengganti doValueUpdate_.

Jika tidak, Anda dapat melakukan tindakan seperti:

  • Penyimpanan kustom sebesar newValue.
  • Ubah properti lain berdasarkan newValue.
  • Menyimpan apakah nilai saat ini valid atau tidak.

Anda harus mengganti doValueUpdate_:

doValueUpdate_(newValue) {
  super.doValueUpdate_(newValue);
  this.displayValue_ = newValue;
  this.isValueValid_ = true;
}

Menangani nilai tidak valid

Jika nilai yang diteruskan ke kolom dengan setValue tidak valid, Anda akan menerima callback doValueInvalid_. Secara default, fungsi doValueInvalid_ tidak melakukan apa pun. Artinya, secara default, nilai yang tidak valid tidak akan ditampilkan. Artinya, kolom tidak akan dirender ulang karena properti isDirty_ tidak akan ditetapkan.

Jika ingin menampilkan nilai yang tidak valid, Anda harus mengganti doValueInvalid_. Dalam sebagian besar situasi, Anda harus menetapkan properti displayValue_ ke nilai yang tidak valid, menetapkan isDirty_ ke true, dan mengganti render_ untuk tampilan di blok agar diperbarui berdasarkan displayValue_, bukan value_.

doValueInvalid_(newValue) {
  this.displayValue_ = newValue;
  this.isDirty_ = true;
  this.isValueValid_ = false;
}

Nilai multi-bagian

Jika kolom Anda berisi nilai multipart (misalnya, daftar, vektor, objek), Anda mungkin ingin bagian-bagiannya ditangani seperti nilai individual.

doClassValidation_(newValue) {
  if (FieldTurtle.PATTERNS.indexOf(newValue.pattern) == -1) {
    newValue.pattern = null;
  }

  if (FieldTurtle.HATS.indexOf(newValue.hat) == -1) {
    newValue.hat = null;
  }

  if (FieldTurtle.NAMES.indexOf(newValue.turtleName) == -1) {
    newValue.turtleName = null;
  }

  if (!newValue.pattern || !newValue.hat || !newValue.turtleName) {
    this.cachedValidatedValue_ = newValue;
    return null;
  }
  return newValue;
}

Pada contoh di atas, setiap properti newValue divalidasi satu per satu. Kemudian di akhir fungsi doClassValidation_, jika ada properti individual yang tidak valid, nilai akan di-cache ke properti cacheValidatedValue_ sebelum menampilkan null (tidak valid). Meng-cache objek dengan properti yang divalidasi satu per satu memungkinkan fungsi doValueInvalid_ menanganinya secara terpisah, cukup dengan melakukan pemeriksaan !this.cacheValidatedValue_.property, bukan memvalidasi ulang setiap properti satu per satu.

Pola untuk memvalidasi nilai multi-bagian ini juga dapat digunakan di validator lokal, tetapi saat ini tidak ada cara untuk menerapkan pola ini.

isDirty_

isDirty_ adalah tanda yang digunakan dalam fungsi setValue, serta bagian lain dari kolom, untuk mengetahui apakah kolom perlu dirender ulang. Jika nilai tampilan kolom telah berubah, isDirty_ biasanya harus ditetapkan ke true.

Teks

→ Untuk mengetahui informasi tentang tempat teks kolom digunakan dan perbedaannya dengan nilai kolom, lihat Anatomi kolom.

Jika teks kolom Anda berbeda dengan nilai kolom, Anda harus mengganti fungsi getText untuk memberikan teks yang benar.

getText() {
  let text = this.value_.turtleName + ' wearing a ' + this.value_.hat;
  if (this.value_.hat == 'Stovepipe' || this.value_.hat == 'Propeller') {
    text += ' hat';
  }
  return text;
}

Membuat editor

Jika Anda menentukan fungsi showEditor_, Blockly akan otomatis memantau klik dan memanggil showEditor_ pada waktu yang tepat. Anda dapat menampilkan HTML apa pun di editor dengan membungkusnya dalam salah satu dari dua div khusus, yang disebut DropDownDiv dan WidgetDiv, yang mengambang di atas UI Blockly lainnya.

DropDownDiv digunakan untuk menyediakan editor yang berada di dalam kotak yang terhubung ke kolom. Secara otomatis memosisikan dirinya di dekat kolom sambil tetap berada dalam batas yang terlihat. Pemilih sudut dan pemilih warna adalah contoh yang baik dari DropDownDiv.

Gambar pemilih sudut

WidgetDiv digunakan untuk menyediakan editor yang tidak berada di dalam kotak. Kolom angka menggunakan WidgetDiv untuk menutupi kolom dengan kotak input teks HTML. Meskipun DropDownDiv menangani penentuan posisi untuk Anda, WidgetDiv tidak. Elemen harus diposisikan secara manual. Sistem koordinat berada dalam koordinat piksel relatif terhadap kiri atas jendela. Editor input teks adalah contoh yang baik dari WidgetDiv.

Gambar editor input teks

showEditor_() {
  // Create the widget HTML
  this.editor_ = this.dropdownCreate_();
  Blockly.DropDownDiv.getContentDiv().appendChild(this.editor_);

  // Set the dropdown's background colour.
  // This can be used to make it match the colour of the field.
  Blockly.DropDownDiv.setColour('white', 'silver');

  // Show it next to the field. Always pass a dispose function.
  Blockly.DropDownDiv.showPositionedByField(
      this, this.disposeWidget_.bind(this));
}

Kode contoh WidgetDiv

showEditor_() {
  // Show the div. This automatically closes the dropdown if it is open.
  // Always pass a dispose function.
  Blockly.WidgetDiv.show(
    this, this.sourceBlock_.RTL, this.widgetDispose_.bind(this));

  // Create the widget HTML.
  var widget = this.createWidget_();
  Blockly.WidgetDiv.getDiv().appendChild(widget);
}

Pembersihan

DropDownDiv dan WidgetDiv menangani penghancuran elemen HTML widget, tetapi Anda harus membuang secara manual semua pemroses peristiwa yang telah diterapkan ke elemen tersebut.

widgetDispose_() {
  for (let i = this.editorListeners_.length, listener;
      listener = this.editorListeners_[i]; i--) {
    Blockly.browserEvents.unbind(listener);
    this.editorListeners_.pop();
  }
}

Fungsi dispose dipanggil dalam konteks null di DropDownDiv. Di WidgetDiv, metode ini dipanggil dalam konteks WidgetDiv. Dalam kedua kasus tersebut, sebaiknya gunakan fungsi bind saat meneruskan fungsi pelepasan, seperti yang ditunjukkan dalam contoh DropDownDiv dan WidgetDiv di atas.

→ Untuk informasi tentang pelepasan yang tidak spesifik untuk pelepasan editor, lihat Melepaskan.

Memperbarui tampilan saat diblokir

Fungsi render_ digunakan untuk memperbarui tampilan dalam blok kolom agar sesuai dengan nilai internalnya.

Contoh umum meliputi:

  • Mengubah teks (dropdown)
  • Mengubah warna (warna)

Default

Fungsi render_ default menetapkan teks tampilan ke hasil fungsi getDisplayText_. Fungsi getDisplayText_ menampilkan properti value_ kolom yang dikonversi menjadi string, setelah dipangkas untuk mematuhi panjang teks maksimum.

Jika Anda menggunakan tampilan saat diblokir default, dan perilaku teks default berfungsi untuk kolom Anda, Anda tidak perlu mengganti render_.

Jika perilaku teks default berfungsi untuk kolom Anda, tetapi tampilan dalam blok kolom Anda memiliki elemen statis tambahan, Anda dapat memanggil fungsi render_ default, tetapi Anda tetap harus menggantinya untuk memperbarui ukuran kolom.

Jika perilaku teks default tidak berfungsi untuk kolom Anda, atau tampilan on-block kolom Anda memiliki elemen dinamis tambahan, Anda harus menyesuaikan fungsi render_.

Diagram alur yang menjelaskan cara membuat keputusan apakah akan mengganti render_

Menyesuaikan rendering

Jika perilaku rendering default tidak berfungsi untuk kolom Anda, Anda harus menentukan perilaku rendering kustom. Hal ini dapat mencakup apa saja, mulai dari menyetel teks tampilan kustom, hingga mengubah elemen gambar, hingga memperbarui warna latar belakang.

Semua perubahan atribut DOM sah, hanya ada dua hal yang perlu diingat:

  1. Pembuatan DOM harus ditangani selama inisialisasi, karena lebih efisien.
  2. Anda harus selalu memperbarui properti size_ agar sesuai dengan ukuran tampilan dalam blok.
render_() {
  switch(this.value_.hat) {
    case 'Stovepipe':
      this.stovepipe_.style.display = '';
      break;
    case 'Crown':
      this.crown_.style.display = '';
      break;
    case 'Mask':
      this.mask_.style.display = '';
      break;
    case 'Propeller':
      this.propeller_.style.display = '';
      break;
    case 'Fedora':
      this.fedora_.style.display = '';
      break;
  }

  switch(this.value_.pattern) {
    case 'Dots':
      this.shellPattern_.setAttribute('fill', 'url(#polkadots)');
      break;
    case 'Stripes':
      this.shellPattern_.setAttribute('fill', 'url(#stripes)');
      break;
    case 'Hexagons':
      this.shellPattern_.setAttribute('fill', 'url(#hexagons)');
      break;
  }

  this.textContent_.nodeValue = this.value_.turtleName;

  this.updateSize_();
}

Memperbarui ukuran

Memperbarui properti size_ kolom sangat penting, karena memberi tahu kode rendering blok cara memosisikan kolom. Cara terbaik untuk mengetahui nilai size_ yang tepat adalah dengan bereksperimen.

updateSize_() {
  const bbox = this.movableGroup_.getBBox();
  let width = bbox.width;
  let height = bbox.height;
  if (this.borderRect_) {
    width += this.constants_.FIELD_BORDER_RECT_X_PADDING * 2;
    height += this.constants_.FIELD_BORDER_RECT_X_PADDING * 2;
    this.borderRect_.setAttribute('width', width);
    this.borderRect_.setAttribute('height', height);
  }
  // Note how both the width and the height can be dynamic.
  this.size_.width = width;
  this.size_.height = height;
}

Mencocokkan warna balok

Jika Anda ingin elemen kolom Anda cocok dengan warna blok yang terlampir, Anda harus mengganti metode applyColour. Anda akan ingin mengakses warna melalui properti gaya blok.

applyColour() {
  const sourceBlock = this.sourceBlock_;
  if (sourceBlock.isShadow()) {
    this.arrow_.style.fill = sourceBlock.style.colourSecondary;
  } else {
    this.arrow_.style.fill = sourceBlock.style.colourPrimary;
  }
}

Memperbarui kemampuan pengeditan

Fungsi updateEditable dapat digunakan untuk mengubah tampilan kolom Anda, bergantung pada apakah kolom tersebut dapat diedit atau tidak. Fungsi default membuat latar belakang memiliki/tidak memiliki respons saat mengarahkan kursor (batas) jika dapat/tidak dapat diedit. Tampilan dalam blok tidak boleh berubah ukurannya, bergantung pada kemampuannya untuk diedit, tetapi semua perubahan lainnya diizinkan.

updateEditable() {
  if (!this.fieldGroup_) {
    // Not initialized yet.
    return;
  }
  super.updateEditable();

  const group = this.getClickTarget_();
  if (!this.isCurrentlyEditable()) {
    group.style.cursor = 'not-allowed';
  } else {
    group.style.cursor = this.CURSOR;
  }
}

Serialisasi

Serialisasi adalah tentang menyimpan status kolom Anda sehingga dapat dimuat ulang ke ruang kerja nanti.

Status ruang kerja Anda selalu menyertakan nilai kolom, tetapi juga dapat menyertakan status lain, seperti status UI kolom Anda. Misalnya, jika kolom Anda adalah peta yang dapat di-zoom yang memungkinkan pengguna memilih negara, Anda juga dapat melakukan serialisasi tingkat zoom.

Jika kolom Anda dapat diserialisasi, Anda harus menetapkan properti SERIALIZABLE ke true.

Blockly menyediakan dua set hook serialisasi untuk kolom. Satu pasang hook berfungsi dengan sistem serialisasi JSON baru, dan pasang hook lainnya berfungsi dengan sistem serialisasi XML lama.

saveState dan loadState

saveState dan loadState adalah hook serialisasi yang berfungsi dengan sistem serialisasi JSON baru.

Dalam beberapa kasus, Anda tidak perlu menyediakannya karena implementasi default akan berfungsi. Jika (1) kolom Anda adalah subclass langsung dari class Blockly.Field dasar, (2) nilai Anda adalah jenis yang dapat diserialisasi JSON, dan (3) Anda hanya perlu menserialisasi nilai, maka penerapan default akan berfungsi dengan baik.

Jika tidak, fungsi saveState Anda harus menampilkan objek/nilai yang dapat diserialisasi JSON yang merepresentasikan status kolom. Fungsi loadState Anda harus menerima objek/nilai yang dapat diserialisasi JSON yang sama, dan menerapkannya ke kolom.

saveState() {
  return {
    'country': this.getValue(),  // Value state
    'zoom': this.getZoomLevel(), // UI state
  };
}

loadState(state) {
  this.setValue(state['country']);
  this.setZoomLevel(state['zoom']);
}

Serialisasi penuh dan data pendukung

saveState juga menerima parameter opsional doFullSerialization. Ini digunakan oleh kolom yang biasanya mereferensikan status yang diserialisasi oleh serializer lain (seperti model data pendukung). Parameter menandakan bahwa status yang dirujuk tidak akan tersedia saat blok dideserialisasi, sehingga kolom harus melakukan semua serialisasi itu sendiri. Misalnya, hal ini benar saat blok individual diserialisasi, atau saat blok disalin dan ditempel.

Dua kasus penggunaan umum untuk hal ini adalah:

  • Saat blok individual dimuat ke ruang kerja yang tidak memiliki model data pendukung, kolom memiliki informasi yang cukup dalam statusnya sendiri untuk membuat model data baru.
  • Saat blok disalin dan ditempel, kolom selalu membuat model data pendukung baru, bukan merujuk ke model data yang sudah ada.

Salah satu kolom yang menggunakan ini adalah kolom variabel bawaan. Biasanya, ID variabel yang dirujuk akan diserialisasi, tetapi jika doFullSerialization benar, semua statusnya akan diserialisasi.

saveState(doFullSerialization) {
  const state = {'id': this.variable_.getId()};
  if (doFullSerialization) {
    state['name'] = this.variable_.name;
    state['type'] = this.variable_.type;
  }
  return state;
}

loadState(state) {
  const variable = Blockly.Variables.getOrCreateVariablePackage(
      this.getSourceBlock().workspace,
      state['id'],
      state['name'],   // May not exist.
      state['type']);  // May not exist.
  this.setValue(variable.getId());
}

Kolom variabel melakukan hal ini untuk memastikan bahwa jika dimuat ke ruang kerja yang tidak memiliki variabelnya, kolom tersebut dapat membuat variabel baru untuk dirujuk.

toXml dan fromXml

toXml dan fromXml adalah hook serialisasi yang berfungsi dengan sistem serialisasi XML lama. Gunakan hook ini hanya jika Anda harus melakukannya (misalnya, Anda sedang mengerjakan codebase lama yang belum dimigrasikan), jika tidak, gunakan saveState dan loadState.

Fungsi toXml Anda harus menampilkan node XML yang merepresentasikan status kolom. Fungsi fromXml Anda harus menerima node XML yang sama dan menerapkannya ke kolom.

toXml(fieldElement) {
  fieldElement.textContent = this.getValue();
  fieldElement.setAttribute('zoom', this.getZoomLevel());
  return fieldElement;
}

fromXml(fieldElement) {
  this.setValue(fieldElement.textContent);
  this.setZoomLevel(fieldElement.getAttribute('zoom'));
}

Properti yang dapat diedit dan diserialisasi

Properti EDITABLE menentukan apakah kolom harus memiliki UI untuk menunjukkan bahwa kolom tersebut dapat digunakan. Nilai defaultnya adalah true.

Properti SERIALIZABLE menentukan apakah kolom harus diserialisasi. Nilai defaultnya adalah false. Jika properti ini adalah true, Anda mungkin perlu menyediakan fungsi serialisasi dan deserialisasi (lihat Serialisasi).

Menyesuaikan dengan CSS

Anda dapat menyesuaikan kolom dengan CSS. Dalam initView method, tambahkan class kustom ke fieldGroup_ kolom Anda, lalu referensikan class ini di CSS Anda.

Misalnya, untuk menggunakan kursor yang berbeda:

initView() {
  ...

  // Add a custom CSS class.
  if (this.fieldGroup_) {
    Blockly.utils.dom.addClass(this.fieldGroup_, 'myCustomField');
  }
}
.myCustomField {
  cursor: cell;
}

Menyesuaikan kursor

Secara default, class yang memperluas FieldInput menggunakan kursor text saat pengguna mengarahkan kursor ke atas kolom, kolom yang ditarik menggunakan kursor grabbing, dan semua kolom lainnya menggunakan kursor default. Jika Anda ingin menggunakan kursor yang berbeda, tetapkan kursor tersebut menggunakan CSS.