How to Create a Custom Calendar View for a DocType in Frappe/ERPNext
Calendar ViewLearn to configure a custom calendar view in Frappe/ERPNext by creating a doctype_calendar.js file and a get_events Python method. Guide covers field mapping and filters.
Frappe Framework provides a powerful, out-of-the-box calendar view that can be configured for any DocType. This feature is ideal for visualizing records that have a start and end date, such as tasks, meetings, appointments, or timesheets.
To enable this view, you need to create a simple JavaScript configuration file that tells the framework how to map your DocType's fields to the calendar's properties. This snippet demonstrates the complete client-side configuration required.
1 frappe.views.calendar["Timesheet"] = { // Doctype Name 2 field_map: { 3 "start": "start_date", //datefield 4 "end": "end_date", // datefield 5 "id": "name", 6 "allDay": "allDay", 7 "child_name": "name", 8 "title": "title" 9 }, 10 //optional 11 style_map: { 12 "0": "info", 13 "1": "standard", 14 "2": "danger" 15 }, 16 gantt: true, 17 filters: [ 18 { 19 "fieldtype": "Link", 20 "fieldname": "project", 21 "options": "Project", 22 "label": __("Project") 23 }, 24 { 25 "fieldtype": "Link", 26 "fieldname": "employee", 27 "options": "Employee", 28 "label": __("Employee") 29 } 30 ], 31 // Custom Function created in [docmodule].[doctype].[docname].py file 32 get_events_method: "erpnext.projects.doctype.timesheet.timesheet.get_events" 33 }
Understanding This Code
What It Does
This script configures the calendar view for a specified DocType (e.g., 'Timesheet'). It maps DocType fields to calendar event properties like start date, end date, and title, sets up user filters, and specifies the server-side Python method responsible for fetching the event data.
When To Use
Use this script when you need to provide users with a visual, date-based representation of records from a DocType. It's ideal for tracking appointments, project tasks, leave applications, or any time-sensitive data.
Prerequisites
- •A Frappe DocType with at least one Date or Datetime field to serve as the start date.
- •A corresponding server-side Python method to fetch and return event data.
Key Concepts
Important ideas to understand in this code
frappe.views.calendar
A global JavaScript object in the Frappe Framework where developers define custom view configurations. By adding a key with your DocType's name, you instruct the framework on how to render it in a calendar format.
Learn morefield_map
This object is crucial for the calendar view. It maps the standard calendar event properties (like 'start', 'end', 'title') to the actual fieldnames in your DocType, telling the calendar which data to display where.
Learn moreget_events_method
This property specifies the dotted path to the Python function on the server that will be called to fetch the calendar events. This function must be whitelisted and must accept 'start' and 'end' date arguments.
Learn morefilters
An optional array of objects that defines filter fields to be displayed above the calendar. This allows users to narrow down the displayed events based on criteria like a linked DocType.
Learn moreStep-by-Step Tutorial
Follow along to understand how this code works
Create the Calendar JavaScript File
In your custom app, navigate to your DocType's folder (e.g., `my_app/my_app/doctype/my_doctype/`). Create a new file named `my_doctype_calendar.js`. This naming convention is essential for Frappe to automatically load the script.
// File: my_app/my_app/doctype/my_doctype/my_doctype_calendar.jsDefine the Client-Side Configuration
In the new JS file, add the configuration object. Replace 'My DocType' with your DocType's name. Map the `start`, `end`, and `title` fields to the corresponding fieldnames in your DocType. Finally, specify the Python method path that will fetch the data.
frappe.views.calendar["My DocType"] = {
field_map: {
"start": "your_start_date_field",
"end": "your_end_date_field", // Optional
"id": "name",
"title": "your_title_field"
},
get_events_method: "my_app.my_app.doctype.my_doctype.my_doctype.get_events"
};Create the Server-Side Python Method
Open the `my_doctype.py` file. Create a Python function named `get_events`. This function must be whitelisted using the `@frappe.whitelist()` decorator and must accept `start`, `end`, and optional `filters` as arguments. It should return a list of dictionaries.
import frappe
from frappe.utils import get_datetime
@frappe.whitelist()
def get_events(start, end, filters=None):
# Query your DocType for records between the given dates
event_docs = frappe.get_all(
"My DocType",
fields=["name", "your_title_field", "your_start_date_field", "your_end_date_field"],
filters=[
{"your_start_date_field": ["<=", end]},
{"your_end_date_field": [">=", start]}
]
)
events = []
for doc in event_docs:
events.append({
"name": doc.name,
"title": doc.your_title_field,
"start": get_datetime(doc.your_start_date_field),
"end": get_datetime(doc.your_end_date_field),
})
return eventsBuild, Migrate, and Test
After saving both files, run `bench build` to bundle your new JavaScript asset and `bench migrate` to apply any server-side changes. Clear your browser cache and navigate to your DocType's list view. You should now see the 'Calendar' view option.
bench build && bench migrateCommon Issues & Solutions
Troubleshoot problems you might encounter