deferLoading() ให้ส่วนที่ยังไม่เห็นรอโหลดทีหลัง
หน้าแก้ข้อมูลลูกค้าในระบบหลังร้านมักยาว มีข้อมูลทั่วไป ที่อยู่จัดส่ง ข้อมูลออกใบกำกับภาษี และประวัติการติดต่อ ทุก section เรนเดอร์ตั้งแต่เปิดหน้า แม้ผู้ใช้จะพับไว้หรือไม่เคยเลื่อนลงไปดู ยิ่งมี select ที่ต้อง query ตัวเลือก หน้าก็ยิ่งเปิดช้า
Filament 5.8 เพิ่ม deferLoading() (PR #19867 โดย Kian Acquoij) ส่วนที่ใส่ไว้จะขึ้นเป็นตัว loading ก่อน แล้วค่อยเรนเดอร์ field ของตัวเองใน request แยกเมื่อเลื่อนมาถึง วิธีใช้คือส่ง Schema เข้า schema() แทน array แล้วต่อท้ายด้วย deferLoading()
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
Section::make('ข้อมูลออกใบกำกับภาษี')
->key('taxInfo')
->schema(
Schema::make()
->components([
TextInput::make('tax_id'),
TextInput::make('branch_code'),
])
->deferLoading(),
)
->collapsed()
ถ้าส่วนนั้นอยู่ใน section ที่พับไว้หรือแท็บที่ยังไม่ได้เปิด Filament จะรอจนผู้ใช้กางหรือเปิดแท็บนั้นก่อน wizard ก็เหมือนกัน แต่ละ step โหลดเมื่อผู้ใช้เดินมาถึง ส่วน repeater และ builder ใส่ deferLoading() ที่ schema ของแต่ละรายการได้ เหมาะกับรายการสินค้าในใบสั่งซื้อที่มีหลายสิบแถวแล้วพับไว้
เอกสารของ v5.8.0 บอกพฤติกรรมที่ควรรู้ไว้สามข้อ
- ทุก schema ที่ defer ต้องมี key ไม่ซ้ำกัน schema ลูกใช้ key ของ section แม่ (
taxInfoข้างบน) ถ้า component เดียวมี schema ลูกที่ defer หลายชุด ต้องใส่key()เองให้ชุดที่เหลือ ส่วนรายการใน repeater กับ builder ได้ key จาก state path ให้เอง - ถ้าส่วนที่ยังไม่โหลดมี error จาก validation Filament จะโหลดส่วนนั้นให้เองเพื่อแสดง error ผู้ใช้จึงไม่ติดอยู่กับฟอร์มที่บันทึกไม่ได้โดยไม่รู้ว่าผิดตรงไหน
- โหลดแล้วอยู่ต่อจนปิดหน้า พับกลับแล้วกางใหม่ไม่ต้องโหลดซ้ำ
deferLoading() รับ boolean หรือ closure ได้ด้วย ถ้าอยากเปิดตามเงื่อนไข เช่น defer เฉพาะตอนแก้ไข แต่ตอนสร้างใหม่ให้โหลดทั้งหมด (closure รับค่าแบบเดียวกับที่อธิบายไว้ในโพสต์เรื่อง utility injection)
ตารางจำการจัดกลุ่มไว้ใน session
ตารางของ Filament จำการเรียง การค้นหา filter และคอลัมน์ที่ซ่อนไว้ใน session ได้มานานแล้ว 5.8 เพิ่มการจัดกลุ่มเข้าไปด้วย persistGroupInSession() (PR #20165) ฝ่ายบัญชีที่ดูใบสั่งซื้อแบบจัดกลุ่มตามสถานะทุกเช้า กลับมาหน้านี้ก็ยังเห็นแบบเดิม
return $table
->groups(['status', 'customer.name'])
->defaultGroup('status', direction: 'desc')
->persistGroupInSession();
defaultGroup() รับ direction ได้แล้วเหมือน defaultSort() (PR #20267) เดิมกลุ่มเริ่มต้นเรียงจากน้อยไปมากอย่างเดียว รุ่นนี้ยังแก้ชื่อ hook ของ Livewire ที่ไม่ตรงกับ property $tableGrouping ด้วย เปลี่ยนการจัดกลุ่มแล้วตารางจึงกลับไปหน้าแรก ไม่ค้างอยู่หน้าที่อาจไม่มีข้อมูลแล้ว
hook ใน trait ไม่โดน page ทับอีกแล้ว
ถ้าเราเขียน trait ที่ใช้ร่วมกันหลาย page แล้วใส่ afterSave() ไว้ใน trait พอ page ไหนเขียน afterSave() ของตัวเอง ของใน trait ก็หายไปเงียบ ๆ ตามกฎของ PHP ที่เมธอดของคลาสทับเมธอดของ trait
5.8 ใช้วิธีเดียวกับ boot{TraitName}() ของ Eloquent (PR #20189) ให้ตั้งชื่อ hook ใน trait ต่อท้ายด้วยชื่อ trait แล้ว Filament จะเรียก hook ของ page ก่อน ตามด้วย hook ของทุก trait
trait LogsChanges
{
protected function afterSaveLogsChanges(): void
{
// บันทึกประวัติการแก้ไข ทำงานต่อจาก afterSave() ของ page
}
}
class EditOrder extends EditRecord
{
use LogsChanges;
protected function afterSave(): void
{
// ทำก่อน แล้ว Filament จึงเรียก afterSaveLogsChanges()
}
}
ใช้ได้กับ page ใน panel ทั้งหน้าสร้าง แก้ไข และดูข้อมูล และใช้กับ importer ได้ด้วย
ของเล็ก ๆ ที่เพิ่มมา
- placeholder ของ stat
Stat::make('ยอดขายวันนี้', $total)->placeholder('-')แสดงขีดแทนช่องว่างเมื่อยังไม่มีค่า ถ้าอยากตั้งให้ทุก stat ใช้Stat::configureUsing()ในboot()ของ service provider (PR #20176) - ใช้หน้ายืนยันรหัส MFA ในหน้าอื่นได้ คลาส
MultiFactorChallengeแยกออกมาจากหน้า login ให้ component ของเราเรียกถามรหัสก่อนทำ action อันตราย อย่างลบข้อมูลหรือเปลี่ยนบัญชีรับเงิน มีตัวจำกัดจำนวนครั้งในตัว เอกสารเตือนว่า schema ที่ว่างเปล่า validate ผ่านเสมอ จึงต้องเรียกhasEnabledProviders()ซ้ำอีกครั้งก่อน validate (PR #20353) - ความสูงของ editor
RichEditorและMarkdownEditorมีminHeight()กับmaxHeight()รับหน่วย CSS ค่าเริ่มต้นคือ10remและเมื่อเนื้อหายาวเกินmaxHeight()จะเลื่อนในกรอบแทนการยืดทั้งหน้า (PR #20258) - ตัวดาวน์โหลดไฟล์ export ของเราเอง override
getDownloader()ใน exporter ได้ เช่น ให้ redirect ไปที่ temporary URL ของไฟล์บน S3 แทนการ stream ผ่านแอป เหมาะกับ host ที่ไม่ให้ stream ไฟล์ใหญ่ ฝั่ง importer มีgetFailedRowsDownloader()สำหรับไฟล์แถวที่นำเข้าไม่ผ่าน (PR #20285) - คู่มือ Boost เป็น Agent Skill เดิม Laravel Boost ใส่ guideline ของ Filament ทั้งชุดเข้า context ของ AI agent ทุก session ตอนนี้เป็น skill ที่โหลดเฉพาะตอน agent แก้โค้ด Filament ประหยัด context ไปได้มาก ต้องรัน
php artisan boost:installแล้วเลือก Agent Skills ตามด้วย filament/filament (skills) เพราะboost:updateอย่างเดียวไม่เพิ่มให้ (PR #20338)
รายการทั้งหมดดูได้ที่ release notes ของ v5.8.0






