Premium support for our pure JavaScript UI components


Post by sudhanshu.jain »

When we have more data and if we scroll in the scheduler pro, our header and date header also get scroll. How we can make them sticky. If we see any scheduler pro example, in all examples on vertical scroll,header and date header are visible.

Is there some props or class we missing ??

Please find attachment.

Attachments
Scroll Header is not visible.png
Scroll Header is not visible.png (122.08 KiB) Viewed 1061 times
Default Case .png
Default Case .png (142.61 KiB) Viewed 1061 times

Post by mats »

Probably your application HTML / CSS is not done correctly. Can you please upload a small test case for us?


Post by sudhanshu.jain »

Sure .

This is index.js --

 <div className={isEmptyLodash({}) ? 'emptyTaskData' : ''}>
      {showAlert ?
        <Alert type='danger' message={errorMessage}
          onClose={() => {
            setShowAlert(false);
            setErrorMessage('');
          }}/> : null}
      <p className={styles.headerText}>
        { getSinglePageContext(data.technicianCount) } Technicians |
          Utilization Rate:
        <b>{ getSinglePageContext(data.utilizationRate) }</b>
      </p>
      <BryntumScheduler
        ref = {scheduler}
        autoHeight = {true}
        zoomOnMouseWheel={false}
        zoomOnTimeAxisDoubleClick={false}
        viewPreset = {getViewPreset(timelineView)}
        tbar = {
          [
            {
              type: 'combo',
              value: 'monthAndYear',
              editable: false,
              ref: 'viewPresetCombo',
              cls: 'select-view',
              listCls: 'list-items',
              listeners: { change: viewPresetHandler },
              items: [{
                value: 'monthAndYear',
                text: 'Month'
              },
              {
                value: 'weekAndDay',
                text: 'Week'
              },
              {
                value: 'dayAndWeek',
                text: 'Day'
              }]
            },
            {
              type: 'dateField',
              editable: false,
              cls: 'date-field',
              listeners: {
                change: setSelectedDate,
                trigger: onDatePickerLoad
              },
              ref: 'selectDate'
            },
            {
              type: 'button',
              text: 'Today',
              listeners: { click: setCurrentDate },
              cls: 'btn-today'
            },
            {
              type: 'button',
              icon: 'b-fa-angle-left',
              cls: 'btn-prev',
              listeners: { click: viewPrevious }
            },
            {
              type: 'button',
              icon: 'b-fa-angle-right',
              cls: 'btn-next',
              listeners: { click: viewNext }
            },
            '->',
            {
              type: 'textfield',
              ref: 'filterByName',
              placeholder: 'Search..',
              cls: 'input-search',
              clearable: true,
              keyStrokeChangeDelay: 100,
              triggers: {
                filter: {
                  align: 'start',
                  cls: 'b-fa b-fa-search'
                }
              },
              listeners: { change: searchHandler }
            }
          ]
        }
        resources = {data.resources}
        timeRanges={data.timeRanges}
        resourceTimeRangesFeature={true}
        resourceTimeRangeStore={resourceTimeRangeStore}
        startDate = {startDate}
        visibleDate = {new Date()}
        emptyText = {'No matches'}
        columns = {getColumnsList(getLodash(jsonDef, 'columns', []))}
        filterBarFeature = {true} // to enable search on columns
        listeners = {{
          presetChange,
          eventClick: ({ eventRecord, eventElement, event }) => {
            eventRecord.data.elementType = TASK;
            openEventPopup(eventRecord, eventElement, event.x, event.y, TASK);
          },
          scheduleDblClick: ({ resourceRecord, tickStartDate,
            tickEndDate, event }) => onScheduleClick(
            resourceRecord, tickStartDate, tickEndDate, event),
          async beforeEventDropFinalize ({ context }) {
            // update the task with the dropped dates and resource id
            const task = {
              ...context.eventRecords[FIRST_INDEX].data,
              startDate: context.startDate,
              endDate: context.endDate,
              resourceId: context.newResource.id
            };
            // check again if the date is less than today
            if(moment().isBefore(task.startDate, 'second')) {
              // show progress bar
              scheduler?.current?.schedulerInstance?.mask({
                text: ''
              });
              const response = await submitTaskDetails(task);
              if(response === null) {
                setShowAlert(true);
                setErrorMessage(ErrorMessageForUpdateWorkflow);
              }
              if(props.dragCompleted) {
                props?.dragCompleted(task);
              }
              // hide progress bar
              scheduler?.current?.schedulerInstance?.unmask();
            }
          }
        }}
        events = {data.events}
        eventStyle = {'colored'}
        eventLayout = {'stack'}
        eventBodyTemplate = {(data) => getEventTemplate(data)}
        eventRenderer = {(eventRecord) => eventRenderer(eventRecord)}
        eventMenuFeature = {false} // disable contextmenu on rgt click of events
        eventEditFeature = {{
          disabled: true // disable event edit popup on double click of events
        }}
        eventDragCreateFeature = {{
          disabled: true // disable event creation on drag
        }}
        eventDragFeature = {{
          disabled: !jsonDef?.dragAllow,
          validatorFn ({ startDate }) {
            if(moment().isAfter(startDate, 'second')) {
              return {
                valid: false,
                message: ErrorMessageForPastDate
              };
            }
            return {
              valid: true
            };
          }
        }}
        eventResizeFeature = {{
          disabled: true
        }}
        stripeFeature={true}
        timeRangesFeature = {{
          showCurrentTimeLine: true,
          showHeaderElements: true,
          enableResizing: true
        }}
      />
    </div>

index.css file

/* stylelint-disable */
.b-toolbar {
  background: transparent;
  border-top: 0.063rem solid #e5e5e5;
  border-bottom: 0.063rem solid #e5e5e5 !important;
  padding: 1rem 1.5rem;
  color: #727272;
  font-size: 0.875rem;
}

.select-view {
  width: 6.25rem;
}

.select-view .b-field-inner input {
  padding: 0.5rem 0.625rem 0.5rem 0.75rem;
}

.select-view .b-field-inner div {
  padding: 0.65rem 0.8rem 0.65rem 0 !important;
}

.select-view .b-field-inner:hover {
  border-color: #e5e5e5 !important;
}

.select-view input {
  padding: 0;
  opacity: 1;
}

.select-view .b-icon {
  font-size: 0.688rem;
  color: #727272;
}

/* .list-items .b-list-item:hover, .list-items .b-selected, .list-items .b-active {
    background: transparent !important;
} */

.date-field {
  width: 3.875rem;
}

.date-field input {
  display: none;
}

.date-field .b-icon {
  padding: 0.563rem 2.15rem 0.563rem 0.75rem !important;
}

.date-field .b-icon-calendar {
  padding-right: 1.563rem;
}

.date-field .b-icon-calendar::after {
  content: "";
  display: block;
  width: 0;
  height: 0;
  border-left: 0.294rem solid transparent;
  border-right: 0.294rem solid transparent;
  border-top: 0.294rem solid #727272;
  position: absolute;
  top: 0.938rem;
  left: 2.5rem;
  z-index: 9;
}

.date-field .b-icon-calendar,
.b-datefield.b-open .b-fieldtrigger {
  color: #323232 !important;
}

.btn-today {
  background: #fff;
  text-transform: capitalize;
}

.btn-today label {
  font-size: 0.875rem;
  color: #727272;
  margin-bottom: 0;
}

.btn-today:hover,
.btn-prev:hover,
.btn-next:hover {
  background: #fff !important;
  border-color: #e5e5e5 !important;
}

.btn-today:active,
.btn-prev:active,
.btn-next:active {
  background: #fff !important;
  color: #727272 !important;
}

.btn-prev,
.btn-next {
  color: #a5a5a5;
  background: #fff;
}

.input-search {
  width: 15.625rem;
}

.input-search input {
  padding: 0.5rem 0.75rem;
}

.select-view,
.btn-today,
.btn-next {
  margin-right: 0.75rem !important;
}

.btn-prev {
  margin-right: 0.5rem !important;
}

.select-view .b-field-inner,
.date-field .b-field-inner,
.btn-today,
.btn-prev,
.btn-next,
.input-search .b-field-inner,
.input-search .b-field-inner:hover {
  border-radius: 0.25rem;
  border-color: #e5e5e5 !important;
}

.b-grid-header-text-content {
  text-transform: capitalize;
}

.b-filter-bar-field .b-field-inner {
  border-color: #d0d1d2 !important;
  height: 1.563rem;
}

.b-filter-bar-field .b-field-inner:hover {
  border-color: #d0d1d2 !important;
}

.b-filter-bar-field .b-filter-bar-field-input {
  font-size: 0.813rem;
}

.b-filter-bar-field .b-fa-search {
  font-size: 0.563rem;
}

.b-grid-header {
  justify-content: start;
  padding: 0 !important;
}

.b-sch-header-row-0 {
  background: #fff;
}

.b-grid-header.b-depth-0 {
  padding: 0;
}

.b-grid-header-text {
  padding: 0.688rem 0.5em 0.688rem 1.625rem;
  border-bottom: 0.063rem solid #d8d9da !important;
  background: #fff;
}

.b-filter-bar-field {
  margin: 0.5em;
  width: 90%;
}

.b-gridbase:not(.b-column-resizing) .b-grid-header-container:not(.b-dragging-header) .b-depth-0:hover,
.b-gridbase:not(.b-column-resizing) .b-grid-header-container:not(.b-dragging-header) .b-depth-0:focus {
  background-color: transparent !important;
}

.b-gridbase.b-sort .b-grid-header.b-sort .b-grid-header-text::after {
  color: #727272;
}

.b-filter-bar-field .b-icon-remove::before {
  font-size: 0.938rem;
}

.b-grid-body-container,
.b-grid-vertical-scroller {
  min-height: 3.75rem;
}

.b-gridbase .b-grid-empty .b-grid-subgrid:first-child::before {
  font-size: 0.875rem;
  color: #727272;
  top: 1.4em;
  left: 38%;
}

.b-grid-empty {
  border-bottom: 0.063rem solid #e9eaeb;
}

.b-sch-header-timeaxis-cell {
  font-size: 0.75rem;
  color: #323232;
}

.b-grid-cell {
  padding: 0 1.5rem;
}

.b-grid-cell,
.b-grid-header-text-content,
.b-sticky-header {
  color: #000;
  font-size: 0.875rem;
}

.b-gridbase.b-columnresize .b-grid-header.b-resizing {
  background: initial;
}

.b-gridbase.b-sort:not(.b-column-resizing) .b-grid-header-container:not(.b-dragging-header) .b-grid-header-text::after {
  color: #727272 !important;
}

.emptyTaskData .b-grid-vertical-scroller,
.emptyTaskData .b-grid-body-container {
  min-height: 0;
}

.b-sch-event-content {
  flex-direction: column;
  font-size: 0.75rem !important;
}

.b-sch-event-body {
  margin-top: 0.188rem;
  font-weight: 600;
}

.b-sch-event-icons span {
  padding-right: 0.5rem;
  font-size: 1rem;
  margin-bottom: 0.313rem;
}

.b-sch-event-wrap:hover .b-sch-event-content span {
  color: #fff !important;
}

.b-sch-event-task {
  display: flex;
}

.b-sch-icon-dark {
  color: #323232;
}

.b-sch-event-icons {
  display: flex;
  flex-direction: column;
}

.b-popup {
  width: 16.875rem;
}

.b-popup-header {
  background: #f7f7f7;
  border-bottom: 0 !important;
  color: #000;
  font-size: 0.875rem;
  padding: 1rem;
}

.b-popup-close {
  color: #a5a5a5;
  font-size: 1rem;
  padding: 1rem;
}

.b-popup-content {
  background: #fff;
  padding: 1rem;
}

.b-popup-block {
  width: 100%;
  margin-bottom: 0.875rem;
}

.b-popup-label {
  color: #727272;
  font-size: 0.75rem;
  margin-bottom: 0.25rem;
}

.b-popup-value {
  color: #323232;
  font-size: 0.875rem;
  margin-bottom: 0;
}

.b-popup-content .b-button {
  border-radius: 0.25rem;
  text-transform: capitalize;
  font-size: 0.875rem;
  padding: 0.5rem;
  width: 100%;
  box-shadow: 0 0.125rem 0.375rem rgba(0, 0, 0, 0.15);
}

.b-popup-content .b-button:not(:first-child) {
  margin-top: 0.875rem;
}

.b-popup-content .b-button:first-child {
  margin-top: 0.375rem;
}

.b-popup-content .primary {
  color: #fff;
  background: var(--primary-color) !important;
}

.b-popup-content .primary:hover {
  background: var(--primary-hover-color) !important;
}

.b-popup-content .secondary {
  color: #727272 !important;
  border: 0.063rem solid #e5e5e5;
  background: #fff;
}

.b-popup-content .secondary:hover {
  background: #fff !important;
}

.b-popup-content .b-button label {
  margin-bottom: 0;
}

.b-popup-block span[class^="icon-"],
.b-popup-alert span[class^="icon-"] {
  padding-right: 0.313rem;
}

.b-popup-status {
  width: 0.5rem;
  height: 0.5rem;
  display: inline-block;
  margin-right: 0.5rem;
}

.b-popup-alert {
  padding: 0.563rem 0.75rem;
  font-size: 0.75rem;
  color: #eb4750;
  background: #ffd6d9;
  width: 100%;
  border-radius: 0.25rem;
  margin-bottom: 0.875rem;
}

.b-popup-warning {
  color: #eb4750;
  font-size: 0.875rem;
}

.b-popup-link {
  color: #36f;
  text-decoration-line: underline;
}

.b-sch-dragcreator-proxy {
  background-color: #f4f3ff !important;
}

.b-sch-tip-invalid .b-sch-tip-message:not(:empty) {
  color: red;
}

.b-grid-subgrid .coffee {
  background: repeating-linear-gradient(
          135deg,
          #ffffff,
          #ffffff 0.18rem,
          #ffffff 0.25rem,
          #fcefc7 0.50rem
  )
}

.b-grid-subgrid .coffee label {
  background: #fff;
  font-weight: 500;
}

.b-theme-classic-dark .b-grid-subgrid .coffee {
  background: repeating-linear-gradient(
          135deg,
          #ffffff,
          #ffffff 0.18rem,
          #ffffff 0.25rem,
          #fcefc7 0.50rem
  )
}

.b-sch-resourcetimerange.notAvailable {
  background: repeating-linear-gradient(
          135deg,
          #ffffff,
          #ffffff 0.18rem,
          #e5e5e5 0.18rem,
          #e5e5e5 0.33rem
  ) ;
  color: #323232 ;
  font-size: 0.875rem ;
  border-color: #e5e5e5 ;
  border-radius: 0rem ;
}

.b-grid-header {
  height : 57px;
}

Post by saki »

Would you post please a runnable showcase? Including all index.html and other files that we can just build and run?


Post by saki »

The reason for scrolling headers is that the container in which the Scheduler is rendered is taller than its upper container and this upper level container (probably body) has overflow:auto.

However, there are many combinations of css rules that may lead into this behavior, therefore we asked for a runnable showcase so that we can spot that specific combination of your case and that we can advise you a good solution.

Generally, we use mainly flexbox to layout and size our components.

For illustration, see the following video where I broke our example just by changing 3 rules:

container-css.gif
container-css.gif (2.98 MiB) Viewed 962 times

Post Reply