pass custom content จาก parent -> child ด้วย slot
Tags: slot, svelte, webcomponents
Published: 2021-02-12 08:56:48

ปกติแล้วเวลาเราจะส่งค่า จาก parent component ไปหา child component จะต้องส่งด้วย props แต่ปัญหาอย่างหนึ่งในการ ส่งค่าข้าม component คือ ถ้าข้อมูลมาขนาดใหญ่ และข้อมูลอยู่ในรูปแบบ html จะเริ่มทำยากแล้วครับ ถ้าเราเจอ case study แบบนี้เราจะมี solution มาแก้ปัญหายังไง มาดูกันครับ

### slot คืออะไร
slot หรือ slot tag หรือ slot element มันคือ html element อันนึงใน webcomponent ที่ช่วยให้เราสามารถรับค่าจาก parent component ได้ หรือหากเราต้องการเจาะช่องไว้ เพื่อให้ content บางอย่างมาแสดงเฉพาะส่วนที่เราเจาะช่องไว้ก็ได้

### มาเตรียม component กันก่อน
```html
<!-- App.svelte -->
<script>
	import Box from './Box.svelte';
</script>

<!-- ใช้งาน Box -->
<Box>

</Box>
```

```html
<!-- Box.svelte -->
<style>
	.box {
		width: 300px;
		border: 1px solid #aaa;
		border-radius: 2px;
		box-shadow: 2px 2px 8px rgba(0,0,0,0.1);
		padding: 1em;
		margin: 0 0 1em 0;
	}
</style>

<div class="box">
  
</div>
```

### ถ้าเราต้องการส่งค่าจาก parent -> child ผ่าน prop
```html
<!-- App.svelte -->
<script>
   import Box from './Box.svelte';
   const title = 'Title Prop'

</script>

<!-- ใช้งาน Box -->
<Box {title} />
```

```html
<!-- Box.svelte -->
<script>
export let title;
</script>

<div class="box">
  {title}
</div>
```

### ส่งค่า ผ่าน prop โดยข้อมูลเป็น html
```html
<!-- App.svelte -->
<script>
   import Box from './Box.svelte';
   const title = '<h1>Title Prop</h1>'
</script>

<!-- ใช้งาน Box -->
<Box {title} />
```

```html
<!-- Box.svelte -->
<script>
export let title;
</script>

<div class="box">
  {@html title}
</div>
```
ในกรณีอาจจะยังไม่เห็นว่ามันมีปัญหายังไง คราวนี้เราลองใส่ข้อมูลไปใน ตัวแปร title เยอะขึ้น ผสมกับ html tag ไปด้วย จะเห็นว่ามันจัดระเบียบข้อมูลยากขึ้น ถ้ายังไม่เห็นภาพ เพิ่ม style เข้าไปอีก ข้อมูลเริ่มรกละ

ถ้าเกิดว่าเราจัดโครงสร้างข้อมูลเอง ทำ block content อาจจะมี style ร่วมด้วย แต่ว่าดูสะอาดตามากขึ้น เราสามารถแก้ปัญหานี้ slot tag ครับ มาดูกัน

```html
<!-- App.svelte -->
<script>
   import Box from './Box.svelte';
</script>

<!-- ใช้งาน Box -->
<Box>
  <h1>Slot Title</h1>
</Box>
```


```html
<!-- Box.svelte -->
<div class="box">
  <slot />
</div>
```

### ลองมาวางโครงและใส่ข้อมูลเยอะมากขึ้น
```html
<!-- App.svelte -->
<script>
   import Box from './Box.svelte';
</script>

<!-- ใช้งาน Box -->
<Box>
  <div class="title">
    <h1>Slot Title</h1>
  </div>

  <div class="sub_title">
    <h4>Slot SubTitle</h4>
  </div>

  <div class="content">
    <p>content...</p>
  </div>

</Box>
```


```html
<!-- Box.svelte -->
<div class="box">
  <slot />
</div>
```

จากตัวอย่างจะเห็นว่าไม่ว่าเราจะใส่ content มากแค่ไหน มันก็ยังดูสะอาดตา เพราะมันเป็นโครงสร้าง html ทั่วไปที่เราคุ้นเคยอยู่แล้ว แถมยังสามารถจัดโครงสร้าง content ได้เองอีกด้วย `<slot />` ถ้าเรากำหนดแบบนี้ ที่ฝั่ง component ลูก เราจะเรียกว่า default slot ไม่ว่าเราจะใส่ content มาในรูปแบบไหน มันจะมาลงที่ defualt slot นี้เลย นี่ก็เป็นแค่ตัวอย่างการใช้ slot tag ง่ายๆนะครับ

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/mtaax3ej3ohy4n37l8mv.png)

ศึกษาเพิ่มเติมเรื่อง slot tag ได้ที่ [slot tag](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot)

หากสนใจ svelte สามารถเรียนรู้การใช้งาน svelte แบบ step by step ได้ที่
[Svelte: Framework Not Framework — (ตอนที่ 1) แรกรู้จัก](https://medium.com/@tanangular/svelte-framework-not-framework-%E0%B8%95%E0%B8%AD%E0%B8%99%E0%B8%97%E0%B8%B5%E0%B9%88-1-%E0%B9%81%E0%B8%A3%E0%B8%81%E0%B8%A3%E0%B8%B9%E0%B9%89%E0%B8%88%E0%B8%B1%E0%B8%81-434fde7ff97f)

ขอบคุณทุกท่านที่อ่านมาถึงตรงนี้ ถ้าอ่านแล้วรู้มีประโยชน์ ฝากกด Subscribe หรือ share link ให้คนอื่นรับรู้ด้วยนะครับ ขอบคุณครับ