Flow card arguments are passed as an input to your Flow card, users can pick the argument values when creating or editing a Flow.
Arguments must have a type that determines how they are shown. For example, a dropdown argument allows a user to pick one value from a predefined set of options, whereas a text argument shows an input field.
Don't overuse arguments! In our experience, Flow cards with just one or two arguments are the most popular.
Argument Types
The following are all available argument types that you can use in your Flow cards and the options that you can use with those types.
Text
"type": "text"
Regular text input. Text, Number and Boolean tokens can be dropped in this field as well.
This is the same as a text input, but with an additional autocomplete popup. The returned value when the card is run, is one of the objects provided in the autocomplete array. In order to provide autocomplete results you need to register an autocomplete listener for the Flow card with FlowCard#registerArgumentAutocompleteListener()
{"title": { "en":"Play an Artist" },"titleFormatted": { "en":"Play an Artist [[artist]]" },"args": [ {"type":"autocomplete","name":"artist","title": { "en":"Artist" },"placeholder": { "en":"Ludwig van Beethoven" } } ]}
/app.js
constHomey=require('homey');classAppextendsHomey.App {asynconInit() {constlaunchAppCard=this.homey.flow.getActionCard("play_artist");launchAppCard.registerArgumentAutocompleteListener("artist",async (query, args) => {constresults= [ { name:"Wolfgang Amadeus Mozart", description:"Joannes Chrysostomus Wolfgangus Theophilus Mozart", icon:"https://path.to/icon.svg",// For images that are not svg use:// image: 'https://path.to/icon.png',// You can freely add additional properties// that you can access in registerRunListener id:"...", }, ];// filter based on the queryreturnresults.filter((result) => {returnresult.name.toLowerCase().includes(query.toLowerCase()); }); } ); }}module.exports= App;
If you don't filter based on the query, it will cause the autocomplete results to appear unresponsive. The easiest way to filter the results is to compare name and query in lowercase as shown above.
Number
"type": "number"
Regular text input. Tokens can be dropped in this field as well.
A color picker that returns a HEX color, e.g. #FF0000.
Example
/.homeycompose/flow/actions/set_tile_color.json
{"title": { "en":"Set tile color" },"titleFormatted": { "en":"Set tile color to [[background]]" },"args": [ {"type":"color","name":"background" } ]}
Droptoken
A droptoken is a special Flow card Argument that only allows the user to enter a Flow Token or Homey Logic variable. You can add a droptoken to your Flow card by specifying, for example, "droptoken": ["number"]. You can use the any of the following types: string, number, boolean or image. A Flow card can only have a single droptoken but you can specify multiple allowed types.
Droptokens are possibly null. Make sure to verify the droptoken exists before using it.
When you add a device argument to your flow card, and provide a driver_id filter, e.g. "filter": "driver_id=yourdriverid", the Flow card will only be displayed for devices that belong to that specific driver.
If the device was already there because the device's class is a supported device class (e.g. light), your cards will be appended to the existing stack of cards. An example would be a Light driver that has a 'disco' mode, next to on/off, dim and color.
If the card has more than one device fields, the other fields will behave like an autocomplete-like argument, which show devices paired in your app.
{"title": { "en": "I will show up under all devices with a driver id of mydriver and with the custom capability id mycustomcapability."
},"args": [ {"type":"device","name":"device","title": { "en":"Device" },"filter":"driver_id=mydriver&capabilities=mycustomcapability" } ]}
Optional arguments
By default all Flow card arguments are required however if you want to allow an argument to be optional you can set the required property to false.
If an argument is not required and is not provided by the user it may be undefined in your Flow card run handler.
If you are creating an Action Flow card, a card for the ...then column, you can set the duration property. This property allows users to choose a duration for the action. If a user provides this argument to the Flow card, it will be passed to the card handler as an argument named duration in milliseconds.
"duration": true has precedence over an argument with "name": "duration" as they are both provided as arguments to the same handler. You should not create a Flow card with the duration property and an argument named "duration".
constHomey=require('homey');classAppextendsHomey.App {asynconInit() {construnAnimationAction=this.homey.flow.getActionCard("run_animation");runAnimationAction.registerRunListener(async (args, state) => {if (args.duration !=null) {// do something with the duration// (e.g. run an animation for duration milliseconds) } }); }}module.exports= App;
Subscribing to argument changes
It might be useful to know when a trigger has changed. For example a Twitter app may have a Flow card that triggers a Flow when a specific hashtag is tweeted. In order to implement this behaviour the app needs to know what hashtags to search for. By subscribing to argument changes the app knows when the argument values have changed and update the list of hashtags it is looking for.
When a Flow is triggered and the Flow Trigger card has arguments, your app needs to validate that the current state matches with the arguments the user chose for the Flow. This listener is executed for each Flow that uses this Flow Trigger card.
For example, a rain_start Flow Trigger card can have a location argument so that the Flow is only triggered when it is raining in the place the user has selected.
constHomey=require('homey');constRainApi=require('rain-api');classAppextendsHomey.App {asynconInit() {constrainStartTrigger=this.homey.flow.getTriggerCard("rain_start");rainStartTrigger.registerRunListener(async (args, state) => {// args is the user input,// for example { 'location': 'New York' }// state is the parameter passed in trigger()// for example { 'location': 'Amsterdam' }// If true, this flow should runreturnargs.location ===state.location; });RainApi.on('raining', (city, amount) => {consttokens= { mm_per_hour: amount }; // for example 3conststate= { location: city }; // for example "Amsterdam"// trigger the cardrainStartTrigger.trigger(tokens, state).then(this.log).catch(this.error); }); }}module.exports= App;