---
title: "Javascript Popup Event creation modal Example | Mobiscroll"
component: "Popup"
framework: "JavaScript"
library_version: "6.1.5"
url: "https://demo.mobiscroll.com/javascript/popup/add-event-modal"
---

# Event creation modal - JavaScript Popup demo

Use the Javascript popup for event add/edit modals. Trigger within the event calendar component and load your own custom forms. Plain JS api for usage everywhere.

- [Live demo](https://demo.mobiscroll.com/javascript/popup/add-event-modal)
- [View code on GitHub](https://github.com/acidb/mobiscroll-demos-javascript/tree/main/src/demos/pickers/popup/add-event-modal)
- This demo in other frameworks: [jQuery](https://demo.mobiscroll.com/jquery/popup/add-event-modal.md), [Angular](https://demo.mobiscroll.com/angular/popup/add-event-modal.md), [React](https://demo.mobiscroll.com/react/popup/add-event-modal.md), [Vue](https://demo.mobiscroll.com/vue/popup/add-event-modal.md)

## Description

Use the popup to show a modal with an add/edit form for event creation and/or update. The popup can be easily set up to be shown right in the middle of the screen, top, bottom or anchored to the newly added event. Check out the [different display modes](https://demo.mobiscroll.com/javascript/popup/mobile-desktop-display) and play around with the different configurations.

You have full control over what is shown within the popup. Use [Mobiscroll form elements](https://demo.mobiscroll.com/javascript/forms) or any components that you are already using throughout your application.

**Interested in exploring the event calendar?** [Check out these examples →](https://demo.mobiscroll.com/javascript/eventcalendar)

## What this demo shows

- Shows a full month calendar which displays events with a custom `Add new event` button above it.
- **Event creation** Clicking `Add new event` opens a popup containing an event form.
- **Event editing** The same popup supports updating an existing event.
- **Event form** The editor includes fields for the title, description, all-day setting, start and end dates, travel time, event color, and busy or free status.
- **Date selection** The start and end date inputs open a date picker with range selection.
- **Save and close behavior** Clicking outside the popup or selecting Cancel closes the editor without applying changes. Selecting Save applies the event changes.
- **Delete flow** The edit dialog includes a `Delete event` action that removes the event from the calendar.
- **Responsive behavior** The dialog adapts to the screen size and device type, with touch-optimized controls such as scrollers on smaller screens and touch devices.
- **Mobile presentation** On smaller screens, the dialog appears as a sheet instead of a popover.
- **Day cell states** Hovering over a day cell highlights the day number with a gray background. Clicking an empty area of the cell selects the day and highlights the day number with a blue background.

## Best for

- **Appointment scheduling** Collect event details, dates, travel time, and availability in a dedicated creation and editing form.
- **Field service calendars** Capture travel time and job details when scheduling work across different locations.
- **Team calendars** Use event colors and busy or free status to communicate event types and availability.
- **Responsive scheduling interfaces** Present the same event workflow as a popover on larger screens and a touch-friendly sheet on smaller screens.

## API used in this demo

- [`theme`](https://mobiscroll.com/docs/javascript/popup/api#opt-theme) - option
- [`themeVariant`](https://mobiscroll.com/docs/javascript/popup/api#opt-themeVariant) - option
- [`width`](https://mobiscroll.com/docs/javascript/popup/api#opt-width) - option
- [`headerText`](https://mobiscroll.com/docs/javascript/popup/api#opt-headerText) - option
- [`display`](https://mobiscroll.com/docs/javascript/popup/api#opt-display) - option
- [`buttons`](https://mobiscroll.com/docs/javascript/popup/api#opt-buttons) - option
- [`addEvent`](https://mobiscroll.com/docs/javascript/eventcalendar/api#method-addEvent) - method
- [`navigateToEvent`](https://mobiscroll.com/docs/javascript/eventcalendar/api#method-navigateToEvent) - method
- [`close`](https://mobiscroll.com/docs/javascript/popup/api#method-close) - method
- [`cssClass`](https://mobiscroll.com/docs/javascript/popup/api#opt-cssClass) - option
- [`showOverlay`](https://mobiscroll.com/docs/javascript/popup/api#opt-showOverlay) - option
- [`controls`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-controls) - option
- [`select`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-select) - option
- [`startInput`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-startInput) - option
- [`endInput`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-endInput) - option
- [`display`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-display) - option
- [`touchUi`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-touchUi) - option
- [`showOverlay`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-showOverlay) - option
- [`showRangeLabels`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-showRangeLabels) - option
- [`view`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-view) - option
- [`labels`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-labels) - option
- [`data`](https://mobiscroll.com/docs/javascript/eventcalendar/api#opt-data) - option
- [`open`](https://mobiscroll.com/docs/javascript/popup/api#method-open) - method
- [`setOptions`](https://mobiscroll.com/docs/javascript/datepicker/api#method-setOptions) - method

## Code

### JS

```js
mobiscroll.setOptions({
  theme: 'ios',
  themeVariant: 'light'
});

var eventStatus = document.getElementById('demo-popup-status-busy');
var eventTitle = document.getElementById('demo-popup-event-title');
var eventDescription = document.getElementById('demo-popup-event-description');
var eventAllDay = document.getElementById('demo-popup-all-day');

var myData = [
  {
    id: 1,
    start: '2026-10-08T13:00',
    end: '2026-10-08T13:45',
    title: "Lunch @ Butcher's",
    description: '',
    allDay: false,
    bufferBefore: 15,
    free: true,
    color: '#009788',
  },
  {
    id: 2,
    start: '2026-10-23T15:00',
    end: '2026-10-23T16:00',
    title: 'Conference',
    description: '',
    allDay: false,
    bufferBefore: 30,
    free: false,
    color: '#ff9900',
  },
  {
    id: 3,
    start: '2026-10-22T18:00',
    end: '2026-10-22T22:00',
    title: 'Site Visit',
    description: '',
    allDay: false,
    bufferBefore: 60,
    free: true,
    color: '#3f51b5',
  },
  {
    id: 4,
    start: '2026-10-24T10:30',
    end: '2026-10-24T11:30',
    title: 'Stakeholder mtg.',
    description: '',
    allDay: false,
    free: false,
    color: '#f44437',
  },
];

var popup = mobiscroll.popup('#demo-add-event-popup', {
  width: 400,
  contentPadding: false,
  headerText: 'Add new event',
  display: 'center',
  buttons: [
    'cancel',
    {
      text: 'Add',
      keyCode: 'enter',
      handler: function () {
        var eventTimes = range.getVal();
        var newEvent = {
          title: eventTitle.value,
          description: eventDescription.value,
          allDay: eventAllDay.value,
          status: eventStatus.value,
          start: eventTimes[0],
          end: eventTimes[1] || eventTimes[0],
        };
        calendar.addEvent(newEvent);
        calendar.navigateToEvent(newEvent);
        mobiscroll.toast({
          message: 'Event added',
        });
        popup.close();
      },
      cssClass: 'mbsc-popup-button-primary',
    },
  ],
  showOverlay: false,
});

var range = mobiscroll.datepicker('#demo-event-date', {
  controls: ['calendar', 'time'],
  select: 'range',
  startInput: '#demo-popup-start-input',
  endInput: '#demo-popup-end-input',
  display: 'anchored',
  touchUi: true,
  showOverlay: false,
  showRangeLabels: false,
});

var calendar = mobiscroll.eventcalendar('#demo-calendar', {
  view: {
    calendar: { labels: true },
  },
  data: myData,
});

document.getElementById('demo-popup-add-btn').addEventListener('click', function () {
  range.setVal([new Date(), new Date()]);
  mobiscroll.getInst(eventTitle).value = 'New Event';
  mobiscroll.getInst(eventDescription).value = '';
  mobiscroll.getInst(eventAllDay).checked = false;
  mobiscroll.getInst(eventStatus).checked = true;
  popup.open();
});

eventAllDay.addEventListener('change', function () {
  var checked = this.checked;
  // Change range settings based on the allDay
  range.setOptions({
    controls: checked ? ['calendar'] : ['calendar', 'time'],
  });
});
```

### HTML

```html
<div mbsc-page class="mds-full-height">
  <div class="mds-full-height mbsc-flex-col">
    <div class="mbsc-button-group-block">
      <button mbsc-button id="demo-popup-add-btn">Add new event</button>
    </div>
    <div style="display: none">
      <div id="demo-add-event-popup">
        <div class="mbsc-form-group">
          <label>
            Title
            <input mbsc-input id="demo-popup-event-title">
          </label>
          <label>
            Description
              <input mbsc-input id="demo-popup-event-description">
          </label>
        </div>
        <div class="mbsc-form-group">
          <label>
            All-day
            <input mbsc-switch type="checkbox" id="demo-popup-all-day"/>
          </label>
          <label>
            Starts
            <input mbsc-input id="demo-popup-start-input" />
          </label>
          <label>
            Ends
            <input mbsc-input id="demo-popup-end-input" />
          </label>
        </div>
          <div class="mbsc-form-group">
            <label>
              Show as busy
              <input id="demo-popup-status-busy" mbsc-segmented type="radio" name="event-status" value="busy">
            </label>
            <label>
              Show as free
              <input id="demo-popup-status-free" mbsc-segmented type="radio" name="event-status" value="free">
            </label>
          </div>
        </div>
      <div id="demo-event-date"></div>
    </div>
    <div id="demo-calendar" class="mbsc-flex-1-1"></div>
  </div>
</div>
```

### CSS

```css
.mds-full-height {
  height: 100%;
}
```

## Implementation notes

- `Popup` renders arbitrary content as children; the demo places `mbsc-form-group` blocks containing an `Input` (Title), an `Input`/`Textarea` (Description), a `Switch` (All-day), two more `Input`s (Starts/Ends) used as `startInput`/`endInput` for the date picker, and a `SegmentedGroup` with two segments (Show as busy/free).
- `width: 400`, `contentPadding: false`, `headerText: 'Add new event'`, `display: 'center'`, and `showOverlay: false` configure a fixed-width, centered popup with a header title, no default inner padding (so the form controls its own spacing), and no dimmed backdrop.
- `buttons` combines a plain `'cancel'` string entry with a custom button object - `{ text: 'Add', keyCode: 'enter', handler, cssClass: 'mbsc-popup-button-primary' }` - so pressing Enter or clicking the button runs `handler` (builds the new event from form state, appends it to the events array/data source, closes the popup, and shows a toast) without a separate `set`/`ok` default action.
- The nested `Datepicker` uses `select: 'range'`, `display: 'anchored'`, `touchUi: true`, and `showRangeLabels: false`; its `controls` toggles between `['calendar']` (all-day) and `['calendar', 'time']` (timed) based on the `Switch`'s checked state - in React/Vue this is a derived value recomputed on render/`v-model`; in Angular/JS it's reassigned via `[controls]` binding or `.setOptions({ controls })` in the `Switch`'s change handler.
- The date picker is wired to the two `Input`s via `startInput`/`endInput` (`[startInput]`/`[endInput]` in Angular, `:startInput`/`:endInput` in Vue, refs passed as props in React, element IDs as strings in JS/jQuery) so typing or picking updates those fields instead of rendering its own text field.
- Opening the popup is imperative in JS/jQuery and Angular, declarative in React/Vue: JS captures the popup instance directly from the return value of `mobiscroll.popup(...)`; jQuery instead calls `.mobiscroll('getInst')` on the popup element to get it; either way, the trigger button's click handler then resets all the field instances' values/checked state and calls `.open()`; Angular keeps a `@ViewChild` reference (`popup: MbscPopup`), resets the component's bound fields, and calls `popup.open()`; React and Vue instead bind the popup's `isOpen`/`:isOpen` prop to state that the trigger button's click handler resets and sets to `true`, and reset that state through an `onClose`/`@close` callback (or the custom Add button's `handler`).
- The `Eventcalendar`'s `data`/event array is updated by spreading in the new event object built inside the Add button's `handler`; `selectedDate` is then set to the new event's `start` so the calendar navigates to it (JS/jQuery instead call `calendar.addEvent(newEvent)` and `calendar.navigateToEvent(newEvent)` on the `Eventcalendar` instance).

## Run it in your project

1. If not signed up yet, or don't own a license, you can [start a free trial](https://mobiscroll.com/starttrial).

2. Clone the repository:

   ```
   git clone https://github.com/acidb/mobiscroll-demos-javascript.git
   ```

3. If not installed yet, install the Mobiscroll CLI from NPM:

   ```
   npm install -g @mobiscroll/cli
   ```

4. Config Mobiscroll - open a terminal window in the root directory and run:

   ```
   mobiscroll config javascript
   ```

5. Install dependencies - open a terminal window in the root directory and run:

   ```
   npm install
   ```

6. Run the project:

   ```
   npm run dev
   ```

On a trial, add `--trial` to the config command: `mobiscroll config javascript --trial`.

Running a demo locally requires a Mobiscroll trial or a license; setup is per framework at https://mobiscroll.com/docs/javascript/getting-started/installation

## Related demos

- Next: [Using as a tooltip](https://demo.mobiscroll.com/javascript/popup/show-hide-tooltip-hover-in-out.md) - Use the Javascript popup with custom content on event hover within the various event calendar views.
