When I click on a day, I need to select a day modifying state and markedDates. The state is modified but the day is not highlighted on the calendar.
The pressed day is highlighted
The pressed day is NOT highlighted
[email protected]
[email protected]
<Calendar
theme={{
backgroundColor: '#ffffff',
calendarBackground: '#ffffff',
textSectionTitleColor: '#b6c1cd',
selectedDayBackgroundColor: '#00adf5',
selectedDayTextColor: '#ffffff',
todayTextColor: '#00adf5',
dayTextColor: '#2d4150',
textDisabledColor: '#d9e1e8',
dotColor: '#00adf5',
selectedDotColor: '#ffffff',
//arrowColor: 'orange',
//monthTextColor: 'blue',
//textDayFontFamily: 'monospace',
//textMonthFontFamily: 'monospace',
//textDayHeaderFontFamily: 'monospace',
textMonthFontWeight: 'bold',
textDayFontSize: 16,
textMonthFontSize: 16,
textDayHeaderFontSize: 16
}}
current = {(this.state.selected_date) || this.state.min_date}
minDate={this.state.min_date}
maxDate={this.state.max_date}
onDayPress={(day) => this.onChangeDate(day)}
markedDates={this.state.markedDates}
monthFormat={'MMMM yyyy'}
onMonthChange={(month) => {log('month changed', month)}}
hideExtraDays={true}
firstDay={1}
/>
This is the onChangeDate function:
onChangeDate(day) {
dateSearched = this._searchDay(day);
var newMarkedDates = this.state.markedDates;
Object.keys(newMarkedDates).forEach(function(key) {
delete newMarkedDates[key].selected;
});
newMarkedDates[dateSearched.selected_date.format("YYYY-MM-DD"].selected = true;
this.setState(prevState => ({
selected_date: day,
markedDates: newMarkedDates
}));
}
If I log "newMarkedDates", I get the correct object with the pressed day with "selected=true" property, but still the Calendar does not highlight the day.
same problem
I don't know if is the best solution but works for me.
<CalendarList
{...}
markedDates={{
...this.state.markedDates,
[this.state.selected_date]: {
selected: true,
disableTouchEvent: true,
}
}}
/>
someone buy this guy a beer @ismavg55, why this is not documented?
Simples solution:
On your calendar add
onDayPress={(day) => this.setMarkedDates(day.dateString)}
markedDates={this.state.markedDates}
then new method in component
setMarkedDates(key) {
let markedDates = {};
if (typeof this.state.markedDates[key] !== 'undefined') {
markedDates = {[key]: {selected: !this.state.markedDates[key].selected}};
} else {
markedDates = {[key]: {selected: true}};
}
this.setState((prevState) => {
return {...prevState, markedDates};
})
}
Its a little workaround but it works as expected. In setMarkedDates you can save last clicked day
@kamwoz: Your solution doesnt support multi-dot
this.state = {
markedDates: {
'2018-10-25': {dots: [vacation, massage, workout], selected: true, selectedColor: 'red'},
'2018-10-26': {dots: [massage, workout], disabled: true},
}
}
Instead can try my solution which supports multi-dot
onDayPress={({ dateString }) => {
const dateObj = _.cloneDeep(this.state.date);
Object.entries(dateObj).forEach(x => x[1].selected = false);
const obj = Object.entries(dateObj).find(x => x[0] === dateString) || [dateString, { }];
obj[1].selected = true;
this.setState({ date: { ...dateObj, [obj[0]]: { ...obj[1] } }});
}}
Just thought will add a piece of additional info that might help in some situations. When I tried to update markedDates when scrolling I found that days in the months other than prev, current, next were not rendered. ie the months were blank. ("react-native-calendars": "^1.21.0")
Calling this.setState directly in the onVisibleMonthsChange callback did not work.
Had to be offloaded in setImmediate or setTimeout
state = {
markedDates: {}
}
updateMarked = (months) => {
//console.log('now these months are visible', months);
let marked = {};
months.map(month => {
marked[month.dateString] = {selected: true, color: 'green', textColor: 'white'}
})
console.log(marked);
//setTimeout(this.setState.bind(this, {markedDates: marked}), 200);
setImmediate(this.setState.bind(this, {markedDates: marked}));
// +++ WORKS +++
// 1. setTimeout(this.setState.bind(this, {markedDates: marked}), 200);
// 2. setTimeout(()=> {
// this.setState({markedDates: marked});
// }, 200);
// 3. setImmediate(this.setState.bind(this, {markedDates: marked}));
// --- DOES NOT WORK ---
// 1. this.setState({markedDates: marked})
// 2. setTimeout(this.setState, 500, {markedDates: marked});
}
render = () => {
return (
<View>
<CalendarList
// Callback which gets executed when visible months change in scroll view.
onVisibleMonthsChange={this.updateMarked}
// Max amount of months allowed to scroll to the past. Default = 50
pastScrollRange={12}
// Max amount of months allowed to scroll to the future. Default = 50
futureScrollRange={12}
// Enable or disable scrolling of calendar list
scrollEnabled={true}
// Enable or disable vertical scroll indicator. Default = false
showScrollIndicator={true}
markedDates={this.state.markedDates}
markingType={'period'}
/>
</View>
);
}
I don't know if is the best solution but works for me.
<CalendarList {...} markedDates={{ ...this.state.markedDates, [this.state.selected_date]: { selected: true, disableTouchEvent: true, } }} />
But the dot in day don't show.
Do you still have a problem?
Bellow code help if you have marked the date with multi dots or use custom market.
<Calendar
onDayPress={onDayPress}
markedDates={{
...markedDates,
[selected]: {
selected: true,
disableTouchEvent: true,
...markedDates.hasOwnProperty(selected) ? markedDates[selected] : {},
}
}}
/>
const onDayPress = day => {
setSelected(day.dateString);
};
Most helpful comment
I don't know if is the best solution but works for me.
<CalendarList {...} markedDates={{ ...this.state.markedDates, [this.state.selected_date]: { selected: true, disableTouchEvent: true, } }} />