I am using fullcalender library to make a big calendar for my project, in their documentation as far as I see, I can only add events by clicking on the empty dates in calendar. But I am trying to add a button outside of a calendar which will show a popup when clicked and user can add an calendar event. I can just create a button outside of calender and call a function like
function handleAddEvent () {
// how do I get selectionInfo here ?
}
<>
<button onClick={handleAddEvent}>Add an event to calender</button>
<FullCalendar
plugins={[
dayGridPlugin,
timeGridPlugin,
interactionPlugin,
listPlugin,
]}
...
/>
</>
but I can't find a way to get the selectionInfo ( is a plain object with the following properties) as it comes from <FullCalendar> and it is necessary to add an event to a calendar. Are there any workarounds for this ? Thanks in advance.
You can see my code sample here
UPDATE
I used customButtons to create an external button to get necessary information from user and add an event along with useRef as calendarRef.current.getApi() to use addEvent to create an event. My codes will be
<FullCalendar
plugins={[
dayGridPlugin,
timeGridPlugin,
interactionPlugin,
listPlugin,
]}
ref={calendarRef}
headerToolbar={{
left: "prev,next today customAddEventBtn",
center: "title",
right: "dayGridMonth,timeGridWeek,timeGridDay,listWeek",
}}
initialView="dayGridMonth"
customButtons={{
customAddEventBtn: {
text: "Add an event",
click: handleCustomAddEventBtn,
},
}}
/>
function handleCustomAddEventBtn() {
let calendarApi = calendarRef.current.getApi();
if (title) {
calendarApi.unselect(); // clear date selection
calendarApi.addEvent({
id: uuidv4(),
title,
start: selectedFromDate, // state to get date form user
end: selectedToDate, // state to get date form user
allDay: true,
});
}
}
Related
I am using Fluent UI DetailsList. My table looks like below:
I need filters below every column (text or drop-down) as shown below:
Please let me know if this is possible? Or maybe a way to display custom header (using html) ?
This actually turned out to be easier than I thought it'd be...
If you're ok with clicking the column header to reveal the choices (vs having the dropdown directly under the title) then this can be achieved using the ContextualMenu component in conjunction with DetailsList. I got it working by tweaking from the variable row height example in the official docs: https://developer.microsoft.com/en-us/fluentui#/controls/web/detailslist/variablerowheights.
Add a ContextualMenu underneath your DetailsList:
<DetailsList
items={items}
columns={columns}
/>
{this.state.contextualMenuProps && <ContextualMenu {...this.state.contextualMenuProps} />}
Inside your column definition, set the hasDropdown action so the user gets a UI indicator that they can/should click the header, and call a contextMenu method (note I'm using onColumnContextMenu as well as onColumnClick so it doesn't matter if they left or right click the header:
{
key: 'dept',
name: 'Department',
fieldName: 'dept',
minWidth: 125,
maxWidth: 200,
onColumnContextMenu: (column, ev) => {
this.onColumnContextMenu(column, ev);
},
onColumnClick: (ev, column) => {
this.onColumnContextMenu(column, ev);
},
columnActionsMode: ColumnActionsMode.hasDropdown,
}
When the onColumnContextMenu method gets invoked, we need to build the context menu properties that will get consumed by the ContextualMenu component. Note the dismissal method as well, which clears out the state so the menu is hidden.
private onContextualMenuDismissed = (): void => {
this.setState({
contextualMenuProps: undefined,
});
}
private onColumnContextMenu = (column: IColumn, ev: React.MouseEvent<HTMLElement>): void => {
if (column.columnActionsMode !== ColumnActionsMode.disabled) {
this.setState({
contextualMenuProps: this.getContextualMenuProps(ev, column),
});
}
};
Finally, inside of getContextualMenuProps you need to determine what the options should be for the user to click. In this example, I'm simply giving sort options (you'll need to add an onClick handler to actually do something when the user clicks the item), but I'll use the column to determine what those items should actually be and paint the filters into the items collection so the user can select one to filter.
private getContextualMenuProps = (ev: React.MouseEvent<HTMLElement>, column: IColumn): IContextualMenuProps => {
const items: IContextualMenuItem[] = [
{
key: 'aToZ',
name: 'A to Z',
iconProps: { iconName: 'SortUp' },
canCheck: true,
checked: column.isSorted && !column.isSortedDescending,
},
{
key: 'zToA',
name: 'Z to A',
iconProps: { iconName: 'SortDown' },
canCheck: true,
checked: column.isSorted && column.isSortedDescending,
}
];
return {
items: items,
target: ev.currentTarget as HTMLElement,
directionalHint: DirectionalHint.bottomLeftEdge,
gapSpace: 10,
isBeakVisible: true,
onDismiss: this.onContextualMenuDismissed,
}
}
Note the target on the ContextualMenuProps object, which is what tells the ContextualMenu where to lock itself onto (in this case, the column header that you clicked to instantiate the menu.
Detail list filter for each column without context menu -
https://codesandbox.io/s/rajesh-patil74-jzuiy?file=/src/DetailsList.CustomColumns.Example.tsx
For instance - Providing filter in text field associated with each column will apply filter on color column.
I am trying to customize Input Text field of react-bootstrap-table2-filter similar option available at https://react-bootstrap-table.github.io/react-bootstrap-table2/storybook/index.html?selectedKind=Column%20Filter&selectedStory=Programmatically%20Text%20Filter&full=0&addons=1&stories=1&panelRight=0&addonPanel=storybook%2Factions%2Factions-panel
I am trying with below code snippet
let dataFilter;
const handleTextChange = (searchDataText) => {
console.log(searchDataText.target.value);
dataFilter(searchDataText.target.value);
};
// This is static and used to define Table Header properties
const columns = [{
dataField: 'data'
, text: ""
, headerFormatter: (column, colIndex) => (<i className="fa fa-podcast"> Name</i>)
, sort: true
, filter: textFilter({
getFilter: (filter) => {
// dataFilter was assigned once the component has been mounted.
dataFilter = filter;
}
})
, headerStyle: {backgroundColor: '#6495ed'}
, headerAlign: 'center'
, align: 'center'
}]
...
...
<Form.Control type="text" placeholder="Search POD" name="search_data_filter"
onChange={handleTextChange}/>
<BootstrapTable keyField='dataKey' data={this.state.tableRows}
columns={columns} bootstrap4={true}
defaultSorted={defaultSorted} striped
hover filter={filterFactory()}
pagination={paginationFactory()}
filter={filterFactory()}
/>
it is almost exact to the given instruction in the above link. But when I execute the code, In console output, I see typed in text is being captured correctly and when it is trying to pass to filter, error occurs ...
dataFilter is not a function
Any help suggestion, alternative approach to implement a custom Text Input as Filter Box outside of Table area?
I am calling the component FullCalendar in my code. For the Calendar I need two plugins to be loaded. The dayGridPlugin and the interactionPlugin. However when I pass them both in the attribute 'plugins', it only loads the first plugin I pass in. I could not find documentation on this specific problem which is why I'm asking here. I'm guessing I made a error in the way I pass them in.
<FullCalendar
defaultView="dayGridMonth"
plugins={[dayGridPlugin, interactionPlugin]}
events={[
{ title: 'event 1', date: '2019-10-01' },
{ title: 'event 2', date: '2019-11-01' }
]}
selectable='true'
/>
The interaction plugin was working but I did not realize that I had to use the dateClick attribute and not the selectable attribute. The dateClick allows you to have a event handler for when for when a date is clicked. It is passed in as the parameter event.
How to get data from SQLite database and pass this data to Picker Component with values and labels?
The question is so general, so I will answer generally. To get data from SQLite you can install this package on your react native project:
https://www.npmjs.com/package/react-native-sqlite-storage
Then you can use this pass your data in item section of this nice component:
https://www.npmjs.com/package/react-native-picker-select
Just follow the instructions for installing and configurations.
To passing the data to the picker it is enough to put your data in the state and convert to to the proper way. To convert you can use following code and put it in the place that you retire the data:
var myMatrix=[];
yourRetriveData.map(function (item, ) {
// console.log ("item [yourRetriveData.map]", item);
obj= {
"label": item.X,
"value": item.Y,
};
myMatrix.push(obj);
});
that.setState({dataForPicker: myMatrix });
Instead of X and Y you can put your proper felids. Then in the picker you need this:
{!this.state.dataForPicker ?
<ActivityIndicator size="small" color="#fff" />:<RNPickerSelect
placeholder={{
label: this.state.label,
value: this.state.value,
}}
items={this.state.data}
onValueChange={(value, index) => {
this._handleItemPicked(value, index)
}}
placeholderTextColor={"#FFF"}
placeholderTextColor={'rgba(255,255,255,1)'}
value={this.props.value}
style={{ ...pickerSelectStyles }}
hideIcon={true}
/>}
I hope I could help.
I am dropping an external object into angular-ui-calendar using angular-dragdrop.
The external object is coming from this list:
<div class="fc-event" data-drag="true"
jqyoui-draggable="{animate:true}"
ng-model="test_object"
ng-repeat="test_object in test_objects">
Draggable - {{ test_object.name }}
</div>
The fullcalendar is set up with:
<div id="ApptsCalendar" calendar="ApptsCalendar"
ui-calendar="calendarOptions.calendar"
ng-model="eventSources" data-drop="true"
jqyoui-droppable="{multiple:true, onDrop: 'drop_function'}"
data-jqyoui-options>
</div>
When dropped, I can process that event using fullcalendar 'drop' method with:
$scope.calendarOptions = {
calendar: {
editable: true,
droppable: true,
drop: function(date,jsEvent,ui,resourceId){
console.log("Dropped from calendarOptions")
console.log(resourceId);
$scope.eventSources[0].push({
id:5,
title: 'dropped event (fake)',
start: date
});
}
}
};
or from the angular-dragdrop 'onDrop' callback to call a 'drop' function:
jqyoui-droppable="{multiple:true, onDrop: 'drop'}"
Both can trigger when I want, but neither seem to have the two pieces I need. I need to have the object value being dropped (defined in ng-model) and the date being dropped into.
Basically, I want to push the event to the the eventSources with:
$scope.eventSources[0].push({
id:5,
title: '...name of object...',
start: '...date of target dropped on...'
});
http://plnkr.co/edit/fj858Htb2FRUg5h1pucP?p=preview
Well, one of the things you wanted is already there. It's date on which the event is dropped. You get it from the first argument of the drop function. It's a moment object (according to the docs) so you might want to use .toDate() in order to get the JS Date object.
The other thing is the value of the event which got dropped. According to the same docs page, the DOM object of the event is accessible using this inside drop function.
Now, this is a bit unconventional way (I don't see many choices here), what you can do is, with the ng-repeat iterating over event objects, you can keep an attribute with value from each object which can later be accessed inside the drop function. For example, see how I added customEventName="{{test_object.name}}" in here:
<div class="fc-event tech_draggable" data-drag="true" id="{{test_object.name}}"
customEventName="{{test_object.name}}" jqyoui-draggable="{animate:true}"
ng-model="test_object" ng-repeat="test_object in test_objects" ...>
Draggable - {{ test_object.name }}
</div>
Then, in the drop function, that can be accessed using this.getAttribute('customEventName') like this:
$scope.calendarOptions = {
calendar: {
editable: true,
droppable: true,
drop: function(momentDate, jsEvent, ui, resourceId) {
console.log(momentDate.toDate()) // gives JS Date object
console.log(this.getAttribute('customEventName')); // gives event2/event3 etc.
//... more
}
}
};
An alternative is to make an attribute with a string representing the scope variable name:
<div ng-repeat="test_object in test_objects">
<div class="fc-event tech_draggable"
data-drag="true"
jqyoui-draggable="{animate:true}"
ng-repeat="test_object in test_objects"
style="margin-bottom:1px;"
data-jqyoui-options="{helper: 'clone'}"
scope-data-name="test_objects[{{$index}}]"
>
Draggable - {{ test_object.name }}
</div>
</div>
And using $scope.$eval to get the actual object:
$scope.calendarOptions = {
calendar: {
editable: true,
droppable: true,
drop: function(date,jsEvent,ui,resourceId){
var scopeDataName = this.getAttribute('scope-data-name');
var data = $scope.$eval(scopeDataName);
$scope.eventSources[1].push({
id: $scope.eventSources[0].length,
title: `${data.name} ${data.description}`,
start: date
});
}
}
};
The DEMO on PLNKR
After some more research, I think fullcalendar has the solution already.
I can use data-event attribute in the element:
data-event='{"title":"{{ test_object.name }}"}'
With that, there is no need to even have a 'drop' function... fullcalendar natively supports drag and drop.
I can then optionally use eventReceive to handle a drop from an external resource and use eventDrop to handle an internal event move.
http://plnkr.co/edit/fj858Htb2FRUg5h1pucP?p=preview