jQuery UI Widgets Forums Scheduler Scheduler Legend does not appear

This topic contains 1 reply, has 2 voices, and was last updated by  Hristo 1 week, 4 days ago.

Viewing 2 posts - 1 through 2 (of 2 total)
  • Author
  • Scheduler Legend does not appear #113650

    jeje
    Participant

    Hello, first of al, thank you for this component.
    Unfortunately I have an issue regarding the legend.
    probably a setup / configuration mismatch, but I don’t know which one.
    no error, just no legend.
    please find my code below
    thank you for your help
    scheduler.component.html file : with showLegend

    <jqxScheduler class="calendar"
                  theme="'material'" #scheduler
                  [date]="date" [views]="views"
                  [localization]="localization"
                  [resources]="resources"
                  [view]="view"
                  [source]="dataAdapter"
                  [width]="'100%'"
                  [height]="'600'"
    
                  [showLegend]="'true'"
                  [legendPosition]="'top'"
                  [legendHeight]="'30'"
    
                  [appointmentDataFields]="schedulerConfig.appointmentDataFields"
                  [editDialog]="EDIT_DIALOG"
    
                  [contextMenuCreate]="contextMenuCreate"
                  [renderAppointment]="renderAppointment"
    
                  (onAppointmentClick)="onAppointmentClick($event)"
                  (onDateChange)="onDateChange($event)"
                  (onViewChange)="onViewChange($event)"
                  appCustomTooltip>
    </jqxScheduler>
    

    scheduler.components.ts file : with resources declaration

    import {
      Component, OnInit, ViewChild, Input, SimpleChanges, OnChanges,
      AfterViewInit, OnDestroy, IterableDiffers, DoCheck
    } from '@angular/core';
    import { jqxSchedulerComponent } from 'jqwidgets-ng/jqxscheduler';
    import { SchedulerSourceModel } from '@app/models/scheduler/source';
    import { Ilocalization } from '@app/models/scheduler/localization';
    import { ISchedulerConfig } from '@app/models/scheduler/config';
    import { IAppointment, IAppointmentData } from '@app/models/scheduler/appointment';
    import { IImplantation} from '@app/models/scheduler/implantation';
    import { TranslateService } from '@ngx-translate/core';
    
    import * as moment from 'moment';
    import { Subject, BehaviorSubject } from 'rxjs';
    import { takeUntil, distinctUntilChanged, switchMap, filter } from 'rxjs/operators';
    import { ApiService } from '@app/services/api.service';
    import { GenericModalService } from '@app/shared/modal/service/generic-modal.service';
    
    interface IPeriod {
      start: number;
      period: 'day' | 'week' | 'month';
    }
    @Component({
      selector: 'app-scheduler',
      templateUrl: './scheduler.component.html',
      styleUrls: ['./scheduler.component.scss']
    })
    export class SchedulerComponent implements OnChanges, OnInit, DoCheck, AfterViewInit, OnDestroy {
      @ViewChild('scheduler') sch: jqxSchedulerComponent;
      @Input() schedulerData: [Ilocalization, ISchedulerConfig, IImplantation[]];
      meetingList: IAppointment[];
      schedulerConfig: ISchedulerConfig;
      implantations: IImplantation[];
      resources: jqwidgets.SchedulerResources;
      localization: Ilocalization;
      dataAdapter: any;
      views: any;
      date = new jqx.date();
      EDIT_DIALOG = false;
      periodSubject: BehaviorSubject<IPeriod> = new BehaviorSubject(null);
      _onDestroy = new Subject();
      start: moment.Moment;
      view: 'dayView' | 'weekView' | 'monthView' = 'monthView';
      currentLoadedMeetingDate: moment.Moment;
    
      renderAppointment: (data: IAppointmentData) => IAppointmentData;
      contextMenuCreate: (menu: any, settings: any) => void;
      private iterableDiffer;
      constructor(private translateService: TranslateService,
        private iterableDiffers: IterableDiffers,
        private overlayService: GenericModalService,
        private apiService: ApiService) {
        this.iterableDiffer = this.iterableDiffers.find([]).create(null);
      }
    
      ngOnChanges(change: SimpleChanges) {
        if (change.meetingList && !change.meetingList.isFirstChange()) {
          this.buildDataAdapter();
          this.sch.source(this.dataAdapter);
        }
      }
    
      ngOnInit(): void {
        this.start = moment().startOf('month');
        this.currentLoadedMeetingDate = this.start.clone();
        this.start.utcOffset(0);
        this.start.set({ hour: 0, minute: 0, second: 0, millisecond: 0 });
        this.start.toISOString();
        this.start.format();
        this.periodSubject.next({ start: this.start.valueOf(), period: 'month' });
        this.localization = this.schedulerData[0];
        this.buildScheduler();
        this.loadAppointmentByPeriod();
        this.loadImplantations();
    
        /********************* Functions ******************* */
    
        this.contextMenuCreate = (menu: any, settings: any) => {
          if (settings) {
            settings.source = [];
          }
        };
    
        this.renderAppointment = (data: IAppointmentData) => {
          if (data.view === 'monthView') {
            data.cssClass = 'month-view-appointment';
            data.height = 100;
          }
    
          const eventType = this.getEventTypeCssClass(data.appointment);
          if (eventType) {
            data.cssClass = <code>${data.cssClass ? data.cssClass + ' ' : ''}apointment-${eventType}</code>;
            const subject = data.appointment.subject.replace(/<[^>]+>/g, '');
            data.html = subject.substring(Math.min(3, subject.length, subject.length)).trim();
          }
    
          data.html = '<strong>' + data.html + '</strong>';
    
          if (data.appointment && data.appointment.place) {
            const logo = this.getCityLogo(data);
            if (!!logo) {
              data.html = data.html + <code><br><img class=&quot;apointment-location-logo&quot; src=&quot;/assets/icons/city/${logo}&quot; /> (${data.appointment.place})</code>;
            } else {
              data.html = data.html + <code><br>(${data.appointment.place})</code>;
            }
          }
          return data;
        };
      }
    
      ngDoCheck() {
        const meetingListChange = this.iterableDiffer.diff(this.meetingList);
        if (meetingListChange) {
    
        }
      }
    
      ngAfterViewInit() {
      }
    
      ngOnDestroy() {
        this._onDestroy.next();
        this._onDestroy.complete();
      }
    
      onAppointmentClick(event: any) {
        const appointment = event.args.appointment;
        const parser = new DOMParser();
        const str: string = appointment.description;
        if (str && str.length) {
          const element = parser.parseFromString(str, 'text/html');
          let body = element.getElementsByTagName('body')[0].innerHTML;
          body = body.replace(/<img\s[^>]*?src\s*=\s*['\"]([^'\"]*?)['\"][^>]*?>/g, '');
          this.overlayService.open(body, null, 'center', true, null, '90%');
        }
    
      }
    
      onDateChange(event: any) {
        const currentDate = moment(event.args.date.toDate());
        const isSameMonth = this.currentLoadedMeetingDate.month() === currentDate.month() &&
          this.currentLoadedMeetingDate.year() === currentDate.year();
        if (!isSameMonth) {
          this.currentLoadedMeetingDate = currentDate.clone();
          this.date = event.args.date;
          currentDate.utcOffset(0);
          currentDate.set({ hour: 0, minute: 0, second: 0, millisecond: 0 });
          currentDate.toISOString();
          currentDate.format();
          const period = {} as IPeriod;
          period.start = currentDate.valueOf();
          period.period = 'month';
          this.periodSubject.next(period);
        }
      }
    
      onViewChange(event: any) {
        this.view = event.args.newViewType;
        const currentDate = moment(event.args.date.toDate()).startOf('month');
        const isSameMonth = this.currentLoadedMeetingDate.month() === currentDate.month() &&
          this.currentLoadedMeetingDate.year() === currentDate.year();
        if (!isSameMonth) {
          this.currentLoadedMeetingDate = currentDate.clone();
          this.date = event.args.date;
          currentDate.utcOffset(0);
          currentDate.set({ hour: 0, minute: 0, second: 0, millisecond: 0 });
          currentDate.toISOString();
          currentDate.format();
          const period = {} as IPeriod;
          period.start = currentDate.valueOf();
          period.period = 'month';
          this.meetingList = [];
          this.periodSubject.next(period);
        } else {
          const source = this.getSource(this.view);
          this.updateDataAdapter(source);
        }
      }
    
      private loadAppointmentByPeriod() {
        this.periodSubject.pipe(
          takeUntil(this._onDestroy),
          filter(query => query !== null),
          distinctUntilChanged(),
          switchMap((value: IPeriod) => {
            return this.apiService.getMeetingList(value.start, value.period);
          })
        ).subscribe((meetingList: IAppointment[]) => {
          this.meetingList = meetingList;
          this.buildDataAdapter();
          this.sch.source(this.dataAdapter);
        });
      }
    
      private buildScheduler(): void {
        this.schedulerConfig = this.schedulerData[1];
        this.views = this.schedulerConfig.views;
        this.buildDataAdapter();
      }
    
      private updateDataAdapter(source: SchedulerSourceModel) {
        this.dataAdapter = new jqx.dataAdapter(source, { autoBind: true });
      }
    
      private buildDataAdapter(): void {
        this.dataAdapter = new jqx.dataAdapter(this.getSource(this.view), { autoBind: true });
        this.resources = {
          colorScheme: 'scheme03',
          dataField: 'id',
          source: this.dataAdapter
        };
      }
    
      private getSource(view: 'dayView' | 'weekView' | 'monthView'): SchedulerSourceModel {
        return new SchedulerSourceModel(
          'array',
          this.schedulerConfig.dataFields,
          'id',
          this.meetingList,
          this.translateService.currentLang,
          view
        );
      }
    
      private getEventTypeCssClass(apointment: IAppointment): string {
        const eventTypes = [ 'evi', 'spu', 'web', 'epm', 'epa', 'com', 'sem'];
        let eventType = apointment?.subject.replace(/<[^>]+>/g, '').substring(0, 3).toLowerCase();
        return eventTypes.find(item => item === eventType);
      }
    
      private getCityLogo(data: IAppointmentData): string {
        return this.implantations.find((cur: IImplantation) => {
          let city = cur.cities.find((implantation: string) => {
            return (<string> data.appointment.place.toLowerCase()).indexOf(implantation) > -1;
          });
          return !!city;
        })?.logo;
      }
    
      private loadImplantations() {
        this.implantations = this.schedulerData[2];
      }
    }
    

    _calendar.css with lgend declaration :

     .jqx-scheduler-legend {
          width: 14px;
          height: 14px;
          float: left;
          margin-right: 3px;
          border-style: solid;
          border-width: 1px;
          cursor: pointer;
          vertical-align: middle;
          margin-top: 4px;
        }
        .jqx-scheduler-legend-label {
          float: left;
          margin-right: 12px;
          cursor: pointer;
          vertical-align: middle;
          margin-top: 4px;
        }

    Thank you for your help
    Regards
    Jérôme

    Scheduler Legend does not appear #113653

    Hristo
    Participant

    Hello Jérôme,

    It is a little bit complicated example (there is missing some settings).
    However, I try to create an example closer to your case.
    Please, take a look at this example:
    https://stackblitz.com/edit/github-aet7ex-eqz7ib?file=src/app/app.component.html
    That I change are the values set in string format, for example, the height and the legendHeight properties.

    Best Regards,
    Hristo Hristov

    jQWidgets team
    https://www.jqwidgets.com

Viewing 2 posts - 1 through 2 (of 2 total)

You must be logged in to reply to this topic.