rasteiner / k3-whenquery
Conditionally show fields and sections. Better.
Installs: 12 387
Dependents: 0
Suggesters: 0
Security: 0
Stars: 66
Watchers: 6
Forks: 1
Open Issues: 4
Language:TypeScript
Type:kirby-plugin
Requires
- getkirby/cms: >=3.8
- getkirby/composer-installer: ^1.2
README
Conditionally show fields and sections. Better.
Installation
Download
Download and copy this repository to /site/plugins/k3-whenquery
.
Git submodule
git submodule add https://github.com/rasteiner/k3-whenquery.git site/plugins/k3-whenquery
Composer
composer require rasteiner/k3-whenquery
Use
Add a whenQuery
property to your fields and sections. The expression in this query will be evaluated in real time in the browser to hide the section or field when it evaluates to a falsy value.
title: Woofler page fields: foosables: type: select label: Foosables options: gerryconas: Gerryconas peterwands: Peterwands perlskippies: Perl Skippies barsters: type: range label: Barsters warning: type: info label: Woofling warning text: Having more than 30 Barsters is **not recommended** while wooffling Gerryconas. theme: negative whenQuery: foosables = 'gerryconas' && barsters > 30
Expression Language Syntax
There are no assignments and function calls (it's meant to be as harmless as possible).
Since there are no assignments, =
is an equality comparison (there is no ==
).
Supported operators
... = ...
: Equals... != ...
: Not equals... < ...
: Less than... > ...
: Greater than... <= ...
: Less or equal... >= ...
: Greater or equal... =~ ...
: Search something in something (see below)... ?? ...
: Nullish coalescing operator... ? ... : ...
: Ternary operator... || ...
: Logical Or... && ...
: Logical And... + ...
: String concatenation or Number addition... - ...
: Number subtraction... * ...
: Number multiplication... / ...
: Number division... % ...
: Remainder operator(...)
: Precedence grouping...[...]
: Optional subscript operator (calculated member access).
: Optional member access by identifier... ::map(...)
: Arraymap
operator (see below)... ::filter(...)
: Arrayfilter
operator (see below)... ::count(...)
: Arraycount
operator (see below)... ::any(...)
: Arrayany
operator (see below)... ::all(...)
: Arrayall
operator (see below)... ::reduce(...)
: Array Reducer (see below)
Member Access is always "optional": it does never throw an error if you access a property of undefined; it just evaluates to undefined
. In short, .
behaves like javascript's ?.
and a[something]
behaves like a?.[something]
.
The search operator =~
is a multifunction tool: it behaves differently depending on the type of its operands:
"string" =~ "tri"
: string on string, returnstrue
if a string contains another[a,b,c] =~ a
: element on array, returnstrue
if an element is present in an array. This case can optionally also be written in the reverse order:a =~ [a,b,c]
[a,b,c] =~ [b,c]
: array on array, returnstrue
if all elements of the right hand side are present in the left hand side array.12 =~ 2
: number on number, returnstrue
if "left" is divisible by "right" (left % right = 0
)."string" =~ /inG$/i
: regex on string, returnstrue
if the string matches the regex. RegExes are useful only in combination with the search operator.
There's also support for String, Number, Boolean (true
, false
), Object and Array literals.
Array operators
::map(expr)
: replaces each item in the array with the right hand side expression::filter(expr)
: filters the array by evaluating right hand side expression::count(expr)
: counts all items in the array that return true for the right hand side expression::any(expr)
: returnstrue
if at least 1 item in the array returns true for the right hand side expression,false
otherwise::all(expr)
: returnstrue
if all items in the array return true for the right hand side expression,false
otherwise
General syntax:
Array operators are made of 3 parts:
- In the left the array they operate on
- after
::
the name of the operation - between the parentheses the expression that is evaluated for each array item.
Inside of the parentheses, the symbol $
represents the "current" item.
Example
fields: blocks: type: blocks imagesEncouragement: type: info label: Nice job! text: Good! You have at least 13 images in this post. This will be a **great** post. theme: positive whenQuery: blocks ::count($.type = 'image') >= 13
Array reducers
Array reducers are functions that take an array and return a single value. They can be used to aggregate values in an array.
The syntax is similar to the array operators, but ::reduce(expr, ?initial)
accepts an optional initial value. If no initial value is provided, the first item of the array is used.
Inside of the parentheses, the symbol $
represents the "current" item, while $1
represents the return value of the "previous" iteration (aka the "accumulator").
The array is always traversed left to right.
Example
fields: percentages: type: structure fields: percent: type: number after: "%" percentagesEncouragement: type: info label: Math GENIUS! text: Great job! The sum of all percentages is exactly 100%. theme: positive whenQuery: percentages ::reduce($1 + $.percent, 0) = 100
An example usage without an initial value:
whenQuery: percentages ::map($.percent) ::reduce($1 + $) = 100
Variables lookup
Content variables
By default, any valid identifier refers to the "current" fieldset. This means that page fields could be shadowed by other fields with the same name in a structure or block, when the query is executed in such structure or block. If no field is found in the current fieldset, the query is evaluated in the page fields.
Model variables
The Site, Pages, Files and Users are "models". Other than content, they also have other properties that might be useful in a query.
These properties are accessible by prepending an underscore (_
) to their name, when (and only when) the query is being executed inside of their respective View.
The accessible Site properties are:
_title
: the title of the site
The accessible Page properties are:
_status
: the status of the page (one of 'draft', 'unlisted' or 'listed')_id
: the id of the page_title
: the title of the page
The accessible User properties are:
_id
: the id of the user_email
: the email of the user_name
: the name of the user_username
: the username of the user (either the name or the email as fallback)_language
: the language of the user_role
: the role name of the user (e.g. "Admin" with a capital "A")_avatar
: the url of the user's avatar_account
: boolean indicating if this is the current user's account
The accessible File properties are:
_dimensions.width
: If the file is an image, the width of the image_dimensions.height
: If the file is an image, the height of the image_dimensions.ratio
: If the file is an image, the ratio of the image_dimensions.orientation
: If the file is an image, one of "landscape", "square" or "portrait"_extension
: the extension of the file (e.g. "jpg", "png", "gif")_filename
: the filename of the file_mime
: the mime type of the file_niceSize
: the nice size of the file (e.g. "1.2 MB", "2.3 KB")_template
: the file template_type
: the file type, any of "archive", "audio", "code", "document", "image", "video" or null_url
: the media url to the file
Example
fields: date: type: date dateInfo: type: info label: Heads up! text: This page is listed, its date will be ignored for sorting. theme: positive whenQuery: date && _status = 'listed'
Known issues
- This plugin extends and replaces the default
Blocks
andLayout
field types. This means that it is not compatible with other plugins that do the same.