Yii2 полная фильтрация событий календаря не работает
Я использую Philipp Frenzel FullCalendar в фреймворке Yii2, и он работает отлично. Я хочу реализовать базовый фильтр событий на основе календаря при выборе опции, но мои коды все еще не работают. Помощь будет высоко ценится.
Это внутри EventController:
<?php
namespace app\controllers;
use Yii;
use app\models\Event;
use app\models\EventSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
/**
* EventController implements the CRUD actions for Event model.
*/
class EventController extends Controller
{
/**
* {@inheritdoc}
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all Event models.
* @return mixed
*/
public function actionIndex()
{
/*$searchModel = new EventSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);*/
$events = Event::find()->all();
$tasks = [];
foreach ($events as $eve)
{
$event = new \yii2fullcalendar\models\Event();
$event->id = $eve->id;
$event->backgroundColor = 'green';
$event->title = $eve->title;
$event->start = $eve->created_date;
$tasks[] = $event;
}
return $this->render('index', [
//'searchModel' => $searchModel,
'events' => $tasks,
]);
}
/**
* Displays a single Event model.
* @param integer $id
* @return mixed
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Event model.
* If creation is successful, the browser will be redirected to the 'view' page.
* @return mixed
*/
public function actionCreate($date)
{
$model = new Event();
$model->created_date = $date;
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['index']);
}else{
return $this->renderAjax('create', [
'model' => $model,
]);
}
}
/**
* Updates an existing Event model.
* If update is successful, the browser will be redirected to the 'view' page.
* @param integer $id
* @return mixed
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->renderAjax('update', [
'model' => $model,
]);
}
}
/**
* Deletes an existing Event model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* @param integer $id
* @return mixed
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the Event model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* @param integer $id
* @return Event the loaded model
* @throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Event::findOne($id)) !== null) {
return $model;
}
throw new NotFoundHttpException('The requested page does not exist.');
}
/**
*
* @param type $choice
* @return type
*/
public function actionFilterEvents($choice = null) {
Yii::$app->reponse->format = \yii\web\Response::FORMAT_JSON;
$query = models\Event::find();
if( is_null($choice) || $choice=='all'){
//the function should return the same events that you were loading before
$dbEvents = $query->all();
$events = $this->loadEvents($dbEvents);
} else{
//here you need to look up into the data base
//for the relevant events against your choice
$dbEvents = $query->where(['=', 'column_name', ':choice'])
->params([':choice' => $choice])
->asArray()
->all();
$events = $this->loadEvents($dbEvents);
}
return $events;
}
/**
*
* @param type $dbEvents
* @return \yii2fullcalendar\models\Event
*/
private function loadEvents($dbEvents) {
foreach( $dbEvents AS $event ){
//Testing
$Event = new \yii2fullcalendar\models\Event();
$Event->id = $event->id;
$Event->title = $event->categoryAsString;
$Event->description = $event->description;
$Event->start = date('Y-m-d\TH:i:s\Z', strtotime($event->created_date . ' ' . $event->created_date));
$Event->end = date('Y-m-d\TH:i:s\Z', strtotime($event->time_out . ' ' . $event->time_out));
$Event->status = $event->status;
$Event->remarks = $event->remarks;
$events[] = $Event;
}
return $events;
}
}
Это событие-индекс:
<?php
use yii\helpers\Html;
use yii\grid\GridView;
use yii\bootstrap\Modal;
$this->title = 'Roster Bul Hanine Project';
$this->params['breadcrumbs'][] = $this->title;
$js=<<< JS
var eventSource=['/event/filter-events'];
$("#select_name").on('change',function() {
//get current status of our filters into eventSourceNew
var eventSourceNew=['/event/filter-events?choice=' + $(this).val()];
//remove the old eventSources
$('#event').fullCalendar('removeEventSource', eventSource[0]);
//attach the new eventSources
$('#event').fullCalendar('addEventSource', eventSourceNew[0]);
$('#event').fullCalendar('refetchEvents');
//copy to current source
eventSource = eventSourceNew;
});
JS;
$this->registerJs($js, \yii\web\View::POS_READY);
?>
<div class="event-index">
<h1><?= Html::encode($this->title) ?></h1>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<p><?= Html::a('Create Roster', ['create'], ['class' => 'btn btn-success']) ?></p>
<p>
<select class="model_attribute" id="select_name">
<option value="all">All Tech</option>
<option value="0">Hendy Nugraha</option>
<option value="1">Ginanjar Nurwin</option>
<option value="2">Rio Andhika</option>
</select>
</p>
<div id="event"></div>
<?php
Modal::begin([
'header'=>'<h4>Roster</h4>',
'id' => 'model',
'size' => 'model-lg',
]);
echo "<div id='modelContent'></div>";
Modal::end();
?>
<?=\yii2fullcalendar\yii2fullcalendar::widget(array(
'events'=> $events,
'id' => 'event',
'clientOptions' => [
'editable' => true,
'eventSources' => ['/event/filter-events'],
'draggable' => true,
'droppable' => true,
],
'eventClick' => "function(calEvent, jsEvent, view) {
$(this).css('border-color', 'red');
$.get('index.php?r=event/update',{'id':calEvent.id}, function(data){
$('.modal').modal('show')
.find('#modelContent')
.html(data);
})
$('#calendar').fullCalendar('removeEvents', function (calEvent) {
return true;
});
}",
/*$('#event').fullCalendar({
eventRender: function(event, element) {
if(event.status == "on leave") {
element.css('background-color', '#131313');
} else if (event.status == "stand by") {
element.css('background-color', '#678768');
} else if (event.status == "active") {
element.css('background-color', '#554455');
}
},
});*/
));
?>
</div>
ниже приведен скриншот, когда я комментирую 'events'=> $events внутри index.php (согласно вашей инструкции). даже я выбираю через опцию выбора, это не фильтрует событие
если я отменяю комментарий 'events'=> $events, он показывает все события, но когда я выбираю опцию select, это не фильтрует событие. ниже снимка экрана:
1 ответ
Используемое расширение включает в себя последнюю версию FullCalendar v3.9.0
, Так что обратитесь к последней версии API 3 для всех ссылок на документацию ниже.
Подход
Для меня, если мне придется реализовать это, я не буду использовать events
вариант, так как нам нужно отфильтровать события во время выполнения на основе параметра, выбранного из раскрывающегося списка, лучше использовать вариант eventSources
вариант. Он позволяет указать несколько источников событий. Эта опция используется вместо events
Вы можете поместить любое количество массивов событий, функций, URL-адресов фида JSON или полных объектов-источников событий в eventSources
массив.
Простой пример на основе JavaScript
$('#calendar').fullCalendar({
eventSources: [
'/feed1.php',
'/feed2.php'
]
});
Если вы посмотрите документацию для Fullcalendar, у них есть раздел, связанный с событиями, с именем Event Data
где вы можете увидеть различные варианты наряду с упомянутым.
Начать с
Мы начнем с предоставления eventSources
URL-адрес нашей ленты JSON для событий календаря и удалите параметр events
, Я буду использовать один источник, вы можете иметь несколько, если хотите, но я буду кратким и простым.
Измените код для виджета и добавьте eventSources
вариант под clientOptions
вариант для виджета.
<?=
\yii2fullcalendar\yii2fullcalendar::widget(array(
'id' => 'eventFilterCalendar',
'clientOptions' => [
'editable' => true,
'eventSources' => ['/schedule/filter-events'],
'draggable' => true,
'droppable' => true,
],
'eventClick' => "function(calEvent, jsEvent, view) {
$(this).css('border-color', 'red');
$.get('index.php?r=event/update',{'id':calEvent.id}, function(data){
$('.modal').modal('show')
.find('#modelContent')
.html(data);
});
$('#calendar').fullCalendar('removeEvents', function (calEvent) {
return true;
});
}",
));
?>
На этом этапе, если вы обновите календарь, вы не увидите никаких событий, которые вы загружали ранее, потому что ранее вы использовали 'events'=>$events
чтобы загрузить события, но теперь мы предоставили источник URL '/schedule/filter-events'
(измените его на соответствующий controller/action
вы хотите использовать, я буду использовать тот же URL для примера).
Вторая часть
Итак $events
то, что вы загружали раньше, теперь будет загружаться через новое действие, которое мы собираемся создать. Если вы следуете примеру, представленному на странице GitHub для расширения, и загружаете ваши события из модели базы данных, а затем зацикливаетесь на цикле for, чтобы загрузить все события в \yii2fullcalendar\models\Events()
модель, а затем загрузить этот массив.
Поскольку вы не предоставили никаких сведений о модели, которую вы используете для базы данных для хранения и загрузки событий в календарь, я предполагаю, что название вашей модели MyEvents
измените его соответственно и поле column_name
в запросе.
/**
*
* @param type $choice
* @return type
*/
public function actionFilterEvents($choice = null) {
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$query = MyEvents::find();
if( is_null($choice) || $choice=='all'){
//the function should return the same events that you were loading before
$dbEvents = $query->all();
$events = $this->loadEvents($dbEvents);
} else{
//here you need to look up into the data base
//for the relevant events against your choice
$dbEvents = $query->where(['=', 'column_name', ':choice'])
->params([':choice' => $choice])
->asArray()
->all();
$events = $this->loadEvents($dbEvents);
}
return $events;
}
/**
*
* @param type $dbEvents
* @return \yii2fullcalendar\models\Event
*/
private function loadEvents($dbEvents) {
foreach( $dbEvents AS $event ){
//Testing
$Event = new \yii2fullcalendar\models\Event();
$Event->id = $event->id;
$Event->title = $event->categoryAsString;
$Event->start = date('Y-m-d\TH:i:s\Z', strtotime($event->date_start . ' ' . $event->time_start));
$Event->end = date('Y-m-d\TH:i:s\Z', strtotime($event->date_end . ' ' . $event->time_end));
$events[] = $Event;
}
return $events;
}
Вещи, чтобы заметить выше
$choice
параметр вactionFilterEvents
сnull
в качестве значения по умолчанию для перечисления всех событий, когда календарь загружается в первый раз.-
loadEvents()
способ загрузки искомых событий из базы данных в\yii2fullcalendar\model\Events
измените имена полей, используемые вforeach
с соответствующими именами полей модели, которые вы будете использовать вместоMyEvents
,
На этом этапе, если вы все сделали правильно, как уже упоминалось, если вы обновите страницу, вы увидите загрузку событий по умолчанию в календаре.
Актуальная часть
Теперь наступает момент фильтрации событий в зависимости от выбора раскрывающегося списка. Для серверной стороны мы уже проделали работу выше, else
часть будет обрабатывать фильтрацию всех событий из базы данных, сравнивая выбранный выбор с нужным столбцом column_name
(замените его именем поля, которое вы хотите сравнить). Часть, которая еще предстоит сделать, теперь на стороне клиента, мы свяжем onchange
событие раскрывающегося списка, а затем использовать в основном эти 3 methods
предоставлено fullcalendar
removeEventSource
, Динамически удаляет источник события. События из источника будут немедленно удалены из календаря.addEventSource
, Динамически добавляет источник события. Источником может быть массив /URL/ функция, как в опции событий. События будут немедленно получены из этого источника и помещены в календарь.refetchEvents
, Получает события из всех источников и отображает их на экране.
Каждый раз, когда мы выбираем выбор предыдущего eventSource
удаляется и новый eventSource
добавлено так в основном будет строить URL-адрес schedule/filter-events?choice=all
если All Tech
выбран, schedule/filter-events?choice=0
если Hendy Nugraha
выбрано и так далее.
Добавьте приведенный ниже javascript поверх вашего представления, где вы инициализировали свой виджет.
Убедитесь, что селектор используется ниже #select_name
соответствует вашему раскрывающемуся id
,
$js = <<< JS
var eventSource=['/schedule/filter-events'];
$("#select_name").on('change',function() {
//get current status of our filters into eventSourceNew
var eventSourceNew=['/schedule/filter-events?choice=' + $(this).val()];
//remove the old eventSources
$('#eventFilterCalendar').fullCalendar('removeEventSource', eventSource[0]);
//attach the new eventSources
$('#eventFilterCalendar').fullCalendar('addEventSource', eventSourceNew[0]);
$('#eventFilterCalendar').fullCalendar('refetchEvents');
//copy to current source
eventSource = eventSourceNew;
});
JS;
$this->registerJs($js, \yii\web\View::POS_READY);
Сделайте все, как сказано выше, и он начнет работать и покажет вам отфильтрованные результаты, как только вы измените параметры в раскрывающемся списке.
Примечание: я предоставил решение выше из работающего проекта, с Yii2.0.15.1
и последнее доступное расширение.
РЕДАКТИРОВАТЬ
Я поражен, что вы не можете различить серверную часть, HTML и javascript, код, который я предоставил, относящийся к javascript, который вам нужно было вставить в представление event-index
был внутри heredoc
и вам нужно было просто скопировать вставить его, но каким-то образом вы завернули Javascript внутри <script>
пометить и удалить heredoc
? и к тому же вы звоните $this->registerJs()
внутри тега сценария, а не <?php ?>
теги? ¯ \ _ (ツ) _ / ¯.
И вы даже не изменили имя контроллера в URL для var eventSource=['/schedule/filter-events'];
Javascript код вашего контроллера Event
и не schedule
, я писал в каждой точке, где я предполагал, что имя модели или контроллера изменяет его соответственно, даже ваш код виджета не обновляется соответственно, он также имеет 'eventSources' => ['/schedule/filter-events'],
когда это должно быть 'eventSources' => ['/event/filter-events'],
,
Так что на этот раз просто скопируйте и вставьте весь код вида ниже, и ничего не меняйте. Я больше не буду кормить тебя ложкой только потому, что ты должен пометить это правильно, хотя это правильный ответ и должен был быть награжден.
Устранение неполадок и исправление синтаксических ошибок - это ваши обязанности, которые необходимо устранить при интеграции кода. Предоставленное решение работает, и если вы не смогли его интегрировать, это не означает, что оно не должно быть помечено правильным ответом.
"Событийно-index.php`
<?php
use yii\helpers\Html;
use yii\grid\GridView;
use yii\bootstrap\Modal;
$this->title = 'Roster Bul Hanine Project';
$this->params['breadcrumbs'][] = $this->title;
$js=<<< JS
var eventSource=['/event/filter-events'];
$("#select_name").on('change',function() {
//get current status of our filters into eventSourceNew
var eventSourceNew=['/event/filter-events?choice=' + $(this).val()];
//remove the old eventSources
$('#event').fullCalendar('removeEventSource', eventSource[0]);
//attach the new eventSources
$('#event').fullCalendar('addEventSource', eventSourceNew[0]);
$('#event').fullCalendar('refetchEvents');
//copy to current source
eventSource = eventSourceNew;
});
JS;
$this->registerJs($js, \yii\web\View::POS_READY);
?>
<div class="event-index">
<h1><?= Html::encode($this->title) ?></h1>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<p><?= Html::a('Create Roster', ['create'], ['class' => 'btn btn-success']) ?></p>
<p>
<select class="model_attribute" id="select_name">
<option value="all">All Tech</option>
<option value="0">Hendy Nugraha</option>
<option value="1">Ginanjar Nurwin</option>
<option value="2">Rio Andhika</option>
</select>
</p>
<div id="event"></div>
<?php
Modal::begin([
'header'=>'<h4>Roster</h4>',
'id' => 'model',
'size' => 'model-lg',
]);
echo "<div id='modelContent'></div>";
Modal::end();
?>
<?=\yii2fullcalendar\yii2fullcalendar::widget(array(
//'events'=> $events,
'id' => 'event',
'clientOptions' => [
'editable' => true,
'eventSources' => ['/event/filter-events'],
'draggable' => true,
'droppable' => true,
],
'eventClick' => "function(calEvent, jsEvent, view) {
$(this).css('border-color', 'red');
$.get('index.php?r=event/update',{'id':calEvent.id}, function(data){
$('.modal').modal('show')
.find('#modelContent')
.html(data);
})
$('#calendar').fullCalendar('removeEvents', function (calEvent) {
return true;
});
}",
/*$('#event').fullCalendar({
eventRender: function(event, element) {
if(event.status == "on leave") {
element.css('background-color', '#131313');
} else if (event.status == "stand by") {
element.css('background-color', '#678768');
} else if (event.status == "active") {
element.css('background-color', '#554455');
}
},
});*/
));
?>
</div>