Angular fullcalendar adding an event when clicking on the day - javascript

Hi hope you will help me on this
I'm working on Angular 10 and full calendar v5 and I want to know how can I add an event into the day when clicking on it
export class CalendarComponent implements OnInit{
nomaction;
constructor(public dialog: MatDialog) { }
ngOnInit(): void {
}
calendarOptions: CalendarOptions = {
initialView: 'dayGridMonth',
weekends: true,
dateClick: this.handleDateClick.bind(this), // bind is important!
events: [
{ title: 'event 1', date: '2020-08-20' },
{ title: 'event 2', date: '2020-08-21' }
]
};
handleDateClick(arg) {
const dialogRef = this.dialog.open(AddeventComponent, {
width: '250px',
data: {nomaction: this.nomaction}
});
dialogRef.afterClosed().subscribe(result => {
this.nomaction = result.nomaction;
this.calendarOptions.events = [{ title: this.nomaction, date: arg.dateStr }];//a code for adding an event into the day
console.log('action',this.nomaction);
});
}
toggleWeekends() {
this.calendarOptions.weekends = !this.calendarOptions.weekends
}
}
this.calendarOptions.events is not an array so I couldn't use push to add the object !
How can I add it without losing my first data !

Add on your calendar options this :
calendarOptions: CalendarOptions = {
initialView: 'dayGridMonth',
weekends: true,
dateClick: this.handleDateClick.bind(this), // bind is important!
events: [
{ title: 'event 1', date: '2020-08-20' },
{ title: 'event 2', date: '2020-08-21' }
],
dateClick:function (info) {
console.log("See day infos: ",info);
}
};
I let you the documentation here

Related

ng2-smart-table default column sorting is not working

not sure if someone has the same issue before, but I have been struggling with ng2-smart-table component.
I have a custom data source I am trying to load and display using this component. By default I would like to sort by last update time in descending order. I have the following definition for my settings:
settings = {
hideSubHeader: true,
noDataMessage: 'There are no matching search results',
columns: {
priority: {
title: '!',
sort: true,
},
issueId: {
title: 'ID',
sort: true,
},
issueType: {
title: 'Issue',
sort: true,
},
patientFullName: {
title: 'Customer',
sort: true,
},
LastUpdated: {
title: 'Last Updated',
type: 'date',
sort: true,
sortDirection: 'desc',
valuePrepareFunction: (date) => {
if (date) {
return new DatePipe('en-US').transform(date, 'MM/dd/yyyy hh:mm a');
}
return null;
},
},
assignee: {
title: 'Assigned To',
sort: true,
},
callStatus: {
title: 'Call Status',
sort: true,
valuePrepareFunction: (callStatus) => {
let displayVal = 'N/A';
if (callStatus) {
displayVal = CallStatus[callStatus];
}
return displayVal;
}
},
physicianName: {
title: 'Contact Name',
sort: true,
},
followUpTime: {
title: 'Follow Up',
sort: true,
sortDirection: 'desc',
valuePrepareFunction: (date) => {
if (date) {
return new DatePipe('en-US').transform(date, 'MM/dd/yyyy hh:mm a');
}
return null;
},
},
status: {
title: 'Status',
sort: true,
},
medicalGroupName: {
title: 'Medical Group Name',
sort: true,
},
},
actions: {
add: false,
edit: false,
delete: false
},
pager: {
display: true,
perPage: 50
},
};
Inside the constructor and also in the "init" method, I always call the following:
this.source.setSort([{ field: 'LastUpdated', direction: 'desc' }]);
But it keeps on sorting by default by "FollowUpTime". I was wondering if there's another way in which I can force to sort by an specific column or if I am missing something probably.
Any clue or help will be highly appreciated. I will keep on trying to find a solution for this.
PS. Curious thing is that whenever I remove the object that corresponds to the "FollowUpTime" column, it works fine, I mean, this portion of code:
followUpTime: {
title: 'Follow Up',
sort: true,
sortDirection: 'desc',
valuePrepareFunction: (date) => {
if (date) {
return new DatePipe('en-US').transform(date, 'MM/dd/yyyy hh:mm a');
}
return null;
},
},

Fullcalendar initializing before data is loaded (Empty calendar)

I'm trying to implement the Timeline calendar from Fullcalendar with Vuejs, but the calendar is initializing before the data is ready. It works if I navigate to other pages and comeback.. all the data is there. I've created the methods: getEmployees() and getApprovedAbsences(), to create the array with the data needed.
I'm fairly new to Vue js, so any help would be appreciated. Thanks
Code:
<template>
<div class="admin-calendar">
<FullCalendar :options="calendarOptions" />
</div>
</template>
<script>
import FullCalendar from '#fullcalendar/vue'
import dayGridPlugin from '#fullcalendar/daygrid'
import interactionPlugin from '#fullcalendar/interaction'
import resourceTimelinePlugin from '#fullcalendar/resource-timeline'
import ptLocale from '#fullcalendar/core/locales/pt';
import moment from "moment";
export default {
components: { FullCalendar },
props: {
getAbsencesRequests: {
type: Array,
},
employees: {
type: Array,
},
},
data() {
return {
calendarOptions: {
plugins: [ resourceTimelinePlugin ],
headerToolbar: {
left: 'today prev,next',
center: 'title',
right: 'resourceTimelineDay,resourceTimelineWeek,resourceTimelineMonth'
},
locales: [ ptLocale ],
locale: 'pt',
aspectRatio: 1.6,
initialView: 'resourceTimelineDay',
resourceGroupField: 'department',
resourceAreaHeaderContent: 'Colaboradores',
handleWindowResize: false,
height: 400,
resources: this.getEmployees,
events: this.getApprovedAbsences,
}
}
},
methods: {
async getApprovedAbsences() {
let absenceList = []
this.getAbsencesRequests.forEach(absence => {
if (absence.status === "APPROVED") {
absence.periods.forEach((period) => {
absenceList.push({
start: moment(period.validFromLocaleDate, "DD/MM/YYYY").format("YYYY-MM-DD"),
end: moment(period.validToLocaleDate, "DD/MM/YYYY").format("YYYY-MM-DD"),
title: absence.absenceName,
resourceId: absence.requesterId,
});
});
}
})
return absenceList
},
async getEmployees() {
let employeeList = []
this.employees.forEach(employee => {
employeeList.push({
id: employee.id,
department: employee.department["id"] === "" ? "SEM DEPARTAMENTO ATRIBUÍDO" : employee.department["name"],
title: employee.name,
})
})
return employeeList
}
},
}
</script>
You could add an if statement to check if data is ready. Something like this:
<template>
<div class="admin-calendar">
<FullCalendar
v-if="employeeList && absenceList"
:options="calendarOptions" />
</div>
</template>
This would only load FullCalendar component after resources and events are not null.
Now, change data to this:
data() {
return {
employeeList: null,
absenceList: null,
calendarOptions: {
plugins: [ resourceTimelinePlugin ],
headerToolbar: {
left: 'today prev,next',
center: 'title',
right: 'resourceTimelineDay,resourceTimelineWeek,resourceTimelineMonth'
},
locales: [ ptLocale ],
locale: 'pt',
aspectRatio: 1.6,
initialView: 'resourceTimelineDay',
resourceGroupField: 'department',
resourceAreaHeaderContent: 'Colaboradores',
handleWindowResize: false,
height: 400,
resources: this.getEmployees,
events: this.getApprovedAbsences,
}
}
}
And change load methods to store data in component variables:
methods: {
async getApprovedAbsences() {
let tmpAbsenceList = []
this.getAbsencesRequests.forEach(absence => {
if (absence.status === "APPROVED") {
absence.periods.forEach((period) => {
tmpAbsenceList.push({
start: moment(period.validFromLocaleDate, "DD/MM/YYYY").format("YYYY-MM-DD"),
end: moment(period.validToLocaleDate, "DD/MM/YYYY").format("YYYY-MM-DD"),
title: absence.absenceName,
resourceId: absence.requesterId,
});
});
}
})
absenceList = tmpAbsenceList
},
async getEmployees() {
let tmpEmployeeList = []
this.employees.forEach(employee => {
tmpEmployeeList.push({
id: employee.id,
department: employee.department["id"] === "" ? "SEM DEPARTAMENTO ATRIBUÍDO" : employee.department["name"],
title: employee.name,
})
})
employeeList = tmpEmployeeList
}
},
And finally, call getMethods within created():
async created() {
await this.getApprovedAbsences()
await this.getEmployees()
}
This should load everything first, and then call FullCalendar. It should guarantee that everything is set up before loading the component. Try it and check if this idea works for you...

Adapt React.createClass method to ES6 Class Component with react-data-grid

I am working the react-data-grid library to create an filterable datatable in react. All of their examples use the depreciated React.createClass method, and I am trying to refactor to the ES6 Class Components.
Specifically, I am trying to refactor the Filterable Grid example:
demo
source
gist of non-refactored adaption that is working
My refactored code looks like this:
import React from 'react'
import ReactDataGrid from 'react-data-grid'
const { Toolbar, Data: { Selectors } } = require('react-data-grid-addons')
class FilterableTable extends React.Component {
constructor(props) {
super(props);
this._columns = [
{
key: 'id',
name: 'ID',
width: 80
},
{
key: 'task',
name: 'Title',
editable: true
},
{
key: 'priority',
name: 'Priority',
editable: true
},
{
key: 'issueType',
name: 'Issue Type',
editable: true
},
{
key: 'complete',
name: '% Complete',
editable: true
},
{
key: 'startDate',
name: 'Start Date',
editable: true
},
{
key: 'completeDate',
name: 'Expected Complete',
editable: true
}
];
this.state = { rows: this.createRows(1001), filters: {} };
console.log(this.state);
}
getRandomDate = (start, end) => {
return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime())).toLocaleDateString();
}
createRows = () => {
let rows = [];
for (let i = 1; i < 1000; i++) {
rows.push({
id: i,
task: 'Task ' + i,
complete: Math.min(100, Math.round(Math.random() * 110)),
priority: ['Critical', 'High', 'Medium', 'Low'][Math.floor((Math.random() * 3) + 1)],
issueType: ['Bug', 'Improvement', 'Epic', 'Story'][Math.floor((Math.random() * 3) + 1)],
startDate: this.getRandomDate(new Date(2015, 3, 1), new Date()),
completeDate: this.getRandomDate(new Date(), new Date(2016, 0, 1))
});
}
return rows;
}
getRows = () => {
return Selectors.getRows(this.state);
}
getSize = () => {
return this.getRows().length;
}
rowGetter = ( rowIdx ) => {
let rows = this.getRows();
return rows[rowIdx];
}
handleFilterChange = ({ filter }) => {
let newFilters = Object.assign({}, this.state.filters);
if (filter.filterTerm) {
newFilters[filter.column.key] = filter;
} else {
delete newFilters[filter.column.key];
}
this.setState({ filters: newFilters });
}
onClearFilters = () => {
// all filters removed
this.setState({filters: {} });
}
render() {
return (
<ReactDataGrid
columns={this._columns}
rowGetter={this.rowGetter}
enableCellSelect={true}
rowsCount={this.getSize()}
minHeight={800}
toolbar={<Toolbar enableFilter={true}/>}
onAddFilter={this.handleFilterChange}
onClearFilters={this.onClearFilters} />);
}
}
export default FilterableTable
Issue:
An issue arises when I click the filter button - a new header row is rendered (via the Toolbar component), but there is no input field. This screenshot shows the two examples side by side - my ES6 version on top and the createClass version on the bottom:
I am not sure what is causing this, but have a feeling it might be due to the way I am importing Toolbar ? Any help or a point in the right direction would be greatly appreciated ! (As well as any other suggestions re refactoring this component.)
To enable filtering for a given column, you need to set filterable=true for that column. So, add filterable:true to each object in this._columns. For more info, check http://adazzle.github.io/react-data-grid/examples.html#/filterable-grid.
this._columns = [
{
key: 'id',
name: 'ID',
width: 80
},
{
key: 'task',
name: 'Title',
editable: true,
filterable:true
},
{
key: 'priority',
name: 'Priority',
editable: true,
filterable:true
},
{
key: 'issueType',
name: 'Issue Type',
editable: true,
filterable:true
},
{
key: 'complete',
name: '% Complete',
editable: true,
filterable:true
},
{
key: 'startDate',
name: 'Start Date',
editable: true,
filterable:true
},
{
key: 'completeDate',
name: 'Expected Complete',
editable: true,
filterable:true
}
];

Ext js handling setting minDate of a datepicker using the value of another datepicker

Good day all.
I'm doing a date range selection using two datepickers defined as follow:
items: {
xtype: 'panel',
layout: 'hbox',
items: [{
title: 'FROM',
margin: '5',
items: {
xtype: 'datepicker',
start: true,
reference: 'startDate',
maxDate: new Date(),
maxText: 'Future dates are not available',
bind: {
value: '{startDate}'
},
showToday: false,
listeners: {
select: 'checkDateInterval'
}
}
}, {
title: 'TO',
margin: '5',
items: {
xtype: 'datepicker',
start: false,
reference: 'endDate',
bind: {
value: '{endDate}'
},
maxDate: new Date(),
showToday: false,
listeners: {
select: 'checkDateInterval'
}
}
}]
}
What I'm trying to achieve is to set the minDate of the second datepicker as the date selected in the first one, so the user cannot select a date in the past once he selected the first date.
I'd also like to reset the second date once the user select a date on the first datepicker.
how can I point to the date selected on the first element?
Use this:
{
xtype: 'datefield',
hidden: true,
width: '17%',
editable: false,
tabIndex: 6,
id: 'start',
format: 'Y-m-d',
minDate: new Date(),
name: 'start_date',
onTriggerClick: function() {
var dt = this;
var due = Ext.getCmp('Due');
dt.setMaxValue(due.value);
Ext.form.DateField.prototype.onTriggerClick.apply(dt, arguments);
},
listeners: {
change: function(dp, date) {
var due = Ext.getCmp('Due');
due.setValue(date);
}
}
}, {
xtype: 'datefield',
hidden: true,
id: 'Due',
editable: false,
tabIndex: 8,
width: '17%',
format: 'Y-m-d',
name: 'due_date',
onTriggerClick: function() {
var dt = this;
dt.setMinValue(Ext.getCmp('start').value);
Ext.form.DateField.prototype.onTriggerClick.apply(dt, arguments);
},
listeners: {
change: function(dp, date) {
var start = Ext.getCmp('start');
start.setValue(date);
}
}
}
The maxDate property is bindable, so you can just move the endDate minDate property to the bind config, pointing to startDate, like this
items: {
xtype: 'datepicker',
start: false,
reference: 'endDate',
bind: {
value: '{endDate}',
minDate: '{startDate}',
},
showToday: false,
listeners: {
select: 'checkDateInterval'
}
}
You can reset the endDate picker value in the checkDateInterval function of your controller.
var picker = this.getView().lookupReference('endDate');
picker.setValue(null);

List Component: How to detect which item was selected?

I can access a list (as a container of items) in a controller but I do not know how to access list items properties.
How to create the correct ComponentQuery rule? I tried 'list > item' but it does not work.
Each item has it's title but I get 'undefined' as output in selectSection.
Ext.define( 'UGP.controller.BeginList',
{
extend: 'Ext.app.Controller',
config:
{
views: [ 'BeginList' ],
control:
{
'list':
{
select: 'selectSection'
}
}
},
selectSection: function()
{
Ext.Msg.alert( 'title=' + this.title );
}
}
);
The BeginList.js with the list component:
Ext.define( 'UGP.view.BeginList',
{
extend: 'Ext.List',
config:
{
fullscreen: true,
itemTpl: '{title}',
data:
[
{ title: 'Chapter 1', id: 0, action: "selectSection" },
{ title: 'Chapter 2', id: 1, action: "selectSection" },
{ title: 'Chapter 3', id: 2, action: "selectSection" },
{ title: 'Chapter 4', id: 3, action: "selectSection" }
]
}
}
);
You can see in the select event documentation that it passes arguments. So you can change the signature of your selectSection function to this :
selectSection: function (list, record) {
Ext.Msg.alert( 'title=' + record.get( 'title' ) );
}
You can also take a look at the itemTap event which usually the one used to detect tap events on a list item.
Hope this helps

Categories

Resources