首页 > 解决方案 > 如何在 fullCalendar 中隐藏事件?

问题描述

使用最新版本的 fullCalendar (5.3.2) 我想隐藏一些与我现在不想在给定视图中显示的资源相对应的事件。执行此操作的标准方法是使用一个eventClassNames函数来检查它并添加一个“隐藏”类。像这样的东西:

eventClassNames: function(arg) {
   my_class = "";
   if (arg.view.type != 'resourceTimeGridDay') {
      if (arg.event.extendedProps.real_rc != "1") {
         my_class = 'hidden';
      }
   }
   return my_class;
}

使用简单的 CSS:

.fc-event.hidden {
  display: none;
}

这可以正常工作,但是当隐藏事件和显示事件之间存在重叠时会出现问题。例如在这种情况下:

events: [
  {
    title: 'Resource 1',
    real_rc: '1',
    start: '2020-12-22 16:00',
    end: '2020-12-22 17:00'
  },
  {
    title: 'Resource 2',
    real_rc: '2',
    start: '2020-12-22 15:00',
    end: '2020-12-22 17:00'
  }
]

应该只显示带有的事件,real_rc == 1实际上它是正确的,但是隐藏事件使用的空间被保留,如下图所示:

错误的结果

如果列表real_rc: 2中省略了带有 的事件,则event结果是预期的:

预期结果

我已经使用 Chrome DevTools 试图弄清楚发生了什么,我认为问题在于“隐藏”类没有像fullCalendar 状态那样设置在“最外层事件元素”上,而是设置在内部一个:

在此处输入图像描述

(第一个 DIV 是第一个事件,如您所见,hidden该类已设置但不是设置为 DIV,而是设置为a标签)

这是一个测试它的代码笔

恕我直言,这是一个完整的日历错误,但现在我遇到了一个问题,我需要一个解决方案。我的选择是:

  1. 为父级使用 CSS 选择器 <--不可能:它不存在(尚)
  2. (1) 使用 jquery <--我不知道怎么做?我知道我需要在$(".fc-event.hidden").parent().remove()加载和显示事件时执行类似的操作,但由于 v3 不存在这样的 更新,即使它存在,当前 v5 删除 DOM 元素也不会调整其他事件框的大小。
  3. 尝试修复库的代码<--问题:如果下一个版本的库没有解决方案,我不想担心补丁
  4. 加载时过滤事件 <-- 慢:我使用回调函数通过 Ajax 加载事件,我可以在那里进行快速过滤,但在这种情况下,我会失去性能,因为我每次需要时都必须重新获取事件显示事件real_rc != 1
  5. 自定义视图 <-- 我不想重新发明轮子。正如@saqibkafeel 在评论中所建议的,自定义视图可用于创建新视图,但我喜欢当前视图并且不需要新视图,只需默认视图按预期工作即可。

有没有办法在不创建新问题的情况下绕过这个问题?(我觉得最简单的选择是找到一个可以让我做选项2的钩子,但是我花了一整天都没有找到任何东西)。

标签: javascriptjquerycssfullcalendarfullcalendar-5

解决方案


正如您已经注意到的,CSS 和 JS 在这里无法提供帮助,因为事件是使用放置的,position:absolute因此删除一个事件(甚至完全从 DOM 中)不会影响其他事件的显示。唯一的方法是在渲染之前从日历中删除事件。

所以删除事件而不是添加一个类:

eventClassNames: function(arg) { /* you can also use "eventDidMount" */
       if (arg.view.type != 'resourceTimeGridDay') {
          if (arg.event.extendedProps.real_rc != "1") {
             arg.event.remove(); /* HERE */
          }
       }
    },

完整代码:

document.addEventListener('DOMContentLoaded', function() {
  var calendarEl = document.getElementById('calendar');

  var calendar = new FullCalendar.Calendar(calendarEl, {
    initialView: 'timeGridWeek',
    initialDate: '2020-12-22',
    headerToolbar: {
      left: 'prev,next today',
      center: 'title',
      right: 'dayGridMonth,timeGridWeek,timeGridDay'
    },
    height: 'auto',

    eventClassNames: function(arg) {
       if (arg.view.type != 'resourceTimeGridDay') {
          if (arg.event.extendedProps.real_rc != "1") {
             arg.event.remove();
          }
       }
    },

    events: [
      {
        title: 'Test Resource 1',
        real_rc: '1',
        start: '2020-12-22 13:00',
        end: '2020-12-22 14:00'
      },
      {
        title: 'Also resource 1',
        real_rc: '1',
        start: '2020-12-22 13:30',
        end: '2020-12-22 14:30'
      },
      {
        title: 'Resource 1',
        real_rc: '1',
        start: '2020-12-22 16:00',
        end: '2020-12-22 17:00'
      },
      {
        title: 'Resource 2',
        real_rc: '2',
        start: '2020-12-22 15:00',
        end: '2020-12-22 17:00'
      }
    ]
  });

  calendar.render();
});
html, body {
  margin: 0;
  padding: 0;
  font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
  font-size: 14px;
}

#calendar {
  max-width: 1100px;
  margin: 40px auto;
}
<link rel="stylesheet" href="https://unpkg.com/fullcalendar@5.1.0/main.min.css">
<script src="https://unpkg.com/fullcalendar@5.1.0/main.min.js"></script>
<div id='calendar'></div>

另一个想法是控制display事件的发生,如下所示:

document.addEventListener('DOMContentLoaded', function() {
  var calendarEl = document.getElementById('calendar');

  var calendar = new FullCalendar.Calendar(calendarEl, {
    initialView: 'timeGridWeek',
    initialDate: '2020-12-22',
    headerToolbar: {
      left: 'prev,next today',
      center: 'title',
      right: 'dayGridMonth,timeGridWeek,timeGridDay'
    },
    height: 'auto',

    eventDidMount: function(arg) {
       if (arg.view.type != 'resourceTimeGridDay') {
          if (arg.event.extendedProps.real_rc != "1") {
             arg.event.setProp( 'display', 'none' );
          }
       }
    },

    events: [
      {
        title: 'Test Resource 1',
        real_rc: '1',
        start: '2020-12-22 13:00',
        end: '2020-12-22 14:00'
      },
      {
        title: 'Also resource 1',
        real_rc: '1',
        start: '2020-12-22 13:30',
        end: '2020-12-22 14:30'
      },
      {
        title: 'Resource 1',
        real_rc: '1',
        start: '2020-12-22 16:00',
        end: '2020-12-22 17:00'
      },
      {
        title: 'Resource 2',
        real_rc: '2',
        start: '2020-12-22 15:00',
        end: '2020-12-22 17:00'
      }
    ]
  });

  calendar.render();
});
html, body {
  margin: 0;
  padding: 0;
  font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
  font-size: 14px;
}

#calendar {
  max-width: 1100px;
  margin: 40px auto;
}
<link rel="stylesheet" href="https://unpkg.com/fullcalendar@5.1.0/main.min.css">
<script src="https://unpkg.com/fullcalendar@5.1.0/main.min.js"></script>
<div id='calendar'></div>


一个交互式演示,您可以在其中切换显示:

var rc = "1";

document.addEventListener('DOMContentLoaded', function() {
  var calendarEl = document.getElementById('calendar');

  var calendar = new FullCalendar.Calendar(calendarEl, {
    initialView: 'timeGridWeek',
    initialDate: '2020-12-22',
    headerToolbar: {
      left: 'prev,next today',
      center: 'title',
      right: 'dayGridMonth,timeGridWeek,timeGridDay'
    },
    height: 'auto',

    eventDidMount: function(arg) {
       if (arg.view.type != 'resourceTimeGridDay') {
          if (arg.event.extendedProps.real_rc != rc) {
             arg.event.setProp( 'display', 'none' );
          } 
       }
    },
    viewDidMount: function(arg) {
       var es = calendar.getEvents();
       for(var i=0;i<es.length;i++)
        es[i].setProp( 'display', 'auto' )
    },

    events: [
      {
        title: 'Test Resource 1',
        real_rc: '1',
        start: '2020-12-22 13:00',
        end: '2020-12-22 14:00'
      },
      {
        title: 'Also resource 1',
        real_rc: '1',
        start: '2020-12-22 13:30',
        end: '2020-12-22 14:30'
      },
      {
        title: 'Resource 1',
        real_rc: '1',
        start: '2020-12-22 16:00',
        end: '2020-12-22 17:00'
      },
      {
        title: 'Resource 2',
        real_rc: '2',
        start: '2020-12-22 15:00',
        end: '2020-12-22 17:00'
      }
    ]
  });

  calendar.render();
  document.querySelector("#toggle").addEventListener('click',function() {
    if (rc=="1") rc="2"; else rc = "1";
    /* trigger view change */
    calendar.changeView('dayGridMonth');
    calendar.changeView('timeGridWeek');
  });
});
html, body {
  margin: 0;
  padding: 0;
  font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
  font-size: 14px;
}

#calendar {
  max-width: 1100px;
  margin: 40px auto;
}
<link rel="stylesheet" href="https://unpkg.com/fullcalendar@5.1.0/main.min.css">
<script src="https://unpkg.com/fullcalendar@5.1.0/main.min.js"></script>
<button id="toggle">toggle</button>
<div id='calendar'></div>


推荐阅读