FlutterArtist FilterModelStructure ex2
Note: The article you are viewing is example Demo59b, a minor upgrade from example Demo59a, which adds some configurations so that TildeFilterCriterion(s) are set to default values instead of manual user operations on the FilterPanel.

You see, when you select a new Company, the list of Department(s) will change accordingly, and a particular Department will be selected by default.

No ADS
Similar to example Demo59a, the following is the Field-Based JSON structure you will receive to send to the server for querying and filtering employees.
{
"connector": "AND",
"conditions": [
{
"field": "searchText",
"operator": "containsIgnoreCase",
"value": null
},
{
"connector": "OR",
"conditions": [
{
"field": "departmentId",
"operator": "equalTo",
"value": 4
},
{
"field": "departmentId",
"operator": "equalTo",
"value": 3
}
]
}
]
}1. registerFilterModelStructure
First, let's look at the complete code for the defineFilterModelStructure() method.
Employee59bFilterModel.defineFilterModelStructure()
@override
FilterModelStructure defineFilterModelStructure() {
return FilterModelStructure(
criteriaStructure: FilterCriteriaStructure(
simpleCriterionDefs: [
SimpleFilterCriterionDef<String>(criterionBaseName: "searchText"),
],
multiOptCriterionDefs: [
// Multi Options Single Selection Criterion.
MultiOptFilterCriterionDef<CompanyInfo>.singleSelection(
criterionBaseName: "company",
fieldName: 'companyId',
toFieldValue: (CompanyInfo? rawValue) {
return SimpleVal.ofInt(rawValue?.id);
},
tildeCriterionConfigs: [
TildeCriterionConfig(
suffix: '~1', // company~1
defaultSettingPolicy: DefaultSettingPolicy.onEveryLoad,
),
TildeCriterionConfig(
suffix: '~2', // company~2
defaultSettingPolicy: DefaultSettingPolicy.onEveryLoad,
),
],
children: [
// Multi Options Single Selection Criterion.
MultiOptFilterCriterionDef<DepartmentInfo>.singleSelection(
criterionBaseName: "department",
fieldName: 'departmentId',
toFieldValue: (DepartmentInfo? rawValue) {
return SimpleVal.ofInt(rawValue?.id);
},
tildeCriterionConfigs: [
TildeCriterionConfig(
suffix: '~1', // department~1
defaultSettingPolicy: DefaultSettingPolicy.onEveryLoad,
),
],
),
],
),
],
),
conditionStructure: FilterConditionStructure(
connector: FilterConnector.and,
conditionDefs: [
FilterConditionDef.simple(
tildeCriterionName: "searchText~",
operator: FilterOperator.containsIgnoreCase,
),
FilterConditionDef.group(
groupName: 'G2',
connector: FilterConnector.or,
conditionDefs: [
FilterConditionDef.simple(
tildeCriterionName: "department~1",
operator: FilterOperator.equalTo,
),
FilterConditionDef.simple(
tildeCriterionName: "department~2",
operator: FilterOperator.equalTo,
),
],
),
],
),
);
}tildeCriterionConfigs
Similar to example Demo59a, there will be two TildeCriterion(s) - "company~1" and "company~2" created based on the Criterion("company") blueprint.

No ADS
company~1 / company~2
First, let's consider the configuration of the criteria pair "company~1" and "company~2".
MultiOptCriterionDef<CompanyInfo>
MultiOptFilterCriterionDef<CompanyInfo>.singleSelection(
criterionBaseName: "company",
fieldName: 'companyId',
toFieldValue: (CompanyInfo? rawValue) {
return SimpleVal.ofInt(rawValue?.id);
},
tildeCriterionConfigs: [
TildeCriterionConfig(
suffix: '~1', // company~1
defaultSettingPolicy: DefaultSettingPolicy.onEveryLoad,
),
TildeCriterionConfig(
suffix: '~2', // company~2
defaultSettingPolicy: DefaultSettingPolicy.onEveryLoad,
),
],
...
}By applying DefaultSettingPolicy.onEveryLoad, both company~1 and company~2 are guaranteed to automatically select a default value immediately after data is loaded. This specific value is determined by the logic within the FilterModel.specifyDefaultValueForMultiOptTildeCriterion() method.
No ADS
By default, TildeFilterCriterion(s) are only assigned default values for the first data load. In other words, their default configuration is like this:
(Default Configs)
tildeCriterionConfigs: [
TildeCriterionConfig(
suffix: '~1', // company~1
defaultSettingPolicy: DefaultSettingPolicy.onInitialOnly,
parentMatchSuffix: null,
),
TildeCriterionConfig(
suffix: '~2', // company~2
defaultSettingPolicy: DefaultSettingPolicy.onInitialOnly,
parentMatchSuffix: null,
),
],department~1
Next, let’s look at the configuration for "department~1":
MultiOptTildeCriterionDef<DepartmentInfo>
MultiOptTildeCriterionDef<DepartmentInfo>.singleSelection(
criterionBaseName: "department",
fieldName: 'departmentId',
toFieldValue: (DepartmentInfo? rawValue) {
return SimpleVal.ofInt(rawValue?.id);
},
tildeCriterionConfigs: [
TildeCriterionConfig(
suffix: '~1', // department~1
defaultSettingPolicy: DefaultSettingPolicy.onEveryLoad,
),
],
),Thanks to this setup, whenever "company~1" changes, the department list for "department~1" reloads, and the system automatically assigns a new default value to it via FilterModel.specifyDefaultValueForMultiOptTildeCriterion() method.

department~2
In contrast, for "department~2", since no explicit configuration is provided, it falls back to the default policy: DefaultSettingPolicy.onInitialOnly.
This results in a different user experience: "department~2" only auto-selects a default value during the very first data load. If you change "company~2" later, the data for "department~2" will still reload, but it will no longer automatically select a value (unless done manually by the user).
No ADS
Which DefaultSettingPolicy should I choose?
Choosing between onEveryLoad and onInitialOnly depends entirely on the User Experience (UX) you intend to provide:
Use DefaultSettingPolicy.onEveryLoad when: | You want to ensure the criterion always holds a valid value as soon as the parent data changes. For example: When selecting a "Company," you want the first "Department" to be auto-selected so the user sees search results immediately without extra clicks. |
Use DefaultSettingPolicy.onInitialOnly (Default) when: | You want to allow the user to maintain an "empty" (null/none) state after the initial load. This is useful when you want the user to proactively select a value if needed, rather than having the system force a selection every time the data list updates. |
2. specifyDefaultValueForMultiOptTildeCriterion()
After the data is loaded for each MultiOptTildeFilterCriterion, the assignment of a default value is determined by the specifyDefaultValueForMultiOptTildeCriterion() method:
specifyDefaultValueForMultiOptTildeCriterion()
@override
OptValueWrap? specifyDefaultValueForMultiOptTildeCriterion({
required String multiOptTildeCriterionName,
required String multiOptCriterionBaseName,
required Object? parentMultiOptTildeCriterionValue,
required SelectionType selectionType,
required XData multiOptTildeCriterionXData,
}) {
if (multiOptCriterionBaseName == "company") {
var xList = multiOptTildeCriterionXData as ListXData<int, CompanyInfo>;
CompanyInfo? companyInfo = xList.items.firstOrNull;
return OptValueWrap.single(companyInfo);
} else if (multiOptCriterionBaseName == "department") {
var xList = multiOptTildeCriterionXData as ListXData<int, DepartmentInfo>;
DepartmentInfo? departmentInfo = xList.items.firstOrNull;
return OptValueWrap.single(departmentInfo);
}
return null;
}No ADS
FlutterArtist
- Basic concepts in Flutter Artist
- FlutterArtist Block ex1
- FlutterArtist Filter Example
- FlutterArtist FilterModel MultiOptFilterCriterion ex1
- FlutterArtist FilterInput Example 1
- FlutterArtist Form ex1
- The idea of designing filter models in FlutterArtist
- FlutterArtist FormModel.patchFormFields() Ex1
- FlutterArtist BlockQuickItemUpdateAction Example
- FlutterArtist BlockNumberPagination Ex1
- FlutterArtist GridView Infinite Scroll Example
- FlutterArtist BlockQuickMultiItemCreationAction Example
- FlutterArtist ListView Infinite Scroll Pagination Example
- FlutterArtist Pagination
- FlutterArtist Sort DropdownSortPanel Example
- FlutterArtist Dio
- FlutterArtist BlockBackendAction Example
- FlutterArtist BackgroundWebDownloadAction Example
- FlutterArtist StorageBackendAction ex1
- FlutterArtist Block External Shelf Event ex1
- FlutterArtist Filter FormBuilderMultiDropDown Ex1
- FlutterArtist Master-detail Blocks ex1
- FlutterArtist Scalar ex1
- FlutterArtist Pagination Davi table Infinite Scroll Ex1
- FlutterArtist Filter Tree FormBuilderField ex1
- FlutterArtist Filter FormBuilderRadioGroup ex1
- FlutterArtist Form Parent-child MultiOptFormProp ex1
- FlutterArtist Manual Sorting ReorderableGridView Example
- FlutterArtist Manual Sorting ReorderableListView
- FlutterArtist Scalar External Shelf Event ex1
- FlutterArtist Code Flow Viewer
- FlutterArtist Log Viewer
- FlutterArtist config
- FlutterArtist StorageStructure
- FlutterArtist Debug Storage Viewer
- FlutterArtist DebugMenu
- FlutterArtist Debug UI Components Viewer
- FlutterArtist Debug Shelf Structure Viewer
- FlutterArtist Context Provider Views
- FlutterArtist FilterModelStructure ex1
- FlutterArtist FilterModelStructure ex2
- FlutterArtist FilterModelStructure ex3
- FlutterArtist Internal Shelf Event ex1
- FlutterArtist Deferring External Shelf Events (Ex1)
- FlutterArtist DropdownSortPanel
Show More