Using Node + Mongoose, I've got something that works, but I wonder if I'm missing an easier way to do this.
I have a mongoose schema called ClipsConfiguration with the following:
exclude_words: {
type: [String],
default: undefined,
set: function (v) {
return typeof v === "object"
? v.filter((elm) => elm !== "")
: undefined;
},
},
- I have a page (jade template) that allows you to edit this field using an html multiple select (named "excluded_phrases") using Bootstrap5 tags, see https://github.com/lekoala/bootstrap5-tags
input(hidden, value="", name="exclude_words")
select.form-select#exclude_words(name="exclude_words", multiple, data-allow-new="true", data-allow-clear="true", data-placeholder="type words or phrases and hit enter")
if config.exclude_words
each phrase in config.exclude_words
option(value="#{phrase}", selected) #{phrase}
The hidden input ensures that exclude_words always exists in the form data, even if there are no selected options in the select.
Then in my POST method, I currently do this in code when creating a new config doc or finding an existing config doc, then saving.
config = await Configuration.findOne({
user_id: req.user._id,
});
if (!config) {
config = new ClipsConfiguration(req.body);
config.user_id = req.user._id;
config.token = uuidv4();
} else {
config.set(req.body);
}
config.save();
The outcome is that if the select element has no options, the form data still contains an empty string. The set method on the mongoose schema checks to see if the submitted data is an array. If it is, it filters out the empty string from the submitted contents. If it's only the empty string from the hidden input, it saves the value as undefined, thus removing the field from the mongo document.
This behaves as I need it to, but my question is, have I created something more complicated than necessary?