mydomain
No ADS
No ADS

FlutterArtist Debug Filter Model Inspector

  1. FilterModel
  2. Conclude
  3. FilterCriteria
Debug Filter Model Inspector is a tool that allows you to inspect the state and data of a FilterModel. This tool can be opened via a button on the FilterControlBar or programmatically via code.
Open the Debug Filter Model Inspector using the code:
FilterModel filterModel = ...;

filterModel.showDebugFilterModelInspector();

1. FilterModel

First, let’s look at a simple FilterModel with two defined criteria.
product77a_filter_model.dart (*)
...
@override
FilterModelStructure defineFilterModelStructure() {
  return FilterModelStructure(
    criteriaStructure: FilterCriteriaStructure(
      simpleCriterionDefs: [
        SimpleFilterCriterionDef<double>(criterionBaseName: "price"),
      ],
      multiOptCriterionDefs: [
        // Multi Options Single Selection Criterion.
        MultiOptFilterCriterionDef<CategoryInfo>.singleSelection(
          criterionBaseName: "category",
          fieldName: 'categoryId',
          toFieldValue: (CategoryInfo? rawValue) {
            return SimpleVal.ofInt(rawValue?.id);
          },
        ),
      ],
    ),
    conditionStructure: FilterConditionStructure(
      connector: FilterConnector.and,
      conditionDefs: [
        FilterConditionDef.simple(
          tildeCriterionName: "category~",
          operator: FilterOperator. equalTo,
        ),
        FilterConditionDef.simple(
          tildeCriterionName: "price~min",
          operator: FilterOperator.equalTo,
        ),
        FilterConditionDef.simple(
          tildeCriterionName: "price~max",
          operator: FilterOperator.equalTo,
        ),
      ],
    ),
  );
}
Criteria
On the Debug Filter Model Inspector, you can view the data type definitions of these criteria.
tildeCriterionName
In FlutterArtist, a tildeCriterionName is a special identifier representing a filtering condition. A single criterion can have one or multiple tildeCriterionName(s). Each tildeCriterionName maps 1-to-1 to an input field on the FilterPanel.
A tildeCriterionName always contains the "~" character. For example, like this:
  • category~
  • price~min
  • price~max
tildeCriterionName = criterionBaseName + suffix
On the UI (FilterPanel), users input or select values corresponding to each tildeCriterionName.
  • Tilde-Based JSON is a conditional structure that accurately records what the user sees on the interface. Each TildeFilterCriterion corresponds to an input field on the interface.
  • Criteria-Based JSON is a simplified conditional structure of Tilde-Based JSON where tildeCriterionName(s) are replaced by criterionName(s) and their logical values.
Tilde-Based JSON
{
    "connector": "AND",
    "conditions": [
        {
            "tildeCriterionName": "category~",
            "value": "CategoryInfo(1, Electric Cars)",
            "operator": "equalTo"
        },
        {
            "tildeCriterionName": "price~min",
            "value": 1000,
            "operator": "greaterThan"
        },
        {
            "tildeCriterionName": "price~max",
            "value": 20000,
            "operator": "lessThan"
        }
    ]
}
Criteria-Based JSON
{
    "connector": "AND",
    "conditions": [
        {
            "criterionName": "category",
            "value": "CategoryInfo(1, Electric Cars)",
            "operator": "equalTo"
        },
        {
            "criterionName": "price",
            "value": 1000,
            "operator": "greaterThan"
        },
        {
            "criterionName": "price",
            "value": 20000,
            "operator": "lessThan"
        }
    ]
}
At the third level, we have Field-Based JSON, which is the final serialization process. This is where the toFieldValue() method is called to convert a complex data type into a simpler data type (int, double, String, bool). Field-Based JSON is the final product sent to the server for data querying and filtering.
Field-Based JSON
{
    "connector": "AND",
    "conditions": [
        {
            "field": "categoryId",
            "operator": "equalTo",
            "value": 1
        },
        {
            "field": "price",
            "operator": "greaterThan",
            "value": 1000
        },
        {
            "field": "price",
            "operator": "lessThan",
            "value": 20000
        }
    ]
}
Tildes
This tab allows you to inspect the current values of all tildeCriterionName(s) These values are passed into FilterModel.createNewFilterCriteria() to construct a new FilterCriteria object.
@override
Song02aFilterCriteria createNewFilterCriteria({
  required Map<String, dynamic> criteriaMap,
}) {
  return Song02aFilterCriteria(
    album: criteriaMap["album~"],
    searchText: criteriaMap["searchText~"],
  );
}
{ } Tilde-Based JSON
This tab displays a JSON result of combining the condition structure and the current data of the TildeCriterion(s).
  • This is the representation closest to what the user sees on the UI.
{ } Criteria-Based JSON
This tab displays a JSON result of combining the condition structure, the criterionBaseName(s), and the current data of the TildeCriterion(s).
  • This is the logic-level representation, where UI-specific (~) details are removed.
{ } Field-Based JSON
This tab displays a JSON result of combining the conditional structure and field(s) with their current data.
  • This is the final representation used for API requests.
Field-Based JSON is a complete JSON payload that can be sent directly to the server for filtering data. Note: Before querying, a FilterCriteria object is automatically created from the FilterModel, and you can retrieve this JSON from it.
Block.performQuery()
@override
Future<ApiResult<PageData<ProductInfo>?>> performQuery({
  required Object? parentBlockCurrentItem,
  required Product77aFilterCriteria filterCriteria,
  required SortableCriteria sortableCriteria,
  required Pageable pageable,
}) async {
  return await productRestProvider.queryWithFieldBasedJSON(
    pageable: pageable,
    fieldBasedJSON: filterCriteria.fieldBasedJSON,
  );
}
toFieldValue()
Note: The data types of the fields are simple types (String, int, double, bool), so in some cases you need to provide a toFieldValue() conversion function like the one below:
defineFilterModelStructure()
@override
FilterModelStructure defineFilterModelStructure() {
  return FilterModelStructure(
    criteriaStructure: FilterCriteriaStructure(
      simpleCriterionDefs: [
        SimpleFilterCriterionDef<double>(criterionBaseName: "price"),
      ],
      multiOptCriterionDefs: [
        // Multi Options Single Selection Criterion.
        MultiOptFilterCriterionDef<CategoryInfo>.singleSelection(
          criterionBaseName: "category",
          fieldName: 'categoryId',
          toFieldValue: (CategoryInfo? rawValue) { // <---------
            return SimpleVal.ofInt(rawValue?.id);
          },
        ),
      ],
    ),
    ...
  );
}

2. Conclude

Think of FilterModel as a 3-step pipeline:
  • Users input values on the UI (FilterPanel) → Each input maps to a tildeCriterionName
  • UI values are grouped into logical filtering criteria → UI-specific details (~) are removed
  • Criteria are transformed into primitive data for API requests → Uses field + value
Even simpler way to think
  • Tilde = what the user sees
  • Criteria = what the system understands
  • Field = what the server needs

3. FilterCriteria

To view the Debug information for FilterCriteria, you can use the Debug Filter Criteria Inspector:
No ADS

FlutterArtist

Show More
No ADS