I’ve been working with tags in different applications for a while and every time I use them, I write the functionality from scratch. It’s not complicated, but by rewriting the code, I always tend to neglect safety checks and nice to have features.
What are tags? It’s a string that contains elements, aka tags, that are separated by a comma:
- jan,feb,dec
- newsletter 08-24, holiday card 2024, invitation summer party 2025
Yesterday, Stephan posted in the TapForms forum requesting the same functionality. While I shared a solution using my code, it sparked an idea. The result is a class that encapsulates all tag handling and includes features such as sorting and tag removal. I’ll provide detailed documentation for the class later, but here’s an example of it in action with a prompter. It provides the additional option to add or remove a tag.
This script uses all records of the currently selected search. But it can work on a saved search, or on all records as well. Just comment/uncomment the respective code sections.
For the script to work, the field id constants name_id and tags_id need to be defined according to your form. name_id is used in the console log to provide some infos on which record the script is running. tag_id is the field where you collect your tags.
var prompterVarTask;
var prompterVarText;
class tagHandler {
// class methods
constructor(init, separator=",") {
this.separator = separator;
if (init == null){
this.tags = new Array();
} else {
this.tags = init.split(this.separator);
// remove leading and trailing spaces
this.tags = this.tags.map(el => el.trim());
// remove empty elements
this.tags = this.tags.filter(function (el) {
return el != "";
});
this.tags = [...new Set(this.tags)]; // make tags unique
}
}
// add a new tag. if empty, it's ignored.
add(tag){
if (tag){
this.tags.push(tag.trim());
this.tags = [...new Set(this.tags)]; // make tags unique, prevents duplicates
}
}
// removes tag
remove(tag){
const index = this.tags.indexOf(tag);
this.tags.splice(index, 1);
}
// sorts the tag. sort function can be provided for specific sorts
sort(fcnt){
if (fcnt){
this.tags.sort(fcnt);
} else {
this.tags.sort();
}
}
// returns all the tags formatted as a string
toString(sep=this.separator){
return this.tags.join(sep);
}
}
function callbackSetTag() {
const name_id = 'fld-34101f547a2a4ae39bb8b205910ac13c';
const tags_id = 'fld-9146bd6ba97541adb47c95da52996a85';
if (!prompterVarTask){
console.log("Task not defined! Aborting!", "#ff0000");
return;
}
// get records from current search
let recs = search.getRecords();
// // get records from a saved search
// let recs = form.getSearchNamed('Selected').getRecords();
// // use all records
// let myRecords = form.getRecords();
console.log('Found ' + recs.length + ' records');
for (rec of recs){
console.log("Processing " + rec.getFieldValue(name_id))
// load initial values
let tags = new tagHandler(rec.getFieldValue(tags_id));
// check task to be performed
if (prompterVarTask == 'add tag'){
// add new tag
tags.add(prompterVarText);
} else if (prompterVarTask == 'delete tag'){
// add new tag
tags.remove(prompterVarText);
}
// save new tags
rec.setFieldValue(tags_id, tags.toString(", "));
console.log("Updated tags: " + tags.toString(", "));
}
document.saveAllChanges();
};
function setTag(){
let task = ['add tag', 'delete tag'];
let prompter = Prompter.new();
prompter.addParameter('Select Task', 'prompterVarTask', 'popup', task)
.addParameter('Tag', 'prompterVarText', 'text')
.show('Add Tag to current record', callbackSetTag);
}
setTag();
Did you like this post? Did you use the given code? Please consider supporting me by buying me a coffee!
Thanks!