Membuat Menu Menggunakan SvelteJS

Topic created · 1 Posts · 23 Views
  • Membuat Mega Menu Berdasarkan Kusi Bali Js ke 2 Menggunakan Sveltejs. Goalnya adalah array dari menu object akan di mapping menjadi DOM tree. Untuk mengetahu tag svelte dan penggunaan bisa lihat - lihat dokumentasi svelte

    --> Hasil akhir

    Mission

    1. Menutup semua menu yang terbuka, jika klik di luar menu
    2. Menutup menu yang terbuka, jika menu lain di klik

    Membuat Svelte Component

    Satu yang special dari svelte tag adalah <svelte:self/> dimana ini representatif dari component itu sendiri ini mirip dengan fungsi rekursif.

    <script>
            export let menu = [];
    	export let visible = (new Array(menu.length)).fill(false);
    	
    	function toggle(index, status) {
    		visible[index] = status
    	}
    
    	function handleClick (index) {
    		return (e) => {
    			toggle(index, !visible[index])
    		}
    	}
    	
    </script>
    <ul>
      {#each menu as item, index }
        {#if item.children}
            <li>
                <div on:click={handleClick(index)} >{item.name}</div>
                {#if visible[index]}
    		<div >
    			<svelte:self menu={item.children}  />
    		</div>
    	    {/if}
            </li>
        {:else}
            <li>{item.name}</li>
        {/if}
      {/each}
    </ul>
    
    

    Menambah Transisi

    Transisi pada svelte tidak bisa ditaruh pada tag spesial svelte seperti <svelte:self/> oleh karena itu saya menaruhnya kedalam tag div dan transisi akan hanya bisa berjalan saat element di hapus atau di tambah, bisa menggunakan logic block else-if. Transisi yang saya gunakan adalah slide yaitu membuat seolah muncul dari atas ke bawah

    <script>
    	import { slide } from 'svelte/transition';
    	import { quintOut } from 'svelte/easing';
    	
            export let menu = [];
    	export let visible = (new Array(menu.length)).fill(false);
    	
    	function toggle(index, status) {
    		visible[index] = status
    	}
    
    	function handleClick (index) {
    		return (e) => {
    			toggle(index, !visible[index])
    		}
    	}
    	
    </script>
    <ul>
      {#each menu as item, index }
        {#if item.children}
            <li>
                <div on:click={handleClick(index)} >{item.name}</div>
                {#if visible[index]}
    		<div  transition:slide="{{delay: 250, duration: 300, easing: quintOut }}">
    			<svelte:self menu={item.children}  />
    		</div>
    	    {/if}
            </li>
        {:else}
            <li>{item.name}</li>
        {/if}
      {/each}
    </ul>
    
    
    

    1. Menutup Menu

    Untuk menutup menu ketika melakukan klik di luar submenu saya medengarkan klik pada body element menggunakan tag spesial dari svelte <svelte:body />. kemudian menggunakan event modifier yaitu capture , hal ini dilakukan agar fungsi handleOutsde dipanggil sebelum sebuah menu di tekan (menu tertutup dulu baru menu lain yang ditekan muncul submenunya). untuk detailnya mengenai lihat https://javascript.info/bubbling-and-capturing

    <script>
    	import { slide } from 'svelte/transition';
    	import { quintOut } from 'svelte/easing';
    	
            export let menu = [];
    	export let visible = (new Array(menu.length)).fill(false);
    	
    	function toggle(index, status) {
    		visible[index] = status
    	}
    
    	function handleClick (index) {
    		return (e) => {
    			toggle(index, !visible[index])
    		}
    	}
    	function handleOutsde (event) {
    		visible = (new Array(menu.length)).fill(false);
    	}
    	
    </script>
    <svelte:body on:click|capture={handleOutsde} />
    <ul>
      {#each menu as item, index }
        {#if item.children}
            <li>
                <div on:click={handleClick(index)} >{item.name}</div>
                {#if visible[index]}
    		<div  transition:slide="{{delay: 250, duration: 300, easing: quintOut }}">
    			<svelte:self menu={item.children}  />
    		</div>
    	    {/if}
            </li>
        {:else}
            <li>{item.name}</li>
        {/if}
      {/each}
    </ul>
    

    2. Menutup Menu lainnya

    Untuk menutup menu lainnya hal pertama yang harus di pikirkan adalah bagaimana agar menu parent tetap terbuka walaupun submenu di klik ini karena fungis sebelumnya handleOutsde menutup semua menu dengan melabeli menu telah tertutup, untuk mengatasi itu kita perlu memberi tahu parent element bahwa ada child sedang dalam keadaan terbuka untuk itu perlu dibuat sebuah custom event dimana nanti akan medispatch "memanggil fungsi di parent" memberitahu bahwa submenu telah di klik.

    <script>
    	import { slide } from 'svelte/transition';
    	import { quintOut } from 'svelte/easing';
    	import { createEventDispatcher } from 'svelte';
    
    	const dispatch = createEventDispatcher();
    	
    	export let position = null;
      export let menu = [];
    	export let visible = (new Array(menu.length)).fill(false);
    	
    	function doToggle(pos, status) {
    		dispatch('open', {pos, status})
    	}
    	
    	function toggle(index, status) {
    		doToggle(position, true)
    		visible[index] = status
    	}
    	
    	function handleOpen(event) {
    		toggle(event.detail.pos, event.detail.status);
    	}
    
    	function handleClick (index) {
    		return (e) => {
    			toggle(index, !visible[index])
    		}
    	}
    
    	function handleOutsde (event) {
    		visible = (new Array(menu.length)).fill(false);
    	}
    	
    </script>
    <svelte:body on:click|capture={handleOutsde} />
    <ul>
      {#each menu as item, index }
        {#if item.children}
            <li>
                <div on:click|stopPropagation={handleClick(index)} >{item.name}</div>
                {#if visible[index]}
    							<div  transition:slide="{{delay: 250, duration: 300, easing: quintOut }}">
    								<svelte:self position={index} menu={item.children} on:open={handleOpen} />
    							</div>
    						{/if}
            </li>
        {:else}
            <li>{item.name}</li>
        {/if}
      {/each}
    </ul>
    

Pengumuman!

Untuk yang baru join, jangan lupa perkenalkan dirimu disini ya

Juga jangan lupa baca ketentuan penggunaan di forum ini. Rekan-rekan bisa lihat disini.

Buat yang penasaran alasan dibuatnya forum BaliJS ini silakan baca disini.

Utas Populer Bulan Ini

Semeton Online

Forum Stats

0
Online

122
Users

91
Topics

456
Posts