Core Docs

Section (layout)

Section là renderer runtime của 1 row ComponentGroup. Đặt component con vào DOM theo cấu hình DB.

Sectionlayout primitive trong Core. Mỗi row ComponentGroup trong DB trở thành 1 Section lúc runtime, và mỗi row Component bên trong group đó trở thành 1 EditableComponent con render vào element của section.

Nguồn: Core/Components/Section.cs. Row dữ liệu: Core.Models.ComponentGroup.

Nó thực sự làm gì?

public class Section : EditableComponent
{
    public ComponentGroup ComponentGroup { get; set; }

    public override void Render()
    {
        if (elementType is null)
        {
            // Section được build quanh element có sẵn — đọc tag.
            var tag = Element.TagName.ToLowerCase();
            if (Enum.TryParse(tag, out ElementType type)) elementType = type;
        }
        else
        {
            // Section được cho ElementType — tạo tag đó.
            Html.Take(ParentElement)
                .Add(elementType.Value)
                .ClassName(ComponentGroup is null ? null : ComponentGroup.ClassName);
            Element = Html.Context;
        }
        // … duyệt ComponentGroup.Component và render từng child …
    }

    public void UpdateViewComponent()
    {
        DisposeChildren();
        Html.Take(ParentElement).Clear();
        elementType = null;
        Render();
    }
}

Hai chế độ construct:

// Chế độ 1: build element mới với tag chỉ định
new Section(ElementType.div) { ComponentGroup = group, ParentElement = parent };

// Chế độ 2: bọc element có sẵn (re-skin nó thành section)
new Section(existingElement) { ComponentGroup = group };

Field ComponentGroup chi phối render

FieldTác dụng
ElementTypeTag HTML (div, tr, td, fieldset, …).
ClassNameClass CSS gắn lên element render.
ComponentChildren render bên trong.
ParentIdKhác null → section này là con của section khác.
OrderThứ tự render giữa sibling.

Lồng & cây

Section nest qua ComponentGroup.ParentId. Framework load list phẳng rồi BuildTree(...) ráp ChildGroup, sau đó Section.Render() walk cây.

ComponentGroup (root)        ─►  <div class="form">
├── ComponentGroup (header)  ─►    <div class="row">
│   ├── Component(Textbox)    ─►      <input ... />
│   └── Component(Datepicker) ─►      <input type="date" />
└── ComponentGroup (body)    ─►    <fieldset class="body">
    └── Component(GridView)   ─►      <table>...</table>

Update sau khi đổi cấu hình

Nếu cấu hình section thay đổi (toggle visibility 1 child), gọi UpdateViewComponent() — nó dispose children, clear DOM, render lại.

Update tinh hơn: giữ ref child cụ thể và toggle child.Show = false.

Chia cột (responsive grid)

Đây là cách chia layout 1 section thành N cột — tính năng built-in, không cần viết CSS riêng.

ComponentGroup có 5 field cấu hình số cột theo screen width:

FieldKhi nào áp dụngBreakpoint hằng số (EditableComponent)
XsColMàn hình rất nhỏ (< 567px)ExSmallScreen = 567
SmColMàn hình nhỏ (< 768px)SmallScreen = 768
ColumnMàn hình trung bình (< 992px)MediumScreen = 992
LgColMàn hình lớn (< 1200px)LargeScreen = 1200
XlColMàn hình rất lớn (< 1452px)ExLargeScreen = 1452

Khi resolve, framework gọi EditForm.GetInnerColumn(group) đi từ nhỏ → lớn theo screen hiện tại để pick số cột phù hợp. Sau đó Section.RenderComponentResponsive set:

Html.Take(Element)
    .ClassName("grid")
    .Style($"grid-template-columns: repeat({innerCol}, 1fr)");

Tức là CSS Grid với N cột bằng nhau (1fr mỗi cột).

Ví dụ: form 2 cột trên desktop, 1 cột trên mobile

ComponentGroup:
  Name: Header
  ElementType: div
  XsCol: 1     # mobile dọc
  SmCol: 1
  Column: 2    # tablet trở lên 2 cột
  LgCol: 2
  XlCol: 2

Bên trong section thêm các Component (Textbox, Number, …) → tự xếp vào lưới 2 cột.

Cho 1 component span nhiều cột

Component.Column (colSpan) — mỗi component có thể chiếm nhiều ô:

var colSpan = ui.Column ?? 2;   // mặc định = 2 (Section.cs:759)

Ví dụ trong section 4 cột, đặt Component.Column = 4 cho 1 component → chiếm cả hàng.

Layout pattern thường gặp trong Core

Mục đíchClassName (set trên ComponentGroup)Ghi chú
Form responsive grid(để rỗng, dùng Column field)Framework auto set grid + style.
Bootstrap rowrow + child có col-md-6, …Dùng khi tự kiểm soát cột.
Container fluidcontainer-fluidWrap toàn form full-width.
Ribbon collapsibleribbonTự thêm icon collapse + dropdown.
Default panelpanel groupStyle chuẩn của framework.
Ẩn mặc địnhdefault-hideSection ẩn ngay khi render.

Pattern trực tiếp trong Section.cs: nếu ClassName chứa "ribbon" thì render kiểu ribbon collapsible; chứa "default-hide" thì ẩn ngay; còn lại thêm panel group.

Layout dạng table (ui-layout)

Khi cần label cố định cột trái + value cột phải kiểu form truyền thống, framework có pattern table-based:

Html.Instance.Table.ClassName("ui-layout").TBody.TRow.Render();

Tự động render <table class="ui-layout"> với <tr> cho mỗi component, cột trái là label (label-header), cột phải là widget. Pattern này active khi section có loại đặc biệt — xem RenderInputLabel trong Section.cs:483.

Layout custom thủ công

Nếu 5 field *Col chưa đủ, vẫn còn 2 đường:

  1. Set ClassName thành CSS class do bạn tự define — viết flex/grid riêng trong file CSS dự án. Section render sẽ áp class đó lên element ngoài, mọi child component nhận layout từ class.

    ClassName: my-custom-layout

    Trong file CSS:

    .my-custom-layout {
      display: grid;
      grid-template-columns: 200px 1fr 200px;
      gap: 1rem;
    }
  2. Subclass Section. Override Render() đặt children thủ công. Set ComponentGroup.ComType = "MyCustomSection" để runtime instantiate subclass của bạn.

Ưu tiên dùng *Col field trước — DB-driven và responsive sẵn. CSS class custom khi cần layout đặc biệt (sidebar, masonry, …). Subclass Section chỉ khi không cách nào khác.

Visibility expression

ComponentGroup.Visibility (và Component.Visibility) chứa expression evaluate trên entity. False → ẩn section/component. Hữu ích cho “chỉ show panel khi status = Approved”.

Evaluator nằm trong EditableComponent.Extensions — xem đó để biết syntax.

Các kiểu section thường gặp

Mục đíchElementTypeClassNameGhi chú
Form rowdivrowChứa 1+ input đặt cạnh nhau.
Card / paneldivcard / panelHeading + body section.
Cell trong tabletd(tuỳ)1 component cho cell grid.
Tab panedivtab-paneDùng với TabComponent strip.
Inline label groupfieldsetfield-groupWrap input liên quan + legend.

Field DB Section thực dùng

(Trích từ Section.cs + EditForm.GetInnerColumn — chỉ field thực sự được đọc:)

  • ComponentGroup.ClassName — class CSS gắn lên element.
  • ComponentGroup.ElementType — tag HTML render ra.
  • ComponentGroup.Component — children.
  • ComponentGroup.Label — text label (cho ribbon, fieldset).
  • ComponentGroup.Visibility — expression ẩn/hiện theo entity.
  • ComponentGroup.IsCollapsible — kết hợp ribbon để cho phép thu/mở.
  • ComponentGroup.XsCol / SmCol / Column / LgCol / XlCol — số cột grid theo breakpoint.
  • ComponentGroup.ParentId — section cha (cây).
  • ComponentGroup.Order — thứ tự giữa siblings.

(Liên kết với FeatureId, load + BuildTree do framework xử lý, Section bản thân không touch.)

Tip

  • Đừng nest quá sâu. Mỗi section là 1 element DOM + iteration. Phẳng-nhưng-có-class nhanh hơn sâu-mặc-định.
  • ComponentGroup.ClassName được append raw — tránh khoảng trắng trong field user-edit được.
  • Section render rỗng → kiểm tra children Active = trueFeatureId khớp parent feature.

Core Docs · Astro · Core.API/wwwRoot/docs