Results:
Loading...

React Data GridDate Component

You can create your own date components, and AG Grid will use them every time it needs to ask the user for a date value. The date components are currently used in date filters.

Simple Date Component

Below is a simple example of filter component as a Hook:

export default forwardRef((props, ref) => {
   const [date, setDate] = useState(null);
   const [picker, setPicker] = useState(null);
   const refFlatPickr = useRef();
   const refInput = useRef();

   // we use a ref as well as state, as state is async,
   // and after the grid calls setDate() (eg when setting filter model)
   // it then can call getDate() immediately (eg to execute the filter)
   // and we need to pass back the most recent value, not the old 'current state'.
   const dateRef = useRef();

   //*********************************************************************************
   //          LINKING THE UI, THE STATE AND AG-GRID
   //*********************************************************************************

   const onDateChanged = (selectedDates) => {
       const newDate = selectedDates[0];
       setDate(newDate);
       dateRef.current = newDate;
       props.onDateChanged();
   };

   useEffect(() => {
       setPicker(flatpickr(refFlatPickr.current, {
           onChange: onDateChanged,
           dateFormat: 'd/m/Y',
           wrap: true
       }));
   }, []);

   useEffect(() => {
       if (picker) {
           picker.calendarContainer.classList.add('ag-custom-component-popup');
       }
   }, [picker]);

   useEffect(() => {
       //Callback after the state is set. This is where we tell ag-grid that the date has changed so
       //it will proceed with the filtering and we can then expect AG Grid to call us back to getDate
       if (picker) {
           picker.setDate(date);
       }
   }, [date, picker]);

   useImperativeHandle(ref, () => ({
       //*********************************************************************************
       //          METHODS REQUIRED BY AG-GRID
       //*********************************************************************************
       getDate() {
           //ag-grid will call us here when in need to check what the current date value is hold by this
           //component.
           return dateRef.current;
       },

       setDate(date) {
           //ag-grid will call us here when it needs this component to update the date that it holds.
           dateRef.current = date;
           setDate(date);
       },

       //*********************************************************************************
       //          AG-GRID OPTIONAL METHODS
       //*********************************************************************************

       setInputPlaceholder(placeholder) {
           if (refInput.current) {
               refInput.current.setAttribute('placeholder', placeholder);
           }
       },

       setInputAriaLabel(label) {
           if (refInput.current) {
               refInput.current.setAttribute('aria-label', label);
           }
       }
   }));

   // inlining styles to make simpler the component
   return (
       <div className="ag-input-wrapper custom-date-filter" role="presentation" ref={refFlatPickr}>
           <input type="text" ref={refInput} data-input style={{ width: "100%" }} />
           <a class='input-button' title='clear' data-clear>
               <i class='fa fa-times'></i>
           </a>
       </div>
   );
});

Note that the grid calls getDate and setDate synchronously. As state is asynchronous, you will also need to use a ref if using state to store the current date value. This is demonstrated in the example above.

Here is the same example as a Class-based Component:

export default class CustomDateComponent extends Component {
   constructor(props) {
       super(props);

       this.state = {
           date: null
       };
   }

   render() {
       //Inlining styles to make simpler the component
       return (
           <div className="ag-input-wrapper custom-date-filter" role="presentation" ref="flatpickr">
               <input type="text" ref="eInput" data-input style={{width: "100%"}}/>
               <a class='input-button' title='clear' data-clear>
                   <i class='fa fa-times'></i>
               </a>
           </div>
       );
   }

   componentDidMount() {
       this.picker = flatpickr(this.refs.flatpickr, {
           onChange: this.onDateChanged.bind(this),
           dateFormat: 'd/m/Y',
           wrap: true
       });

       this.eInput = this.refs.eInput;

       this.picker.calendarContainer.classList.add('ag-custom-component-popup');
   }

   //*********************************************************************************
   //          METHODS REQUIRED BY AG-GRID
   //*********************************************************************************

   getDate() {
       //ag-grid will call us here when in need to check what the current date value is hold by this
       //component.
       return this.state.date;
   }

   setDate(date) {
       //ag-grid will call us here when it needs this component to update the date that it holds.
       this.setState({date});
       this.picker.setDate(date);
   }

   //*********************************************************************************
   //          AG-GRID OPTIONAL METHODS
   //*********************************************************************************

   setInputPlaceholder(placeholder) {
       this.eInput.setAttribute('placeholder', placeholder);
   }

   setInputAriaLabel(label) {
       this.eInput.setAttribute('aria-label', label);
   }

   //*********************************************************************************
   //          LINKS THE INTERNAL STATE AND AG-GRID
   //*********************************************************************************

   updateAndNotifyAgGrid(date) {
       //Callback after the state is set. This is where we tell ag-grid that the date has changed so
       //it will proceed with the filtering and we can then expect AG Grid to call us back to getDate
       this.setState({date}, this.props.onDateChanged);
   }

   //*********************************************************************************
   //          LINKING THE UI, THE STATE AND AG-GRID
   //*********************************************************************************

   onDateChanged = (selectedDates) => {
       this.setState({date: selectedDates[0]});
       this.updateAndNotifyAgGrid(selectedDates[0]);
   };
}

Registering Date Components

By default the grid will use the browser-provided date picker for all Supported Browsers, but for other browsers it will just provide a simple text field. You can use your own date picker in AG Grid by providing a custom Date Component as follows:

<AgGridReact
   components={{ agDateInput: CustomDateComponent }}
   ...other properties...
/>

Please see Provided Components for more information about overriding AG Grid provided components (as we're doing here by overriding agDateInput).

Example: Custom Date Component

The example below shows how to register a custom date component that contains an extra floating calendar picker rendered from the filter field. The problem with this approach is that we have no control over third party components and therefore no way to implement a preventDefault when the user clicks on the Calendar Picker (for more info see Custom Floating Filter Example). Our way of fixing this problem is to add the ag-custom-component-popup class to the floating calendar.

Custom Date Interface

The interface for a custom date component is as follows:


interface IDateReactComp {
  // Returns the current date represented by this component 
  getDate(): Date | null;

  // Sets the date represented by this component 
  setDate(date: Date | null): void;

  // Optional: Sets the disabled state of this component 
  setDisabled?(disabled: boolean): void;

  // Optional: Sets the current input placeholder 
  setInputPlaceholder?(placeholder: string): void;

  // Optional: Sets the current input aria label 
  setInputAriaLabel?(placeholder: string): void;

  // Optional: A hook to perform any necessary operation just after the GUI for this component has been rendered on the screen.
  // If a parent popup is closed and reopened (e.g. for filters), this method is called each time the component is shown.
  // This is useful for any logic that requires attachment before executing, such as putting focus on a particular DOM element.
  afterGuiAttached?(params?: IAfterGuiAttachedParams): void;

  getReactContainerStyle?: () => {};

  getReactContainerClasses?: () => string[];

}

Note that if you're using Hooks for Grid Components that have lifecycle/callbacks that the grid will call (for example, the getDate callback from an Date Component), then you'll need to expose them with forwardRef & useImperativeHandle.

Please refer to the Hook documentation (or the examples on this page) for more information.

Custom Date Parameters

When a React component is instantiated the grid will make the grid APIs, a number of utility methods as well as the cell & row values available to you via props - the interface for what is provided is documented below.

Properties available on the IDateParams<TData = any, TContext = any> interface.

onDateChanged
Function
Method for component to tell AG Grid that the date has changed.
onDateChanged = () => void;
filterParams
DateFilterParams
DateFilterParams
filterParams: DateFilterParams;

type DateFilterParams = 
      IDateFilterParams & IFilterParams<TData>


interface IDateFilterParams {
  // Required if the data for the column are not native JS `Date` objects. 
  comparator?: IDateComparatorFunc;
  // Defines whether the grid uses the browser date picker or a plain text box.
  //  - `true`: Force the browser date picker to be used.
  //  - `false`: Force a plain text box to be used.
  //
  // Default: `undefined` - If a date component is not provided, then the grid will use the browser date picker
  // for all supported browsers and a plain text box for other browsers.
  browserDatePicker?: boolean;
  // This is the minimum year that may be entered in a date field for the value to be considered valid. Default: `1000` 
  minValidYear?: number;
  // This is the maximum year that may be entered in a date field for the value to be considered valid. Default is no restriction. 
  maxValidYear?: number;
  // Defines the date format for the floating filter text when an in range filter has been applied.
  //
  // Default: `YYYY-MM-DD`
  inRangeFloatingFilterDateFormat?: string;
  // If `true`, the `'inRange'` filter option will include values equal to the start and end of the range. 
  inRangeInclusive?: boolean;
  // If `true`, blank (`null` or `undefined`) values will pass the `'equals'` filter option. 
  includeBlanksInEquals?: boolean;
  // If `true`, blank (`null` or `undefined`) values will pass the `'lessThan'` and `'lessThanOrEqual'` filter options. 
  includeBlanksInLessThan?: boolean;
  // If `true`, blank (`null` or `undefined`) values will pass the `'greaterThan'` and `'greaterThanOrEqual'` filter options. 
  includeBlanksInGreaterThan?: boolean;
  // If `true`, blank (`null` or `undefined`) values will pass the `'inRange'` filter option. 
  includeBlanksInRange?: boolean;
  // Array of filter options to present to the user.
  filterOptions?: (IFilterOptionDef | ISimpleFilterModelType)[];
  // The default filter option to be selected. 
  defaultOption?: string;
  // By default, the two conditions are combined using `AND`.
  // You can change this default by setting this property.
  // Options: `AND`, `OR`
  defaultJoinOperator?: JoinOperator;
  // Maximum number of conditions allowed in the filter.
  // Default: `2`
  maxNumConditions?: number;
  // By default only one condition is shown, and additional conditions are made visible when the previous conditions are entered
  // (up to `maxNumConditions`). To have more conditions shown by default, set this to the number required.
  // Conditions will be disabled until the previous conditions have been entered.
  // Note that this cannot be greater than `maxNumConditions` - anything larger will be ignored. 
  // Default: `1`
  numAlwaysVisibleConditions?: number;
  // Placeholder text for the filter textbox
  filterPlaceholder?: FilterPlaceholderFunction | string;
  // Specifies the buttons to be shown in the filter, in the order they should be displayed in.
  // The options are:
  //
  //  - `'apply'`: If the Apply button is present, the filter is only applied after the user hits the Apply button.
  //  - `'clear'`: The Clear button will clear the (form) details of the filter without removing any active filters on the column.
  //  - `'reset'`: The Reset button will clear the details of the filter and any active filters on that column.
  //  - `'cancel'`: The Cancel button will discard any changes that have been made to the filter in the UI, restoring the applied model.
  buttons?: FilterButtonType[];
  // If the Apply button is present, the filter popup will be closed immediately when the Apply
  // or Reset button is clicked if this is set to `true`.
  //
  // Default: `false`
  closeOnApply?: boolean;
  // Overrides the default debounce time in milliseconds for the filter. Defaults are:
  // - `TextFilter` and `NumberFilter`: 500ms. (These filters have text field inputs, so a short delay before the input is formatted and the filtering applied is usually appropriate).
  // - `DateFilter` and `SetFilter`: 0ms
  debounceMs?: number;
  // If set to `true`, disables controls in the filter to mutate its state. Normally this would
  // be used in conjunction with the Filter API.
  //
  // Default: `false`
  readOnly?: boolean;
}

type FilterPlaceholderFunction = 
      (params: IFilterPlaceholderFunctionParams) => string


interface IFilterPlaceholderFunctionParams {
  // The filter option key
  filterOptionKey: ISimpleFilterModelType;
  // The filter option name as localised text
  filterOption: string;
  // The default placeholder text
  placeholder: string;
}

interface IFilterParams<TData = any, TContext = any> {
  // The column this filter is for. 
  column: Column;
  // The column definition for the column. 
  colDef: ColDef<TData>;
  // The row model, helpful for looking up data values if needed.
  // If the filter needs to know which rows are
  // a) in the table,
  // b) currently visible (i.e. not already filtered),
  // c) which groups,
  // d) what order - all of this can be read from the rowModel.
  rowModel: IRowModel;
  // A function callback to be called when the filter changes. The
  // grid will then respond by filtering the grid data. The callback
  // takes one optional parameter which, if included, will get merged
  // to the FilterChangedEvent object (useful for passing additional
  // information to anyone listening to this event, however such extra
  // attributes are not used by the grid).
  filterChangedCallback: (additionalEventAttributes?: any) => void;
  // A function callback, to be optionally called, when the filter UI changes.
  // The grid will respond with emitting a FilterModifiedEvent.
  // Apart from emitting the event, the grid takes no further action.
  filterModifiedCallback: () => void;
  // A function callback for the filter to get cell values from provided row data. Called with a
  // `ValueGetterParams` to get the value for this filter's column for the provided row data.
  //
  // The callback takes care of selecting the right column definition and deciding whether to use
  // the column `valueGetter` or raw field etc.
  valueGetter: ValueGetterFunc<TData>;
  // A function callback, call with a node to be told whether the node passes all filters except the current filter.
  // This is useful if you want to only present to the user values that this filter can filter given the status of the other filters.
  // The set filter uses this to remove from the list,
  // items that are no longer available due to the state of other filters (like Excel type filtering).
  doesRowPassOtherFilter: (rowNode: IRowNode<TData>) => boolean;
  // The grid api. 
  api: GridApi<TData>;
  // The column api. 
  columnApi: ColumnApi;
  // Application context as set on `gridOptions.context`. 
  context: TContext;
}
api
The grid api.
columnApi
The column api.
context
TContext
Application context as set on gridOptions.context.