mydomain
No ADS
No ADS

FlutterArtist Sort DropdownSortPanel Example

  1. Structure of the example
  2. Country12aSortModelBuilder
  3. Country12aShelf
  4. DropdownSortPanel
  5. Country12aBlock
Sorting involves arranging data in a specific order, such as ascending or descending, based on one or more criteria. In applications, sorting can be performed on the client-side or server-side, or even both, each with its own advantages and limitations.
Server-side Sorting
Server-side sorting involves sending a request to the server to perform the sorting operation. The server processes the data (usually via database queries) and returns the sorted results to the client. If the request includes pagination, the data received will vary depending on the sorting criteria.
Client-side Sorting
Client-side sorting involves arranging data already available on the client (previously fetched from the server). The data itself doesn’t change; only the order changes according to the selected criteria.
No ADS
FlutterArtist supports both server-side and client-side sorting. You provide a SortModelBuilder to define the criteria and rules for client-side sorting. SortModelBuilder is used to create two SortModel objects, one used for server-side sorting, the other used for client-side sorting.
  • ServerSide-SortModel: Provides criteria for the server to perform sorting (e.g., by price or stock quantity). Through the SortPanel, users select their preferred criteria and direction.
  • ClientSide-SortModel: Provides a list of criteria and data comparison rules (by implementing the abstract methods of the SortModelBuilder).
Chú ý, nếu bạn không muốn sử dụng SortModel cho máy khách, người dùng có thể tự sắp xếp các ITEM(s) một cách thủ công thông qua việc kéo thả trên giao diện. Chẳng hạn các ví dụ sau:
Trong bài viết này chúng ta sẽ xem một ví dụ làm thế nào để tạo một SortModel và sử dụng nó cho một Block để xắp xếp các ITEM(s) của Block này.
  • Download FlutterArtist Demo

1. Structure of the example

2. Country12aSortModelBuilder

In this example, CountryInfo is a data model representing information about a country. The model contains several properties that can be used for sorting.
CountryInfo
class CountryInfo { 
  String id; 
  String name; 
  String nameInEnglish; 
  String countryCode; 
  String isoCode2; 
  String isoCode3; 
  int population; 
  int area; 
  double? gdp;
}
SortModelBuilder defines:
  • Sorting criteria
  • Comparison rules for client-side sorting
This builder is used by the Block to create SortModel instances for both client-side and server-side sorting.
Block (*)
SortModel<ITEM>? get clientSideSortModel;

SortModel<ITEM>? get serverSideSortModel;
country12a_sort_model_builder.dart
class Country12aSortModelBuilder extends SortModelBuilder<CountryInfo> {
  Country12aSortModelBuilder({
    required super.clientSideSortMode,
    required super.serverSideSortMode,
  });

  @override
  SortModelStructure defineSortModelStructure() {
    return SortModelStructure(
      sortCriterionDefs: [
        SortCriterionDef(
          criterionName: 'nameInEnglish',
          text: 'Name In English',
          translationKey: "country.nameInEnglish",
        ),
        SortCriterionDef(
          criterionName: 'population',
          text: 'Population',
          translationKey: "country.population",
          serverSideConfig: SortCriterionConfig(
            initialSortDirection: SortDirection.desc,
          ),
        ),
        SortCriterionDef(
          criterionName: 'area',
          text: 'Area',
          translationKey: "country.area",
          serverSideConfig: SortCriterionConfig(
            initialSortDirection: SortDirection.asc,
          ),
        ),
      ],
    );
  }

  @override
  Comparable? getComparisonValue({
    required CountryInfo item,
    required String criterionName,
  }) {
    if (criterionName == "nameInEnglish") {
      return item.nameInEnglish;
    } else if (criterionName == "population") {
      return item.population;
    } else if (criterionName == "area") {
      return item.area;
    }
    return null;
  }

  @override
  String? getTranslationText({required String translationKey}) {
    return null;
  }
}

3. Country12aShelf

After creating Country12aSortModelBuilder, you need to register it as a component of Country12aBlock inside the Shelf.
country12a_shelf.dart
class Country12aShelf extends Shelf {
  @override
  ShelfStructure defineShelfStructure() {
    return ShelfStructure(
      filterModels: {},
      blocks: [
        Country12aBlock(
          name: Country12aBlock.blkName,
          description: null,
          config: BlockConfig(
            pageable: Pageable(pageSize: 5),
            clientSideSortStrategy: SortStrategy.modelBased,
          ),
          filterModelName: null,
          formModel: null,
          childBlocks: [],
          sortModelBuilder: Country12aSortModelBuilder(
            clientSideSortMode: SortMode.single,
            serverSideSortMode: SortMode.single,
          ),
        ),
      ],
    );
  }

  Country12aBlock findCountry12aBlock() {
    return findBlock(Country12aBlock.blkName) as Country12aBlock;
  }
}
No ADS
BlockConfig.clientSideSortStrategy
The BlockConfig.clientSideSortStrategy parameter defines how the Block handles client-side sorting.
BlockConfig(
  ...
  clientSideSortStrategy: SortStrategy.modelBased,
),
none
With this configuration, this Block will not support client-side sorting (including manual sorting) and block.clientSideSortModel will always return null.
modelBased
With this configuration, Block will apply sorting on the client side if you provide it with a SortModelBuilder, then block.clientSideSortModel will be guaranteed to be non-null.
manual
With this configuration, Block accepts manual arrangement of its ITEM(s) via drag and drop on the interface. In this case block.clientSideSortModel will always be null.
Examples of manual sorting on the client side by dragging and dropping on the interface.

4. DropdownSortPanel

DropdownSortPanel is a UI widget that allows users to select sorting criteria and direction through a dropdown menu.
You can write your own SortPanel widgets by extending the SortPanel class or simply use widgets already created by FlutterArtist.
An example with BreadcrumbSortPanel:
Here are a few style(s) you can apply to DropdownSortPanel:
Modern Pill
Enterprise
Soft UI
style12a.dart
final defaultStyle12a = DropdownSortPanelStyle();

final modernPillStyle12a = DropdownSortPanelStyle(
  textStyle: const TextStyle(
    fontSize: 13,
    fontWeight: FontWeight.w600,
    color: Colors.indigo,
  ),
  padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
  decoration: BoxDecoration(
    color: Colors.indigo.withAlpha(20),
    borderRadius: BorderRadius.circular(25),
    border: Border.all(color: Colors.indigo.withAlpha(50)),
  ),
  dropdownIcon: Icons.unfold_more_rounded,
  dropdownIconColor: Colors.indigo,
);

final enterpriseStyle12a = DropdownSortPanelStyle(
  textStyle: const TextStyle(fontSize: 14, color: Colors.black87),
  padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
  decoration: BoxDecoration(
    color: Colors.white,
    border: Border(bottom: BorderSide(color: Colors.grey.shade400, width: 1.5)),
  ),
  dropdownIcon: Icons.unfold_more_rounded,
  dropdownIconColor: Colors.grey.shade700,
);

final softUIStyle12a = DropdownSortPanelStyle(
  textStyle: const TextStyle(fontSize: 14, color: Colors.blueGrey),
  padding: const EdgeInsets.all(12),
  decoration: BoxDecoration(
    color: Colors.white,
    borderRadius: BorderRadius.circular(12),
    boxShadow: [
      BoxShadow(
        color: Colors.black.withAlpha(10),
        blurRadius: 10,
        offset: const Offset(0, 4),
      ),
    ],
  ),
  dropdownIcon: Icons.unfold_more_rounded,
);
No ADS
How to use DropdownSortPanel:
if (country12aBlock.serverSideSortModel != null)
  DropdownSortPanel.simple(
    sortModel: country12aBlock.serverSideSortModel!,
  ),

if (country12aBlock.clientSideSortModel != null)
  DropdownSortPanel.simple(
    sortModel: country12aBlock.clientSideSortModel!,
  ),
Future<void> _clearCriteria() async {
  await serverSideSortModel.clearAllSorts();
}

5. Country12aBlock

In case a Block uses SortModel for the server side, you need to pay attention to the sortableCriteria parameter of the Block.performQuery() method. SortableCriteria only includes criteria that have direction, or in other words, criteria that have a clear sorting direction, ascending or descending, assigned.
country12a_block.dart (*)
class Country12aBlock
    extends
        Block<
          String, //
          CountryInfo,
          CountryData,
          EmptyFilterInput,
          EmptyFilterCriteria,
          EmptyFormInput,
          EmptyAdditionalFormRelatedData
        > {
  static const blkName = "country12a-block";

  final countryRestProvider = CountryRestProvider(); 
  
  @override
  Future<ApiResult<PageData<CountryInfo>?>> performQuery({
    required Object? parentBlockCurrentItem,
    required EmptyFilterCriteria filterCriteria,
    required SortableCriteria sortableCriteria,
    required Pageable pageable,
  }) async {
    return await countryRestProvider.query(
      sortableCriteria: sortableCriteria,
      pageable: pageable,
    );
  } 
  ...
}
Convert the SortableCriteria object to a String before passing it to the server:
print(sortableCriteria.toSignedString());

// Output:
//  +criterion1,-criterion2


print(sortableCriteria.toJsonString());

// Output:
//  {"criterion1": "asc", "criterion2": "desc"}
After converting SortableCriteria into a String, you can pass this value to the Query API. The string will be parsed on the server side to determine the sorting criteria.
country_rest_provider.dart (**)
...
Future<ApiResult<CountryInfoPage>> query({
  required Pageable pageable,
  SortableCriteria? sortableCriteria,
  String? searchText,
}) async {
  Map<String, dynamic>? queryParameters = {
    "currentPage": pageable.page,
    "pageSize": pageable.pageSize,
    "searchText": searchText,
    // Json String: '{"criterion1": "asc", "criterion2": "desc"}'.
    "jsonSortableCriteria": sortableCriteria?.toJsonString(),
  };

  // /rest/countryInfoPage
  ApiResult<CountryInfoPage> result = await flutterArtistDio.jsonGet(
    "/rest/countryInfoPage",
    queryParameters: queryParameters,
    converter: CountryInfoPage.fromMap,
  );
  return result;
}
No ADS

FlutterArtist

Show More
No ADS