Our powerful JS Calendar component


Post by blgarcia »

Hello,
I'm adding a custom element to the top bar with the following config:

{
    "items": {
        "userMenu": {
            "cls": "user-menu",
            "html": "[stringified html]",
            "menu": {
                "items": [
                    {
                        "type": "widget",
                        "html": "[more stringified html]"
                    }
                ]
            }
        }
    }
}

On initial render, things look great (top half of attached image).

but when a component that is outside of calendar, and completely independent of the calendar changes, the tbar updates to ONLY show the custom item (bottom half of attached image). The data and configs that the calendar is consuming is not changing, and exactly the same as initial render. the data that is changed by the external widget is not being consumed or utilized by the calendar.

I am using the @bryntum/calendar-react wrappers, and fairly recent version of react.

Am i missing something in regards to the tbar config?
is there a way to indicate that i want all the default tbar items?
why is the same config fine on initial render, but bad after an update?
why don't the react demos on your site provide source code to look at?

also, side note, my company paid for the license, so its not associated to my email address, how do i make the connection between the two so i can continue to have access to the forum?

Attachments
calendar-tbar-bug-example.png
calendar-tbar-bug-example.png (287.33 KiB) Viewed 466 times

Post by marcio »

Hey,

Could you please add a code sample of your application?? With that, we could provide better support.

In the meantime, you could try to wrap your configuration around a useState, like this

   // Calendar config
    const [calendarConfig] = useState({
        tbar: [
            // ...All your toolbar configuration
        ]
    }); 

return <BryntumCalendar {...calendarConfig} />;

You can check more information about the React integration here https://www.bryntum.com/docs/calendar/guide/Calendar/integration/react/guide#wrappers-overview

About your side note, your license admin should add you to the license.

Best regards,
Márcio


Post by blgarcia »

i'll give it a shot, right now the configs are memo-ized (useMemo).

let me see about striping it down to a code sample i can provide.


Post by blgarcia »

Heres my calendar component. Its intended as configurable widget that a developer can populate a page with (using passed in JSON schema), i took some of the logic out to shorten it.

i updated it to use state, but i still get the same behavior as my first post.

import React, { useEffect, useMemo, useRef, useState } from 'react'
import { BryntumCalendar } from '@bryntum/calendar-react'

import processIncomingEvents from './utils/process-incoming-events'
import processIncomingResources from './utils/process-incoming-resources'
import processTBar from './utils/process-tbar'

import './index.scss'

function CalendarCore( props ) {
	const { schema, uiSchema } = props
	const [ calendarConfig, setCalendarConfig ] = useState( null )
	const calendar = useRef()

const additionalDate = useMemo( () => {
	// use info from schema/uiSchema to prep minDate, maxDate, nonWorkingTime,
	// weekStartDay, hightlightDate, and hideNonWorkingDays
}, [ schema, uiSchema ] )

const date = useMemo( () => {
	// use info from schema to determine date to have calendar focused on
}, [ schema ] )

const features = useMemo( () => {
	// use info from uiSchema to assemble features - drag and eventEdit for now.
}, [ uiSchema ] )

const modeAndModes = useMemo( () => {
	// use uiSchema to set mode, modes, and overlaySidebar
}, [ uiSchema ] )

useEffect( () => {
	setCalendarConfig( {
		...additionalDate,
		date,
		eventStore: {
			data: processIncomingEvents( schema.events, schema ),
			id: "cal_events"
		},
		features,
		...modeAndModes,
		resourceStore: {
			data: processIncomingResources( schema.resources, schema ),
			id: "cal_resources"
		},
		tbar: processTBar( uiSchema ),
	} )
}, [ additionalDate, date, features, modeAndModes, schema, uiSchema ] )

return (
	<BryntumCalendar
		{ ...calendarConfig }
		ref={ calendar }
	/>
)
}

export default CalendarCore

Post by alex.l »

Hi blgarcia,

There is a difference via properties and configs.
configs notation used for initial rendering to create an instance. properties may be changed at runtime.
We have this note in our docs, try to hover question mark on Configs section:
https://bryntum.com/docs/calendar/api/Core/widget/Toolbar#configs
You cannot just replace an instance with json and expect it will be rendered properly at runtime.

Check in docs:
https://bryntum.com/docs/calendar/api/Calendar/view/Calendar#config-tbar config is created to pass config for initial rendering.
https://bryntum.com/docs/calendar/api/Calendar/view/Calendar#property-tbar property is readonly and cannot be replaced at runtime.
To manage tbar at runtime check https://bryntum.com/docs/calendar/api/Core/widget/Toolbar API.
There are
https://bryntum.com/docs/calendar/api/Core/widget/Toolbar#function-removeAll
to clear items and
https://bryntum.com/docs/calendar/api/Core/widget/Toolbar#function-add
https://bryntum.com/docs/calendar/api/Core/widget/Toolbar#function-remove
to manage items. https://bryntum.com/docs/calendar/api/Core/widget/Toolbar#function-add may use a widget instance as well as config, so you can pass your JSON notation object into this method to create a widget.

All the best,
Alex


Post by blgarcia »

then how does this work with react? the handful of code examples provided by your company only show the use of configs.

Also, that is some important information that maybe should not be hidden inside a tooltip.


Post by marcio »

Hey blgarcia,

You can access the toolbar API by using the reference of the Calendar, I'm attaching one component sample of how you can add/remove an item of the toolbar based on some state using the API Alex mentioned.

The effect would be similar to this:

useEffect(() => {
        const calendar = calendarRef.current.instance
        if(fake) {
            calendar.tbar.add(tbarInfo)
        } else {
            // Remove last item (the button you added)
            const indexToBeRemoved = calendar.tbar.items.length - 1;
            const elementToBeRemoved = calendar.tbar.getAt(indexToBeRemoved);
            calendar.tbar.remove(elementToBeRemoved)
        }
    }, [fake]);
Attachments
App.js.zip
(800 Bytes) Downloaded 36 times

Best regards,
Márcio


Post Reply