How-tos

You can read about general customization rules in the corresponding article.

How to limit app tabs

To limit the tabs on a toolbar, you need to redefine options for the NavBarView. Keep in mind that tab IDs must coincide with the possible display modes.

class CustomBarsView extends scheduler.views["bars/nav"] {
    config() {
        const ui = super.config();
 
        ui.options = [
            { id: "week", value: "Week" },
            { id: "month", value: "Month" },
        ];
        return ui;
    }
}

To limit menu options in the compact mode, you need to change the NavPopupView in the same way:

class CustomNavPopupView extends scheduler.views["bars/navpopup"] {
    config() {
        const ui = super.config();
 
        const options = [
            { id: "week", value: "Week", icon: "shi-week" },
            { id: "month", value: "Month", icon: "shi-month" },
        ];
 
        ui.body.rows[0].data = options;
        return ui;
    }
}

Finally, do not forget to override the default classes via the corresponding property:

webix.ui({
  view: "scheduler",
  override: new Map([
    [scheduler.views["bars/nav"], CustomBarsView],
    [scheduler.views["bars/navpopup"], CustomNavPopupView]
  ])
});

Related sample:  Scheduler: limited Tabs

How to display only working days in Week view

Firstly, you need to configure WeekView to display only 5 day columns and adjust its GetWeek method so that it returns the data only for the first 5 days.

class CustomWeekView extends scheduler.views["modes/week"] {
    config() {
        const ui = super.config();
        if (!this.Compact) ui.rows[2].body.cols.length = 6; //scale + 5 days
        return ui;
    }
    GetWeek(start, end) {
        if (!this.Compact) end = webix.Date.add(end, -2, "day");
        return super.GetWeek(start, end);
    }
}

Secondly, you need to adjust MultiDayView and WeekHeaderView to show only 5 cells:

class CustomWeekHeader extends scheduler.views["modes/week/header"] {
    config() {
        const ui = super.config();
        ui.cols[1].xCount = 5;
        return ui;
    }
}
 
/* and the same for scheduler.views["modes/week/multiday"] */

Do not forget to override the default classes with the new ones:

webix.ui({
  view: "scheduler",
  mode: "week",
  override: new Map([
    [scheduler.views["modes/week"], CustomWeekView],
    [scheduler.views["modes/week/header"], CustomWeekHeader],
    [scheduler.views["modes/week/multiday"], CustomWeekMultiDay],
  ]),
});

Related sample:  Scheduler: Working Days

Note that this customization will work if a week begins with Monday in your locale. If not, you can set it beforehand:

webix.Date.startOnMonday = true;

How to display only working hours in Day/Week scales

Firstly, you need to define and parse the necessary hour cells into the HourScale and DayEvents views. If needed, you can increase the height of scale cells.

DayEvents view is reused in the week scale, so no extra actions are required for the latter.

 
class CustomHours extends scheduler.views["modes/common/hourscale"] {
    config() {
        const ui = super.config();
        ui.type.height = 60;
        return ui;
    }
    ParseHours() {
        const data = [];
        for (let h = 8; h < 22; h++) {
            data.push({ id: h + "" });
        }
        this.List.parse(data);
    }
}
/* and the same for scheduler.views["modes/day/events"] */

Additionally, if your data contains events that do not fit into the desired working hours, you can adjust them before rendering:

class CustomDayEvents extends scheduler.views["modes/day/events"] {
    /* as above */
    config() { ... },
    ParseHours() { ... }
    // adjust out of scale events
    RenderEvents() {
        const evs = this.Events;
        if (evs && evs.length) {
            for (let i = 0; i < evs.length; i++) {
                if (evs[i].start_date.getHours() < 8) {
                    evs[i].start_date.setHours(8);
                    evs[i].start_date.setMinutes(0);
                }
                // same logic for the end_date
            }
        }
 
        super.RenderEvents();
    }
}

Do not forget to override the default classes via the corresponding property:

webix.ui({
  view: "scheduler",
  mode: "week",
  override: new Map([
    [scheduler.views["modes/common/hourscale"], CustomHours],
    [scheduler.views["modes/day/events"], CustomDayEvents],
  ]),
});

Related sample:  Scheduler: Working Hours

How to display info window and wide form

In this tutorial we will try to achieve the following result:

Let's start with a popup. Create InfoPopup class with a Popup component inside and define methods to show/hide the popup.

class InfoPopup extends scheduler.views.JetView {
  config() {
    return {
      view: "popup",
      width: 450,
      height: 350,
      body: CustomInfo,
    };
  }
  Show(node) {
    this.getRoot().show(node);
  }
  Hide() {
    this.getRoot().hide();
  }
}

InfoView should be redefined as well. Set paddings and the "Edit" button action, so that it can open the form in place of the current tab.

class CustomInfo extends scheduler.views["event/info"] {
  config() {
    this.Compact = this.getParam("compact", true);
    const ui = super.config();
    if (!this.Compact) {
      ui.body.rows[0].padding = 4;
      ui.body.rows[1].padding = 4;
      ui.body.rows[1].rows[1].inputWidth = 0;
    }
 
    return ui;
  }
  // opens form for editing
  EditEvent() {
    if (!this.Compact) {
      this.getParentView().Hide();
      this.app.show("main/event.form");
    } else super.EditEvent();
  }
}

Next major step is to redefine the FormView. Split its UI into columns and show the Notes field on the right side.

class CustomForm extends scheduler.views["event/form"] {
  config() {
    let ui = super.config();
    if (!this.Compact) {
      //textarea
      const notes = ui.body.rows[1].elements.splice(5, 1)[0];
      notes.labelPosition = "top";
      notes.height = 334;
      // ...
    }
 
    return ui;
  }
}

After that you should adjust saving logic in the FormView. The data must be saved on clicking "Done" button.

class CustomForm extends scheduler.views["event/form"] {
  // ... config method
 
 
  Back(close) {
    this.Form.clear();
    this.State.selected = null;
    if (!this.Compact)
      this.app.show(`main/modes.${this.State.mode}/event.form`);
    else super.Back(close);
  }
 
  Done(close) {
    const change = this.Form.getDirtyValues();
    // subform is for recurring events
    if (this.SubForm && this.SubForm.IsDirty()) {
      change.$recurring = this.SubForm.GetValues();
      delete change.rec_option;
    }
 
    this.UpdateEvent(change).then(() => this.Back(close));
  }
}

After that you should adjust logic in the MainView for showing/hiding Info and Form.

class CustomMainView extends scheduler.views.main {
  init(view) {
    super.init(view);
    this.Info = this.ui(InfoPopup);
  }
  ShowEvent(ev) {
    //"0" is for new events, form must be opened
    if (!this.Compact) {
      if (ev.id === "0") {
        const mode = this.app.getState().mode;
        this.show(`event.form`);
      } else this.Info.Show(ev.node);
    } else super.ShowEvent(ev);
  }
  HideEvent() {
    this.Info.Hide();
    super.HideEvent();
  }
}

Finally do not forget to override the default classes with the new ones.

webix.ui({
  view: "scheduler",
  override: new Map([
    [scheduler.views.main, CustomMainView],
    [scheduler.views["event/info"], CustomInfo],
    [scheduler.views["event/form"], CustomForm]
  ])
});

Related sample:  Scheduler: Info Window.

Back to top