iT邦幫忙

2021 iThome 鐵人賽

DAY 19
1
Modern Web

ZK 30天速成系列 第 19

元件內建拖放(drag & drop)效果

  • 分享至 

  • xImage
  •  

不論是自己實作拖放效果,或是使用 JavaScript 函式庫,都需要花點心思才能做出,如果不熟 JavaScript 的人還是挺麻煩。ZK 所有元件都內建拖放效果,只要啟用即可。而拖放之後實際要產生什麼行為仍可以 Java 實作。

如何使用拖放效果

例如我要讓一個表格中的每一列可以被拖放改變順序。

https://ithelp.ithome.com.tw/upload/images/20211004/20050621dbURADdj8X.jpg

啟用拖放效果

啟用完後,滑鼠拖拉元件就會看到如上的元件被拖動的殘影效果。

<listbox width="40%" apply="quickstart.DragDropComposer">
...
    <listitem draggable="true" droppable="true" >
        <listcell label="United States"/>
        <listcell label="5,093"/>
        <listcell label="19.39%"/>
    </listitem>
  • 在每個 <listitem> 上都設定 draggable="true",啟用該元件可以被拖拉
  • droppable="true" 讓使用者可以把元件「拖放」到 <listitem>上。

改變元件順序

但光是啟用只是擁有瀏覽器上可以看到的拖放視覺效果,實際上並不會改變每列順序,這必須要透過 Java 來控制元件來改變順序

public class DragDropComposer extends SelectorComposer<Component> {
    @Listen("onDrop = listitem")
    public void move(DropEvent event){
        Listitem listitem = (Listitem)event.getTarget();
        listitem.getParent().insertBefore(event.getDragged(), listitem);
    }
}
  • 當放下元件到 <listitem> 上時,會發出 onDrop 事件,因此我要註冊對應的傾聽器來變更順序
  • event.getTarget() 傳回事件發生的元件,也就是丟下去的目的元件。例如我把 France 拖放到 Germany,那 target 就是 Gerymany。 event.getDragged() 就是被拖的元件,也就是 France。
  • insertBefore(): 我把 France 插入到 Germany 前面來改變順序。

一次拖放多個元件

可以啟用 Listbox 的多選功能來達到一次拖拉多個元件的效果

https://ithelp.ithome.com.tw/upload/images/20211004/20050621H3Vgs6MWR2.jpg

<listbox multiple="true" width="50%">
    <listitem draggable="true" label="Matthew"/>
    <listitem draggable="true" label="Mark"/>
    <listitem draggable="true" label="Lucas"/>
    <listitem draggable="true" label="John"/>
</listbox>
<div droppable="true" sclass="box" height="150px" onDrop="onDrop(event)">
    丟到此區
</div>
  • multiple="true" 啟用多選功能

實作傾聽器

public void onDrop(DropEvent evt) {
    Listitem li = (Listitem)evt.getDragged();
    if (li.isSelected()) {
        Set selected = ((Listitem)evt.getDragged()).getListbox().getSelectedItems();
        //處理整批
    } else {
        li.setSelected(true);
       //處理單一個
    }

    Clients.showNotification("select " + selected.size());
}
  • 從 listitem 可以取得 Listbox 參照,再取得所有選擇的 items (getSelectedItems()

區隔可拖放的目標

有時我希望能指定拖放特定的元件,例如一個區域只能放 email,另一個區域只能放入 contact:

https://ithelp.ithome.com.tw/upload/images/20211004/20050621Kg0fgjxu80.jpg

指定拖拉類別

draggable 上自定一個字串作為其「類別」

<listbox multiple="true" width="50%">
    <listitem draggable="email" label="Email 1"/>
    <listitem draggable="email" label="Email 2"/>
    <listitem draggable="contact" label="Contact 1"/>
    <listitem draggable="contact" label="Contact 2"/>
</listbox>

然後 droppable 指定同樣的「類別」。如果你拖放的元件類別不同,ZK 會顯示像上圖那樣的「禁止」圖示,告知使用者無法放入,即便你拖放了,也不會產生 onDrop 事件。

<div sclass="box" height="50px" droppable="email" onDrop="accept(event)" >
    只接受 email
</div>
  • 當你拖放同樣類別的元件時,才會呼叫 onDrop 傾聽器

以上介紹拖拉的基本用法,如果對 JavaScript 熟悉的人甚至可以客製化拖拉效果,請參考 ZK Client-side Reference


上一篇
如何讓元件自動調整尺寸適應各種裝置螢幕
下一篇
單一頁面應用模式的頁面導航
系列文
ZK 30天速成30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言