Flutter: DropdownWidget ใช้ยังไงมาเบิ่งกัน
Drop down widget คือ ปุ่มที่เอาไว้เลือกเมนูต่างๆเแบบในรูปด้านบนเลยคับ เป็น widget มาตรฐานอีกตัวที่มาจาก material ของ Flutter ที่เรามักจะต้องใช้บ่อยๆ
ถ้าเราพิมพ์ใน vscode จะพบว่ามีให้เลือก 3 แบบ
DropdownButton() ใช้ทั่วๆไปในการสร้าง button แบบ dropdownDropdownButtonFormField() สามารถนำไปใช้งานร่วมกับ FormField()อื่นๆได้สะดวกมากขึ้น เพราะมีทั้ง decoration: และ validator: ให้เรียกใช้งานได้เลยDropdownButtonHideUnderline() ใช้กรณีที่ไม่ต้องการให้เห็น underline ใน UI เลย โดยใน article นี้จะมีการ apply ให้ดูด้วยคับ
ในการใช้งาน เราสามารถกำหนดให้ values ด้านในเป็น static หรือ dynamic จาก API ก็ได้ เพราะเป็น List ชุดนึงที่เราต้องเตรียมไว้ให้กับ widget นี้ Let’s code !
- ในการใช้งาน 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 ต่างๆ
จากนั้นจะลองเพิ่ม property ในส่วนของ styling เข้าไปดูบ้าง เพื่อให้เห็นว่าเราสามารถปรับแต่งได้อย่างไร
2. ถัดไปลอง refactor ในส่วนของ items proptery ที่ยังดูรกๆจะได้แบบนี้
(ในส่วนนี้ได้เพิ่ม code ของ DIY widget เข้ามาแล้ว แต่ ignore line 81 onwards ไปก่อนก็ได้)
3. ในเมื่อสิ่งที่เราต้องการเปลี่ยนแปลง มีเพียง 4 ตัวเท่านั้นคือitems,onChanged,hint และ value
เราสามารถสร้างให้เป็น reusable class เพื่อให้แต่ละไฟล์ใน project มาเรียกใช้งานได้เลย
โดยเราสามารถยก Container() ของ DropdownButton() มาสร้างเป็น class ใน StatefulWidget และกำหนด constructor เพื่อบังคับให้ใส่ค่าที่ต้องการเข้ามาให้ครบได้เลยแบบนี้
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(.) และลดความผิดพลาด
เมื่อเรียกใช้งานจะเป็นลักษณะนี้