Our pure JavaScript Scheduler component


Post by ran »

Hi bryntum Team!
im working with React + Redux.
im having the following flow:
*loading data from server=>
*passing it to scheduler via props=>
*data is displayed well=>
*on changing/deleting events im calling an jsx action, calling server for validation for instanse=>
*getting the updated data from the server and updating the state on the reducer(let say different events times) =>
*Render method of the scheduler component is called **with the new data on the props**
*display of the old events stays.

should i call a refresh method or somthing?
thank you!

Post by mats »

should i call a refresh method or somthing?
No calling refresh manually should never be needed. Please share the code you use populate the new data and we'll inspect it.

Post by ran »

sure.. one important thing, i have noticed it happens when im draging an event and then
retriving the new data.
meaning, calling the api without changing events by the ui does work, playing on the ui and then calling the api doesnt

scheduler component:


export default class Scheduler extends pComponent {

constructor(props) {
super(props);

this.state = {

features: {
dependencies: true,
dependencyEdit: false,
eventDragCreate: false,
eventDrag: true,
eventResize: false,
headerZoom: true,

contextMenu: {
processCellItems: () => false,
},

scheduleContextMenu: {
items: {
addEvent: false,
}
},
};
}


render() {

return (<div>
<BryntumScheduler
ref={'scheduler'}
events={this.props.data.events}
resources={this.props.data.resources}
features={this.state.features}
dependencies={this.props.data.dependencies}
columns={[
{text: '', field: 'name', width: 160, disabled: true}
]}
startDate={new Date(2020, 2, 1)}
endDate={new Date(2020, 2, 7)}
/>
</div>
)
}
};



actions: hard coded updating an event and dispatch the changes

api.updateData= function(dispatch, getState) {
return function() {
return schedulerService.fetchSchdulerData()
.then((response) => {

response.data.events[0].startDate = new Date(2020, 2, 4, 10)
response.data.events[0].endDate = new Date(2020, 2, 4, 11)
dispatch(actions.fetchSchedulerDataFinished(data));
});
}
};

return the updated state. which cause re-render with the updated data.
reducer:

export default function(state = Map(defaultState), action) {
switch(action.type){
case schedulerActionTypes.FETCH_DATA_FINISHED:
state = state.set('schedulerData', action.payload);
return state;

default:
return state;
}
}

Post by mats »

Please always use CODE tags when posting code, or it becomes unreadable.

Post by ran »

oh, sorry about that.
any suggestions what may render the the data correctly?
scheduler component:
export default class Scheduler extends pComponent {

constructor(props) {
super(props);

this.state = {

features: {
dependencies: true,
dependencyEdit: false,
eventDragCreate: false,
eventDrag: true,
eventResize: false,
headerZoom: true,

contextMenu: {
processCellItems: () => false,
},

scheduleContextMenu: {
items: {
addEvent: false,
}
},
};
}


render() {

return (<div>
<BryntumScheduler
ref={'scheduler'}
events={this.props.data.events}
resources={this.props.data.resources}
features={this.state.features}
dependencies={this.props.data.dependencies}
columns={[
{text: '', field: 'name', width: 160, disabled: true}
]}
startDate={new Date(2020, 2, 1)}
endDate={new Date(2020, 2, 7)}
/>
</div>
)
}
};
actions: hard coded updating an event and dispatch the changes
api.updateData= function(dispatch, getState) {
return function() {
return schedulerService.fetchSchdulerData()
.then((response) => {

response.data.events[0].startDate = new Date(2020, 2, 4, 10)
response.data.events[0].endDate = new Date(2020, 2, 4, 11)
dispatch(actions.fetchSchedulerDataFinished(data));
});
}
};
return the updated state. which cause re-render with the updated data.
reducer:
export default function(state = Map(defaultState), action) {
switch(action.type){
case schedulerActionTypes.FETCH_DATA_FINISHED:
state = state.set('schedulerData', action.payload);
return state;

default:
return state;
}
}

Post by saki »

From the code you have posted, it is not clear to me how the updated data finds its way to the Scheduler.
  1. Scheduler property events (resources and dependencies too) are bound to the respective keys in data object of props.
    <BryntumScheduler
        ref={'scheduler'}
        events={this.props.data.events}
        resources={this.props.data.resources}
        dependencies={this.props.data.dependencies}
    />
    
  2. reducer sets 'schedulerData' of state
    state = state.set('schedulerData', action.payload);
    
Now, does events, resources, dependencies objects change with the reducer setting the new schedulerData?

Note: changing the items inside of the events (resources, dependencies) is not enough for the change to be sensed by React. It is necessary to change the object itself. Therefore we have updateState method in our demo:
const updateState = function(state, item) {
    return { ...state, ...item };
}; // eo function updateState

Post by ran »

hi Saki,
your right. there is another wrapper which pass the 'data' on the props.:
the container gets the 'schedulerData' pass it as sData to the wrapper.
container:
let SchedulerPageContainer = connect(
  (state) => {
    return {
      sData: state.get('schedulerData'),
    };
  },
  mapDispatchToProps
)(SchedulerPage);
wrapper:
  render() {
  
    return (
      <div className="scheduler-page">
   <Scheduler getScheduler={this.getScheduler} data={this.props.sData.get('schedulerData')} onEventChange=		{this.props.actions.schedulerGanttActions.OnEventChange}></Scheduler>
          
      </div>
    );
    
regarding the note you have mentioned, i have also tried to do deepCopy to the events on the actions and sent it to the component.
i would like to check the updateState you have mentioned. can you send me a link for that demo please?

Post by saki »

It's React advanced demo in examples/react/javascript/advanced/ and the file itself is in src/redux/reducers/reducer.js.

Generally, the only thing needed would be to assign new events (resources, dependencies) to the Scheduler props and it should work without the necessity of calling any refresh or another UI related method.

You may also want to set syncDataOnLoad = true, however, this option only optimizes the data update so that the less DOM updates are necessary.

If everything else fails, post please a runnable showcase, we'll take a look.

Post by ran »

Generally, the only thing needed would be to assign new events (resources, dependencies)
they are all returns from the server on the actions, im just updating the first event to see if its behave as expected.
also, as iv mentioned, it does work at the first time, meaning - after a second change, such as dragging the first event, and calling the same api,
which modify the first event and return it back to the component, i expected the dragged event to return to the hard coded value, instead it stays on the place it was dragged to.
(i hope its clear)
ill take alook at the demo.
thank you

Post by saki »

Well, generally it works. Navigate to https://bryntum.com/examples/scheduler/react/javascript/simple/build/index.html and then type in the browser console:
bryntum.query(i => i.$name === 'Scheduler').events = [{resourceId:'a',name:'New Meeting 1',startDate:'2017-02-07 11:00',endDate:'2017-02-07 14:00'}]
You can vary the various fields above and repeat the assignment. As you can see the event is always updated.

Post Reply