Directus Driver
ArchivedThese are the docs for ng-qubee 3.8. Read the 4.0 docs for @qubeejs/angular.
Targets Directus — the popular open-source headless CMS and data platform, with its underscore-prefixed operators inside a nested bracket filter syntax.
Configure
Section titled “Configure”import { DriverEnum, provideNgQubee } from 'ng-qubee';
bootstrapApplication(AppComponent, { providers: [provideNgQubee({ driver: DriverEnum.DIRECTUS })]});Wire format
Section titled “Wire format”| Concern | Output |
|---|---|
| Filters (single value) | filter[field][_eq]=value |
| Filters (multi-value) | filter[field][_in]=v1,v2 (CSV) |
| Operator filters | filter[field][_op]=value — full FilterOperatorEnum mapping below |
| Sort | sort=likeCount,-createdDate (CSV, - prefix = DESC) |
| Fields / relations | one fields= CSV: fields=title,author.id,comments.* |
| Search | search=term (global full-text search) |
| Metadata | meta=total_count,filter_count (always emitted) |
| Pagination | limit=N&page=N (1-indexed page) |
The filter / sort / fields / search / limit / page keys honour IConfig.request overrides (their defaults already match the Directus wire format); meta is fixed.
Operator filters
Section titled “Operator filters”FilterOperatorEnum translates to Directus’ underscore operators:
import { FilterOperatorEnum } from 'ng-qubee';
qb.addFilterOperator('likeCount', FilterOperatorEnum.GTE, 4); // filter[likeCount][_gte]=4qb.addFilterOperator('title', FilterOperatorEnum.CONTAINS, 'world'); // filter[title][_contains]=worldqb.addFilterOperator('title', FilterOperatorEnum.ILIKE, 'World'); // filter[title][_icontains]=Worldqb.addFilterOperator('title', FilterOperatorEnum.SW, 'Intro'); // filter[title][_starts_with]=Introqb.addFilterOperator('id', FilterOperatorEnum.IN, 1, 2, 3); // filter[id][_in]=1,2,3qb.addFilterOperator('status', FilterOperatorEnum.NOT, 'draft'); // filter[status][_neq]=draftqb.addFilterOperator('status', FilterOperatorEnum.NOT, 'a', 'b'); // filter[status][_nin]=a,bqb.addFilterOperator('deletedAt', FilterOperatorEnum.NULL, true); // filter[deletedAt][_null]=trueqb.addFilterOperator('deletedAt', FilterOperatorEnum.NULL, false); // filter[deletedAt][_nnull]=trueqb.addFilterOperator('price', FilterOperatorEnum.BTW, 10, 50); // filter[price][_between]=10,50Translation table
Section titled “Translation table”FilterOperatorEnum |
Directus operator |
|---|---|
EQ |
_eq |
GT / GTE / LT / LTE |
_gt / _gte / _lt / _lte |
CONTAINS |
_contains |
ILIKE |
_icontains (case-insensitive contains) |
IN |
_in (CSV) |
SW |
_starts_with |
BTW |
_between with min,max (arity-checked) |
NOT (single) |
_neq |
NOT (multi) |
_nin (CSV) |
NULL (true) |
_null=true |
NULL (false) |
_nnull=true |
FTS / PHFTS / PLFTS / WFTS |
unsupported — throws UnsupportedFilterOperatorError |
Value shape rules
Section titled “Value shape rules”Enforced at call time — both throw InvalidFilterOperatorValueError:
BTWrequires exactly 2 values (min,max).NULLrequires exactly 1 boolean value (true→_null=true,false→_nnull=true).
Other operators leave shape validation to the server.
Fields and relations
Section titled “Fields and relations”Directus has no standalone include parameter — relational data travels through dot paths in the single fields= CSV, so addSelect, addIncludes, and addEmbedded all fold into it:
qb.addSelect('title'); // fields=titleqb.addIncludes('author'); // fields=*,author.*qb.addEmbedded('author', 'id', 'name'); // fields=*,author.id,author.name
qb.addSelect('title').addEmbedded('author', 'id');// → fields=title,author.idWith relations but no flat addSelect, the flat part defaults to * so the base item’s columns stay in the projection. A relation present in both addIncludes and addEmbedded folds into the embedded fragment, which carries the column projection. Directus’ deep[...] relational query options and nested relation filtering are out of scope.
Feature matrix
Section titled “Feature matrix”| Method | Supported? | Notes |
|---|---|---|
addFilter / deleteFilters |
✓ | Folds to _eq (single) or _in CSV (multi) |
addFilterOperator / deleteOperatorFilters |
✓ | See translation table above |
addSort / deleteSorts |
✓ | CSV sort= with - prefix for DESC |
setLimit / setPage |
✓ | limit + page (1-indexed) |
addSelect / deleteSelect |
✓ | Flat columns in the fields= CSV |
addFields / deleteFields / deleteFieldsByModel |
✗ | No per-model field selection — use dot paths via addEmbedded |
addIncludes / deleteIncludes |
✓ | rel.* entries in the fields= CSV |
addEmbedded / deleteEmbedded |
✓ | rel.col dot-projected entries in the fields= CSV |
setSearch / deleteSearch |
✓ | search=term global search |
Response shape
Section titled “Response shape”{ "data": [{ "id": 1, "title": "Hello" }], "meta": { "total_count": 48, "filter_count": 12 }}DirectusResponseStrategy reads data and defaults total to meta.filter_count — the count matching the current filter, which is the relevant total for paging a filtered collection. Point the path at meta.total_count if you want the unfiltered collection size:
provideNgQubee({ driver: DriverEnum.DIRECTUS, response: { total: 'meta.total_count' }});Defaults are encoded in DirectusResponseOptions.