Flutter: DropdownWidget ใช้ยังไงมาเบิ่งกัน

Grassroot Engineer
3 min readAug 22, 2021

--

https://medium.com/flutterdevs/dropdown-in-flutter-324ae9caa743

Drop down widget คือ ปุ่มที่เอาไว้เลือกเมนูต่างๆเแบบในรูปด้านบนเลยคับ เป็น widget มาตรฐานอีกตัวที่มาจาก material ของ Flutter ที่เรามักจะต้องใช้บ่อยๆ

ถ้าเราพิมพ์ใน vscode จะพบว่ามีให้เลือก 3 แบบ

ใน vscode จะมีให้เราเลือก 3 แบบ
DropdownButton() ใช้ทั่วๆไปในการสร้าง button แบบ dropdownDropdownButtonFormField() สามารถนำไปใช้งานร่วมกับ FormField()อื่นๆได้สะดวกมากขึ้น เพราะมีทั้ง decoration: และ validator: ให้เรียกใช้งานได้เลยDropdownButtonHideUnderline() ใช้กรณีที่ไม่ต้องการให้เห็น underline ใน UI เลย โดยใน article นี้จะมีการ apply ให้ดูด้วยคับ

ในการใช้งาน เราสามารถกำหนดให้ values ด้านในเป็น static หรือ dynamic จาก API ก็ได้ เพราะเป็น List ชุดนึงที่เราต้องเตรียมไว้ให้กับ widget นี้ Let’s code !

  1. ในการใช้งาน DropdownButton() จะมีส่วนที่ required อยู่ 4 ตัวด้วยกันคือ
  • items (List<DropdownMenuItem<String>>): โดยจะรับค่าเป็น List<DropdownMenuItem<String>>
  • onChanged (void Function(String)): สำหรับ implement ต่อว่าเมื่อ selected แล้วจะให้ทำไรต่อ ซึ่งอย่างแรกเลยคือ update UI.
  • hint (Widget): Widget ที่ต้องการแสดงเมื่อสถานะ idle ทั่วไปก็เพียง Text()
  • value (String): String ที่จะแสดงหลังจากที่มีการเลือกแล้ว

ส่วนที่เหลือจะเป็นเพียง Cosmetics เช่น

  • isExpanded (bool): เพื่อต้องการให้ button นี้ยืดไปจนสุดขอบซ้ายขวา
  • icon (Widget): เมื่อต้องการกำหนด icon แทน default ที่เป็น Icons.arrow_drop_down
  • อื่นๆ เช่น focusColor, elevation, style, iconEnableColor หรือ การ wrap ด้วย Container()เพื่อตกแต่งด้วย decoration เป็นต้น

โดยอันดับแรกจะเป็นการทดสอบด้วย List<String> ที่เราได้กำหนดไว้เป็น static แล้วคือ ตัวเลือกของภาษา programming ต่างๆ

กำหนด List<String> และ map เพื่อให้ออกมาเป็น List<DropdownMenuItem> เพื่อให้จำเข้าไปให้งานได้

จากนั้นจะลองเพิ่ม property ในส่วนของ styling เข้าไปดูบ้าง เพื่อให้เห็นว่าเราสามารถปรับแต่งได้อย่างไร

เพื่อเติมในส่วนของ cosmetics ใน UI

2. ถัดไปลอง refactor ในส่วนของ items proptery ที่ยังดูรกๆจะได้แบบนี้
(ในส่วนนี้ได้เพิ่ม code ของ DIY widget เข้ามาแล้ว แต่ ignore line 81 onwards ไปก่อนก็ได้)

เมื่อทำการยก items ไปเก็บไว้ที่อื่นให้ดูโล่งๆใน DropdownButton()

3. ในเมื่อสิ่งที่เราต้องการเปลี่ยนแปลง มีเพียง 4 ตัวเท่านั้นคือ
items,onChanged,hint และ value
เราสามารถสร้างให้เป็น reusable class เพื่อให้แต่ละไฟล์ใน project มาเรียกใช้งานได้เลย

โดยเราสามารถยก Container() ของ DropdownButton() มาสร้างเป็น class ใน StatefulWidget และกำหนด constructor เพื่อบังคับให้ใส่ค่าที่ต้องการเข้ามาให้ครบได้เลยแบบนี้

สร้าง Widget class สำหรับ reusable code.
DIY widgets from class.
แสดงผลลัพธ์ที่เหมือนกัน ระหว่างเขียนใหม่หมด กับเขียนเป็น class ไว้เรียกใช้

PS.

เมื่อ items ใน DropdownWidget มี property items ซึ่งรับค่ามาเป็น List<dynamic> จะมีบางครั้งการทำงานร่วมกับ BE อาจจะไม่ได้ต้องการให้ส่งค่าเป็น String เข้าไปเหมือนกับสิ่งที่แสดงใน UI เช่น

ต้องการให้แสดงผลเป็น

['Frontend', 'Backend', 'DevOps', 'Support', 'PM']แต่ให้ส่งค่าเข้าไปเป็น[1, 2, 3, 4, 5]

ในกรณีแบบนี้ค่าที่มาจาก API ตอน GET เพื่อแสดงใน UI มักจะเป็นรูปแบบนี้

{
"positons": [
{
"id": 1,
"name": "Frontend"
},
{
"id": 2,
"name": "Backend"
},
{
"id": 3,
"name": "DevOps"
},
{
"id": 4,
"name": "Support"
},
{
"id": 5,
"name": "PM"
},
]
}

ในกรณีแบบนี้เราจะต้องทำการ custom items ใหม่เพื่อให้แสดงค่าได้ด้วย name และนำมา map ออกมาเป็น id เพื่อส่งค่าไปได้

ซึ่งใน class DropdownWidget() ผมได้เพิ่ม property customItems ในกรณีที่ต้องการ customize List<dynamic> ขึ้นมาเอง โดยระบุสิ่งที่ต้องนำมาแสดงผลคือ

child: Text(e.name)ค่าที่ต้องการนำไปแสดงผล
value: e.id.toString() ค่าที่ต้องการส่งเข้าไปใน API

เมื่อมีการ call API จาก BE เพื่อนำมาทำเป็น List ของ dropdown ควรไปสร้าง model ไว้ก่อนนะคับ เพื่อให้ง่ายในการใช้ dot(.) และลดความผิดพลาด

เมื่อเรียกใช้งานจะเป็นลักษณะนี้

ทางเลือกเมื่อต้องการ custom items ที่รับเข้ามา แต่ต้องเขียนเองใหม่หมด เพราะใน model ยังไม่มี

--

--