I am struggling with ics.js (https://github.com/nwcell/ics.js/)
It is ignoring rules for repeat events set up in rrules
It is not allowing me to add another event from another .ics file after I have added a first one. However, if I delete the first one, I can add the second one.
I am unable to add a calendar event using a JavaScript object.
var myfunc = function(e) { let target = e.currentTarget; if (target.tagName != 'X-EVENT') { throw "downloadEvent is for use on x-events only"; } let form = target.querySelector("form"); let fd = new FormData(form); //console.log(fd.has('subject')); let recur = fd.get("freq") != "none"; let rRule = recur ? {"freq" : fd.get("freq"), "interval" : fd.get("interval"), "byday" : fd.getAll("byday"), "until" : fd.get('until') } : null; let cal = ics(); // cal.addEvent(eventData); cal.addEvent(fd.get("subject"),fd.get("description"), fd.get("location"), fd.get("start"), fd.get("end"), rRule); cal.download(fd.get("subject")); }
As you can infer from the code snippet above, I create adding an event as an object but that failed.
How can I fix this code so that the reoccurrence instructions in rRule are obeyed?
-- edit --
The code for how I am setting up the controls is:
let form = document.createElement("FORM");
element.appendChild(form);
let h = document.createElement("H1");
h.textContent = "Event";
form.appendChild(h);
let evtTable = document.createElement("TABLE");
evtTable.setAttribute("contentEditable", "false");
form.appendChild(evtTable);
let createRow = function(name) {
let row = evtTable.insertRow();
let cell = row.insertCell();
cell.textContent = name;
cell = row.insertCell();
let input = document.createElement("Input");
input.name = name.replace(/\s/,"").toLowerCase();
if (element.hasAttribute(input.name)) {
input.value = element.getAttribute(input.name);
}
cell.appendChild(input);
return row;
}
createRow("Subject");
createRow("Description");
createRow("Location");
row = createRow("Start");
input = row.cells[1].querySelector("input");
console.log("input.name: " + input.name);
input.type = "datetime-local";
row = createRow("End");
input = row.cells[1].querySelector("input");
input.type = "datetime-local";
row = createRow("Repeat");
row.cells[0].title = "Only available for single day events";
input = row.cells[1].querySelector("input");
input.type = "radio";
input.name = "freq";
input.value = "none";
input.checked = true;
row.cells[1].insertBefore(document.createTextNode("None"), input);
row.cells[1].appendChild(document.createTextNode("Day"));
let input2 = document.createElement("input");
input2.name = "freq";
input2.value = "DAILY";
input2.type = "radio";
row.cells[1].appendChild(input2);
row.cells[1].appendChild(document.createTextNode("Week"));
input2 = document.createElement("input");
input2.name = "freq";
input2.value = "WEEKLY";
input2.type = "radio";
row.cells[1].appendChild(input2);
row.cells[1].appendChild(document.createTextNode("Month"));
input2 = document.createElement("input");
input2.name = "freq";
input2.value = "MONTHLY";
input2.type = "radio";
row.cells[1].appendChild(input2);
row = createRow("Weekly Days");
row.cells[0].title = "Days of the week for weekly reoccurance";
input = row.cells[1].querySelector("input");
let cell = row.cells[1];
cell.insertBefore(document.createTextNode("Su"), input);
input.type = "checkbox";
input.name = "byday";
input.value = "SU";
cell.appendChild(document.createTextNode("M"));
input2 = document.createElement("INPUT");
input2.type = "checkbox";
input2.name = "byday";
input2.value = "MO";
cell.appendChild(input2);
cell.appendChild(document.createTextNode("Tu"));
input2 = document.createElement("INPUT");
input2.type = "checkbox";
input2.name = "byday";
input2.value = "TU";
cell.appendChild(input2);
cell.appendChild(document.createTextNode("We"));
input2 = document.createElement("INPUT");
input2.type = "checkbox";
input2.name = "byday";
input2.value = "WE";
cell.appendChild(input2);
cell.appendChild(document.createTextNode("Th"));
input2 = document.createElement("INPUT");
input2.type = "checkbox";
input2.name = "byday";
input2.value = "TH";
cell.appendChild(input2);
cell.appendChild(document.createTextNode("Fr"));
input2 = document.createElement("INPUT");
input2.type = "checkbox";
input2.name = "byday";
input2.value = "FR";
cell.appendChild(input2);
cell.appendChild(document.createTextNode("Sa"));
input2 = document.createElement("INPUT");
input2.type = "checkbox";
input2.name = "byday";
input2.value = "SA";
cell.appendChild(input2);
row.querySelectorAll("select, input, textarea").forEach ((input) => {
input.disabled = true;
});
row = createRow("Interval");
row.cells[0].title = "1 = every week, 2 = every 2 weeks";
input = row.cells[1].querySelector("input");
input.type = "number";
input.name = "interval";
input.min = 1;
input.max = 12;
input.value = 1;
row.querySelectorAll("select, input, textarea").forEach ((input) => {
input.disabled = true;
});
row = createRow("Until");
row.cells[0].title = "Reoccur until this date";
input = row.cells[1].querySelector("input");
input.type = "date";
input.name = "until";
Sections.calTableInputFunc(element, true);
row.querySelectorAll("select, input, textarea").forEach ((input) => {
input.disabled = true;
});
//console.log(JSON.stringify(formValues));
//console.log("element html: " + element.outerHTML);
//}
}
Sections.calTableInputFunc = (xEvent, enable) => {
let changeFunc = (ev) => {
ev.target.closest("x-event").setAttribute(ev.target.name, ev.target.value);
let evtTable = xEvent.querySelector("table");
let startRow = 6;
if (ev.target.getAttribute("name") == "freq") {
evtTable.rows[startRow].querySelectorAll("select, input, textarea").forEach ((input) => {
input.disabled = ev.target.value == "none";
});
evtTable.rows[startRow + 1].querySelectorAll("select, input, textarea").forEach ((input) => {
input.disabled = ev.target.value == "none";
});
evtTable.rows[startRow + 2].querySelectorAll("select, input, textarea").forEach ((input) => {
input.disabled = ev.target.value == "none";
});
}
}
if (enable) {
xEvent.querySelector("table").querySelectorAll("INPUT, TEXTAREA").forEach((elem) => elem.addEventListener("change", changeFunc));
} else {
xEvent.querySelector("table").querySelectorAll("INPUT, TEXTAREA").forEach((elem) => elem.removeEventListener("change", changeFunc));
}
}
-- edit 2 --
I got the following example from Google AI that uses an r(ecurrent) rule. Seeing this fail has me thinking that this could very well be an issue with calendars not supporting the "rrule" protocol. I am going to vote to close this question as not being the correct source of my problem.
// Initialize the ics.js object
var cal = ics();
// Define the recurrence rule (rrule) for a weekly event
var rrule = {
freq: 'WEEKLY', // Event repeats weekly
interval: 1, // Every week
byday: ['MO', 'WE', 'FR'], // On Mondays, Wednesdays, and Fridays
until: new Date(2026, 0, 31) // Repeats until January 31, 2026
};
// Add the recurring event
cal.addEvent(
'Weekly Team Meeting', // Subject
'Discussion on project progress', // Description
'Conference Room A', // Location
'2025-09-22 09:00', // Begin date and time (first occurrence)
'2025-09-22 10:00', // End date and time (first occurrence)
rrule // The recurrence rule object
);
// Download the generated ICS file
cal.download('my_recurring_events');