How to disable list of dates in MUI date picker - javascript

I want to disable MUI date picker future dates (only selected dates not all future dates)
I am getting array of dates from API which needs to be disabled from date picker.
Assume that below blackoutDates are what i am getting from API. So how to disable those dates ?
Below is my code
const getDisabledDates = () => {
let blackoutDates = {[
"2022-03-01",
"2022-03-08"
"2022-04-13",
"2022-05-22"
]}
}
<DatePicker
disablePast
value={checkout.rideDate}
shouldDisableDate={getDisabledDates}
onChange={(newValue) => {
dispatch(setRideDate(newValue?.toISOString().split('T')[0]))
}}
renderInput={(params) => <TextField className={classes.datePickerStyle} {...params}/>}
/>

shouldDisableDate is a function with the current date in param. So you need to compare this with your array, to enable / disable the date
const shouldDisableDate= date => {
let blackoutDates = {[
"2022-03-01",
"2022-03-08"
"2022-04-13",
"2022-05-22"
]}
return blackoutDates.includes(date);
}
This is an exemple, as your date is of type Date whereas your array contains strings. So you'll need to convert the date to a YYYY-MM-DD string first, using your prefered way :)

Handler prop shouldDisableDate passes a date argument to the function you provide. So, your function could look like:
const getDisabledDates = (date) => {
let blackoutDates = [
"2022-03-01",
"2022-03-08"
"2022-04-13",
"2022-05-22"
];
// check `date` object against blackoutDates.
// return true | false
}
Keep in mind that the date parameter is a vanilla Date object.
More info at MUI documentation. In the example, you can see how a function isWeekend is passed to a prop shouldDisableDate. According to date-fns documentation this function accepts the date object. I suggest You play around in the demo that MUI provides.

Related

Array inside useEffect to use in if Statement

I'm trying to use an if statement in my code where I want it to 'open' a Calendar Box if the date of today has occurred as well as for the past days of my calendar to open.
Here is my code where I'm using an useEffect to post it on loading the React Component:
// Call on post method via axios
useEffect(async () => {
console.log(daysData);
const daysDay = daysData.map((day) => day.day);
console.log(daysDay);
if (date + 1 >= daysDay) {
// Url where to post
await axios.post(`http://localhost:5001/open/chocolate`, {
day: date,
});
alert('New day is available to eat!');
}
setOpenCalendarBox('');
}, []);
I'm trying to get an array I've initiated a few lines above of the useEffect function (daysData) and I want the value of the 'day' item inside of the objects inside of the array and then compare the date of today if it is equal to or less than daysDay (day item inside of daysData)
Here is the code for my array:
// Here I initalize the array with useState
const [daysData, setDaysData] = useState([]);
// Here is the port I'm fetching my array from.
useEffect(() => {
fetch('http://localhost:5001/chocolates')
.then((resp) => resp.json())
.then((data) => setDaysData(data));
}, []);
And here is the date code:
// Initiate new Date
const current = new Date();
// Retrieve current day of the month
const date = current.getDate();
I can't seem to get the effect I want. I basically only want to see if the day has passed or if it is today then I want it to post to '/open/chocolate'.
That's probably because the value of daysData is set asynchronously, yet the useEffect block that depends on it does not list it as a dependency. Therefore you are invoking logic, which requires daysData to be populated asynchronously, when the component is loaded at runtime. So daysData will be empty.
A solution is to simply add daysData in the dependency array, so that you will only execute whatever logic that is in there once the array is successfully populated.
On the other hand, you are comparing a number against an array: which will give an unexpected result. If you want any of the day to meet date + 1, use daysDay.some(d => date + 1 >= d). If you want all of the days to meet date + 1, use daysDate.every(d => date + 1 >= d).
useEffect(async () => {
const daysDay = daysData.map((day) => day.day);
// This needs to be fixed, see comment for options
if (daysDay.some(d => date + 1 > d)) {
// Url where to post
await axios.post(`http://localhost:5001/open/chocolate`, {
day: date,
});
}
setOpenCalendarBox('');
}, [daysData]);

Rendering React Components By Date Order

I have to render a series of events occurring based on date connected to a calendar library. I'm using Redux/thunk to bring an index of all event objects to frontend.
I filter the events out based on searchbar value, and the current date selected on calendar as per below.
import moment from 'moment'
function filterEvents (events, searchValue, selectedDay) {
const fixedSearchValue = searchValue.toLowerCase()
const fixedSelectedDate = moment(calendarDateFormatter(selectedDay))
return events.filter(event => {
let eventTitle, eventDate, fixedEventDate, displayEventDate
eventTitle = event.title.toLowerCase()
eventDate = event.start_date
fixedEventDate = moment(eventDate)
displayEventDate = fixedEventDate.format("dddd, MMMM D")
if ((searchValue === "" || eventTitle.includes(fixedSearchValue))
&& fixedEventDate.isAfter(fixedSelectedDate)) {
event["fixedDate"] = fixedEventDate
event["displayDate"] = displayEventDate
return true
} else {
return false
}
})
}
function calendarDateFormatter(selectedDay) {
return selectedDay.year + "-" + selectedDay.month + "-" + selectedDay.day
}
I then sort the resulting events in date order using the following:
function sortEventsByDate (filteredEvents) {
return filteredEvents.sort((event1, event2) => (
dateComparer(event1, event2))
)
}
function dateComparer (event1, event2) {
let eventOneDate, eventTwoDate
eventOneDate = event1.fixedDate
eventTwoDate = event2.fixedDate
return eventOneDate.isAfter(eventTwoDate) ? 1 : -1
}
I now have an array of event items that are sorted based on date/time. Then I tried to extract all unique dates for the current events (in date order), render the date as a parent component that'll list its corresponding events (as child components) that matches the date in time order. Then it'll be the next date with its corresponding events, and so on.
How can I go about this in a clean / scalable / time complexity efficient way? I've tried to create a function that will create an object, iterate through the array of sorted events, use its date as string as keys, and an array of events that match the date key as values, and use this as props to the date parent component. However, the object keys does not save in the same order they were iterated through in the array. This results in unordered date/corresponding events. Please advise!
You can use a combination of Array.filter and Array.map
const getFilteredRenderedNodes = (list) => list
.filter(item => item.date === someDate)
.map(item => (
<div key={item.id}>{item.date}</div>
));
Using Array.filter iterates the array and finds matching items by the criteriaitem.date === someDate. This is a replaceable criteria, but it's what you use to select a subset of items from the list.
Using Array.map returns an array of React.ReactNode, or jsx, which React interprets and renders. The render method includes a key field which must be unique so that React knows which node to update and render and handle events.
You then consume with:
return (
<SomeComponent>
{getFilteredRenderedNodes(myItemList)}
</SomeComponent>
);
Where myItemList is your list of items.

How to update the state of a field programmatically using redux-form

I currently have 2 inputs which look like this:
I'm trying to update the end date input based on the first date input. Example if I input 08/15/2018 inside start date input I expect end date input to equal 08/15/2018.
My current code looks like this for end date input:
<Field
component="input"
format={(value, name) => {
if (startDate.length && name === "start_date") {
return startDate;
}
return value;
}}
name="end_date"
onChange={onDateChange}
type="date"
/>
The variable startDate captures the input from start date input
The current code is able to display the date under end date input, however, it is not updating the redux field - it remains undefined.
How can I display the data and also save it in redux form?
import { getFormValues, change } from 'redux-form';
Fetch value of field first
const mapStateToProps = state => ({
formValues: getFormValues('<formname>')(state) || {},
});
Access that field inside above object received. formValues.
You can use change to change value in store.
change(field:String, value:any)
export const mapDispatchToProps = dispatch => ({
setDate: value => dispatch(change('<formName>', value, null)),
});

date and time concatenate the values in react Js

how to concatenate the date and time value in react js. for date and time picking i am using material UI datepicker and timepicker for selecting the date and time this my example code.
selectDate(event, date) {
this.setState({
updatedDate: moment(date).format('DD-MM-YYYY'),
});
}
selectTime(event, time) {
this.setState({
startime: moment(time).format('HH:mm')
});
}
i want to convert to YYYY-MM-DDThh:mm:ss this format
If it really has to remain a datetime string in state at all times then something along these lines should work (ie taking the previous set state string, converting to a moment object, modifying the relevant parts only, then applying back to state as a string again)
format = 'YYYY-MM-DDThh:mm:ss'
selectDate = (event, date) => this.setState( d => prevState => ({
datetimeStr: (moment(prevState.datetimeStr, this.format) || d)
.year(d.year()).month(d.month()).date(d.date())
.format(this.format)
})(moment(date)))
selectTime = (event, time) => this.setState( d => prevState => ({
datetimeStr: (moment(prevState.datetimeStr, this.format) || d)
.hour(d.hour()).minutes(d.minutes())
.format(this.format)
})(moment(time)))
But would be far more flexible if they are both stored in state as actual Date objects and only combined/formatted when needed as a string in some output, that way if need to be formatted differently in different places you can still derive it from the same state
selectDate = (event, date) => this.setState({date})
selectTime = (event, time) => this.setState({time})
getSelectedDatetimeStr = () => {
const date = moment(this.state.date || {})
const time = moment(this.state.time || {})
return moment({
year: date.year(),
month: date.month(),
day: date.date(),
hours: time.hours(),
minute: time.minutes()
}).format('YYYY-MM-DDThh:mm:ss')
}

Sort by date in React data grid

Is there a sort by date in the React data grid? If so, how can this be called? In the examples, all sorting works only on the line:
Example 1
Example 2
In example 2, there are columns with dates, but they are sorted as strings.
i have a solution that is really good but not great. really good in that it sorts perfectly but it isn't good if you also want to filter on the column as well.
Basically you are displaying the formated date with a custom formatter and the value you are passing to sort on is the the number of seconds from 1/1/1970 for each date so it will sort right.
And yes, i use functions instead of components for the formatter and headerRenderer values all the time and it works fine.
i work an an intranet so i can't just copy/paste my code so this is just hand typed but hopefully you get the idea.
class GridUtil {
static basicTextCell = (props)=>{
return (<span>{props.value? props.value : ""}</span>)
}
}
class AGridWrapper extends React.Component {
///////////////
constructor(props){
super(props);
this.state={...}
this.columnHeaderData = [
{
key: "dateCompleted",
name: "Date Completed",
formatter: (data)=>GridUtil.basicTextCell({value: data.dependentValues.dateCompletedFormatted}),
getRowMetaData: (data)=>(data),
sortable: true
}
];
}//end constructor
///////////////////////////////////
//Note that DateUtil.getDisplayableDate() is our own class to format to MM/DD/YYYY
formatGridData = !props.inData? "Loading..." : props.inData.map(function(obj,index){
return {
dateCompleted: rowData.compDate? new Date(rowData.compDate).getTime() : "";
dateCompletedFormatted: rowData.compDate? DateUtil.getDisplayableDate(rowData.compDate) : "";
}
});
//////////
rowGetter = rowNumber=>formatGridData[rowNumber];
/////////
render(){
return (
<ReactDataGrid
columns={this.columnHeaderData}
rowGetter={this.rowGetter}
rowsCount={this.formatGridData.length}
...
/>
}
I use react-table I was having the same issue, the solution in case, was to convert the date to a javaScript Date, and also return this as a JSon format, I have to format how the date render in the component. here is a link that shows how I did this.
codesandbox sample

Categories

Resources