Jonas
Jonas

Reputation: 261

TypeError: date[("get" + method)] is not a function in React-big-calendar

I am trying to change the view from month to week but in meantime it give me an error . I am new to react and react-big-calendar could someone please help me how to solve this problem . When I change calendar view to month it working fine but when I changed it to week or day so it give me an error. please help me Thanks

Code

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import MyCalendar from 'react-big-calendar';
import CustomToolbar from './toolbar';
import Popup from 'react-popup';
import Input from './input';
import moment from 'moment';
import { fetchEvents, createEvent, updateEvent, deleteEvent } from '../actions';


// Setup the localizer by providing the moment (or globalize) Object to the correct localizer.
const localizer = MyCalendar.momentLocalizer(moment); // or globalizeLocalizer

class Calendar extends Component {

    componentDidMount() {
        this.props.fetchEvents();
    }

    //RENDER SINGLE EVENT POPUP CONTENT
    renderEventContent(slotInfo) {
        const date = moment(slotInfo.start).format('MMMM D, YYYY');
        return (
            <div>
                <p>Date: <strong>{date}</strong></p>
                <p>Subject: {slotInfo.taskChage}</p>
                <p>Time : {slotInfo.time}</p>
                <p>Date : { slotInfo.date}</p>
                <p>Notes : {slotInfo.notes}</p>
                <p>User Id : {slotInfo.userId}</p>
            </div>
        );
    }

    //ON SELECT EVENT HANDLER FUNCTION
    onSelectEventHandler = (slotInfo) => {
        Popup.create({
            title: slotInfo.title,
            content: this.renderEventContent(slotInfo),
            buttons: {
                right: [{
                    text: 'Edit',
                    className: 'info',
                    action: function () {
                        Popup.close(); //CLOSE PREVIOUS POPUP
                        this.openPopupForm(slotInfo); //OPEN NEW EDIT POPUP
                    }.bind(this)
                }, {
                    text: 'Delete',
                    className: 'danger',
                    action: function () {
                        //CALL EVENT DELETE ACTION
                        this.props.deleteEvent(slotInfo.id);
                        Popup.close();
                    }.bind(this)
                }]
            }
        });
    }

    //HANDLE FUNCITON ON SELECT EVENT SLOT
    onSelectEventSlotHandler = (slotInfo) => {
        this.openPopupForm(slotInfo); //OPEN POPUP FOR CREATE/EDIT EVENT
    }

    //POPUP-FORM FUNCTION FOR CREATE AND EDIT EVENT
    openPopupForm = (slotInfo) => {
        let newEvent = false;
        let popupTitle = "Update Event";
        if(!slotInfo.hasOwnProperty('id')) {
            slotInfo.id = moment().format('x');  //Generate id with Unix Millisecond Timestamp
            slotInfo.title = null;
            slotInfo.taskChange = null;
            slotInfo.message=null;
            popupTitle = "Create Event";
            newEvent = true;
        }

        let titleChange = function (value) {
            slotInfo.title = value;
        };
        let taskChange = function (value) {
            slotInfo.taskChage = value;
        };

        let timeChange = function (value) {
            slotInfo.time = value;
        };

        let dateChnage = function ( value){
            slotInfo.date=value;
        };


        let notesChange = function ( value){
            slotInfo.notes=value;
        };

        let userId = function ( value){
            slotInfo.userId=value;
        };

        Popup.create({
            title: popupTitle,
            content: <div>
                        <Input onChange={titleChange} placeholder="Subject" />
                        <Input onChange={taskChange} placeholder="Task Type"  />
                        <Input onChange={timeChange} placeholder="Time"/>
                        <Input onChange={dateChnage} placeholder="Date"/>
                        <Input onChange={notesChange} placeholder="Notes"/>
                        <Input onChange={userId} placeholder="User Id"/>
                    </div>,
            buttons: {
                left: ['cancel'],
                right: [{
                    text: 'Save',
                    className: 'success',
                    action: function () {
                        //CHECK THE ID PROPERTY FOR CREATE/UPDATE
                        if(newEvent) {
                            this.props.createEvent(slotInfo); //EVENT CREATE ACTION
                        } else {
                            this.props.updateEvent(slotInfo); //EVENT UPDATE ACTION
                        }
                        Popup.close();
                    }.bind(this)
                }]
            }
        });
    }

    //EVENT STYLE GETTER FOR SLYLING AN EVENT ITEM
    eventStyleGetter(event, start, end, isSelected) {
        let current_time = moment().format('YYYY MM DD');
        let event_time = moment(event.start).format('YYYY MM DD');
        let background = (current_time>event_time) ? '#DE6987' : '#8CBD4C';
        return {
            style: {
                backgroundColor: background
            }
        };
    }

    render() {
        return (
            <div className="calendar-container">
                <MyCalendar
                    popup
                    selectable
                    localizer={localizer}
                    defaultView={MyCalendar.Views.WEEK}
                    components={{toolbar: CustomToolbar}}
                    views={['week']}
                    style={{height: 600}}
                    events={this.props.events}
                    eventPropGetter={(this.eventStyleGetter)}
                    onSelectEvent={(slotInfo) => this.onSelectEventHandler(slotInfo)}
                    onSelectSlot={(slotInfo) => this.onSelectEventSlotHandler(slotInfo)}
                />
                {console.log(this.props.event)}
                <Popup />
            </div>
        );
    }
}

function mapStateToProps(state) {
    return {
        events: state.events
    };
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators({ 
        fetchEvents, 
        createEvent, 
        updateEvent, 
        deleteEvent
    }, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(Calendar);

Upvotes: 25

Views: 10563

Answers (5)

Michael Peng
Michael Peng

Reputation: 69

I had the same issue before. The solution depends on your date field.

If date field is like start: new Date('2024-09-02T08:00:00-04:00'), then use this: startAccessor="start"

If date field is like "start": "2024-01-15T08:00:00-04:00", then use this: startAccessor={(event) => { return new Date(event.start) }}

In the 2nd case, below will throw same error. startAccessor={(event) => { return moment(event.start) }}

Hope this helps.

Upvotes: 6

Fazle Rabbi Ador
Fazle Rabbi Ador

Reputation: 887

this happens when the date you are trying to display is "String" when actually "date" is an "Object" type, then you could do something like this:

as event data example convert string to date object.

{
  id: 8,
  title: "Meeting",
  start: new Date("2022-05-12T08:00:00.000Z"),
  end: new Date("2022-05-12T09:00:00.000Z")
}

Upvotes: 2

SaimumIslam27
SaimumIslam27

Reputation: 1184

const formatted = moment(time).toDate();

Upvotes: 2

M.Daniyal Aslam
M.Daniyal Aslam

Reputation: 517

Make sure that you have the correct values for start and end keys in your event object, your event object should be like :

data = [
  {
    title: "My event",
    allDay: false,
    start: new Date(2020, 10, 25, 10, 0), // 10.00 AM
    end: new Date(2020, 10, 25, 11, 0), // 2.00 PM
  }
  ]

Upvotes: 0

Steve -Cutter- Blades
Steve -Cutter- Blades

Reputation: 5432

For anyone finding this, a few things.

Your localizer handles manipulation of dates under the hood. All dates that you pass in (from your getNow and date props, all the way to your individual event.start and event.end dates) should be true JS Date objects.

Your various method props, for working with events or setting styling or whatever, will receive true JS Date objects, not localizer objects or UTC strings or whatever.

RBC will only work with true JS Date objects. If you pass it moment instances or date strings or something else, it might display but it will operate funky, as RBC will handle all conversions under the hood, and it's use of the date-arithmatic library, internally, works with true JS Dates and not your localizer objects.

Upvotes: 29

Related Questions