+ // For external use
+ add() {
+ const clone = this.modelRow.cloneNode(true);
+ clone.classList.remove('hidden');
+ this.setClonedInputNames(clone);
+ this.modelRow.parentNode.insertBefore(clone, this.modelRow);
+ window.$components.init(clone);
+ }
+
+ /**
+ * Update the HTML names of a clone to be unique if required.
+ * Names can use placeholder values. For exmaple, a model row
+ * may have name="tags[randrowid][name]".
+ * These are the available placeholder values:
+ * - randrowid - An random string ID, applied the same across the row.
+ * @param {HTMLElement} clone
+ */
+ setClonedInputNames(clone) {
+ const rowId = uniqueId();
+ const randRowIdElems = clone.querySelectorAll('[name*="randrowid"]');
+ for (const elem of randRowIdElems) {
+ elem.name = elem.name.split('randrowid').join(rowId);
+ }
+ }
+
+}