Does ag-grid have a grid event that corresponds to to the "Reset Columns" item that is at the bottom of each column menu?
I need to do some special processing on "Reset Columns", and different handling of column "move", "resize", (etc.). I setup an event handler for the "columnEverythingChanged" event and a different event handler for "columnMoved" (etc.). I found that:
1) When no changes have been made to any column and I press "Reset Columns", "columnEverythingChanged" gets called. Fine.
2) When one or more columns have been changed and I press "Reset Columns", both "columnEverythingChanged" AND "columnMoved" (or other) get called.
My problem: in case (2), my "columnMoved" logic should not run.
A secondary problem: "columnEverythingChanged" also gets called at application startup. Not a big deal, but I had to hack around it.
This was so long ago, I don't remember the details. But in my code, I see that I use the columnMoved, columnResized, columnVisible, filterChanged, and sortChanged events. I run the same function on all of these events. That function debounces the event before doing my special processing.
you can use GlobalListener to work with multiple events without issue
gridOption.api.addGlobalListener(GlobalListenerSaveColumnState);
function GlobalListenerSaveColumnState(type, event) {
if (type == "columnVisible" || type == "columnResized"|| type == "columnMoved"|| type == "columnPinned" || type == "dragStopped") {
UpdateGridDefaultsIntoDb(event);
}
}
I solved this by 'overriding' the default getMainMenuItems function, which basically creates that "hamburger" icon, and reveals the options inside the Main Menu. When overriden, you can supply the list of items you want to include, and you can give it your own function you want to run when "Reset Columns" is clicked.
this.gridOptions = {
viewportDatasource: {
init: this.init,
setViewportRange: this.setViewportRange,
},
rowModelType: 'viewport',
sideBar: localStorage.getItem('test_pivot') == 'true' ? 'columns' : '',
suppressRowClickSelection: false,
suppressMultiSort: true,
rowMultiSelectWithClick: true,
rowSelection: 'multiple',
getMainMenuItems: (params) => this.getMainMenuItems(params), // <- This piece right here
getContextMenuItems: this.getContextMenuItems,
};
Later you define that getMainMenuItems()
getMainMenuItems(params) {
params.defaultItems[params.defaultItems.length - 1] = {
name: this.translate.instant('i18n.reset_columns'),
action: () => {
this.onResetColumnStateClick(null); // <- The custom functionality you want to execute when Reset Columns is clicked
},
};
return params.defaultItems;
}
I believe their documentation has another example containing the getMainMenuItems function
https://ag-grid.com/javascript-data-grid/column-menu/
https://plnkr.co/edit/?open=main.js&preview
Related
I'm trying to build an add-in with similar behaviour like the comment system.
I select a part of text.
Press a button in my add-in. A card is created that links to that text.
I do something else, like write text on a different position.
When I press the card in my add-in, I'd like to jump back to the selected text (in point 1).
I studied the API, documentation. And learned that I could do something like that with Bindings. A contentcontrol might also be an option, although I noticed that you can't connect and eventhandler (it's in beta). I might need an eventhandler to track changes later.
Create binding (step 2)
Office.context.document.bindings.addFromSelectionAsync(Office.BindingType.Text, { id: 'MyBinding' }, (asyncResult) => {
if (asyncResult.status == Office.AsyncResultStatus.Failed) {
console.log('Action failed. Error: ' + asyncResult.error.message);
} else {
console.log('Added new binding with id: ' + asyncResult.value.id);
}
});
Works. Then I click somewhere else in my document, to continue with step 4.
View binding (step 4).
So I click the card and what to jump back to that text binding, with the binding selected.
I figured there are multiple ways.
Method #1
Use the Office.select function below logs the text contents of the binding. However, it doesn't select that text in the document.
Office.select("bindings#MyBinding").getDataAsync(function (asyncResult) {
if (asyncResult.status == Office.AsyncResultStatus.Failed) {
}
else {
console.log(asyncResult.value);
}
});
Method #2
Use the GoToById function to jump to the binding.
Office.context.document.goToByIdAsync("MyBinding", Office.GoToType.Binding, function (asyncResult) {
let val = asyncResult.value;
console.log(val);
});
This shows like a blue like frame around the text that was previously selected and puts the cursor at the start.
I'd prefer that I don't see that frame (no idea if that's possible) and I would like to the text selected.
There is the Office.GoToByIdOptions interface that mentions:
In Word: Office.SelectionMode.Selected selects all content in the binding.
I don't understand how pass that option in the function call though and I can't find an example. Can I use this interface to get the selection?
https://learn.microsoft.com/en-us/javascript/api/office/office.document?view=common-js-preview#office-office-document-gotobyidasync-member(1)
goToByIdAsync(id, goToType, options, callback)
If there are other ways to do this, I'd like to know that as well.
With some help I could figure it out. I learned that an Interface is just an object.
So in this case:
const options = {
selectionMode: Office.SelectionMode.Selected
};
Office.context.document.goToByIdAsync("MyBinding", Office.GoToType.Binding, options, function (asyncResult) {
console.log(asyncResult);
});
This gives the selected result.
Sure someone can provide a better answer than this, as it's unfamiliar territory for me, but...
When you create a Binding from the Selection in Word, you're going to get a Content Control anyway. So to avoid having something that looks like a content control with the blue box, you either have to modify the control's display or you have to find some other way to reference a region of your document. In the traditional Word Object model, you could use a bookmark, for example. But the office-js APIs do not seem very interested in them.
However, when you create a Binding, which is an Office object, you don't get immediate access to the Content Control's properties (since that's a Word object). So instead of creating the Binding then trying to modify the Content Control, you may be better off creating the Content Control then Binding to it.
Something like this:
async function markTarget() {
Word.run(async (context) => {
const cc = context.document.getSelection().insertContentControl();
// "Hidden" means you don't get the "Bounding Box"
// (blue box with Title), or the Start/End tag view
cc.appearance = "Hidden";
// Provide a Title so we have a Name to bind to
cc.title = "myCC";
// If you don't want users changing the content, you
// could uncomment the following line
//cc.cannotDelete = true;
return context.sync()
.then(
() => {
console.log("Content control inserted");
// Now create a binding using the named item
Office.context.document.bindings.addFromNamedItemAsync("myCC",
Office.BindingType.Text,
{ id: 'MyBinding' });
},
() => console.log("Content control insertion failed")
).then(
() => console.log("Added new binding"),
() => console.log("Binding creation failed")
)
});
}
So why not just create the ContentControl, name it, and then you should be able to select it later using its Title, right? Well, getting the "data" from a control is one thing. Actually selecting it doesn't seem straightforward in the API, whereas Selecting a Binding seems to be.
So this code is pretty similar to your approach, but adds the parameter to select the whole text. The syntax for that is really the same syntax as { id: 'MyBinding' } in the code you already have.
function selectTarget() {
Office.context.document.goToByIdAsync(
"MyBinding",
Office.GoToType.Binding,
{ selectionMode: Office.SelectionMode.Selected },
function(asyncResult) {
let val = asyncResult.value;
console.log(val);
}
);
}
Both the Binding and the ContentControl (and its Title) are persisted when you save/reopen the document. In this case, the Binding is persisted as a piece of XML that stores the type ("text"), name ("MyBinding") and a reference to the internal ID of the content control, which is a 32-bit number, although that is not immediately obvious when you look at the XML - in an example here, the Id Word stores for the ContentControl is -122165626, but "Office" stores the ID for the Binding as 4172801670, but that's because they are using the two different two's complement representations of the same number.
Heads up to anyone who is self hosting who also runs across this bug....
In version 5.6.0 silver theme, the dialog urlinput enable/disable works for the input field but not the browse button of the control. The problem is that the enable/disable events are intercepted by the typeaheadBehaviours portion of the internal object so they never make it to the event handlers for the overall field. The fix is to add the onDisabled and onEnabled handlers to the Disabling.config for typeaheadBehaviours and remove the line of code from each handler that addresses the input field.
Original typeaheadBehaviours Disabling.config....
Disabling.config({
disabled: function () {
return spec.disabled || providersBackstage.isDisabled();
}
})
Amended code....
Disabling.config({
disabled: function () {
return spec.disabled || providersBackstage.isDisabled();
},
onDisabled: function (comp) {
memUrlPickerButton.getOpt(comp).each(Disabling.disable);
},
onEnabled: function (comp) {
memUrlPickerButton.getOpt(comp).each(Disabling.enable);
}
})
Haven't been able to figure out how to get those events to bubble up to the the overall control handlers but this seems to make things work as expected.
I'm trying to make an input that will allow user to select multiple items. When finished selecting, he can press Enter to push his selections into an array in the state. The input will then clear and be ready for his next set of selections. (Imagine populating a 2-d array quickly). However, with the code below, if the user presses Enter to select the hint, my callback, pushToState, will trigger as it's in onKeyDown. What's the correct way to implement this behavior?
<Typeahead
id="basic-typeahead-multiple"
labelKey="name"
multiple
onChange={setMultiSelections}
options={options}
selected={multiSelections}
onKeyDown={(event) => {
if (event.key === 'Enter') {
pushToState(multiSelections);
setMultiSelections([]);
}
}}
/>
Your use case is similar to the one in this question. You basically need to determine whether the user is selecting a menu item or not. You can do that by checking the activeIndex of the typeahead:
// Track the index of the highlighted menu item.
const [activeIndex, setActiveIndex] = useState(-1);
const onKeyDown = useCallback(
(e) => {
// Check whether the 'enter' key was pressed, and also make sure that
// no menu items are highlighted.
if (event.key === 'Enter' && activeIndex === -1) {
pushToState(multiSelections);
setMultiSelections([]);
}
},
[activeIndex]
);
return (
<Typeahead
id="basic-typeahead-multiple"
labelKey="name"
multiple
onChange={setMultiSelections}
options={options}
onChange={setMultiSelections}
onKeyDown={onKeyDown}
selected={multiSelections} >
{(state) => {
// Passing a child render function to the component exposes partial
// internal state, including the index of the highlighted menu item.
setActiveIndex(state.activeIndex);
}}
</Typeahead>
);
I'm trying to get user's latest mouse click in order to display the right table. However, I can't find any way to implement this idea. How do i get user's latest mouse click by using mouseEvent function?
I tried using if else statements but it doesn't work when there is still value in the monstersTable1
def handleEditMonster(action : ActionEvent) = {
val selectedMonster1 = monstersTable1.selectionModel().selectedItem.value
val selectedMonster2 = monstersTable2.selectionModel().selectedItem.value
if (selectedMonster1 != null){
val okClicked = MainApp.showMonsterEditDialog(selectedMonster1)
if (okClicked) showMonstersDetails(Some(selectedMonster1))
} else if (selectedMonster2 != null) {
val okClicked = MainApp.showMonsterEditDialog(selectedMonster2)
if (okClicked) showMonstersDetails(Some(selectedMonster2))
} else {
// Nothing selected.
val alert = new Alert(Alert.AlertType.Warning){
initOwner(MainApp.stage)
title = "No Selection"
headerText = "No monsters Selected"
contentText = "Please select a monsters in the table."
}.showAndWait()
}
}
I want it to be able to access the second table even though selectedMonster1 is still != null
It's not entirely clear from your question what it is you're trying to do, so please bear with me... (For future reference, it's best if you can create a ''minimal, complete and verifiable example'' that illustrates your problem.)
I'm assuming that you have two scalafx.scene.control.TableView instances, referenced via monstersTable1 and monstersTable2. You want to allow the user to select either one of the monsters in the first table, or one of the monsters in the second table, but not to be able to select one monster from each table simultaneously.
I'm unclear when your handleEditMonster function is called, so I'm guessing that it's invoked when the user clicks, say, an Edit Monster button, as that button's clicked event handler.
Do I have that right?
Assuming the above is accurate, you should listen for changes in table selection, and clear the selection in the other table when a new selection is made. The currently selected item in each table is a property that we can add a listener to, so we can achieve this with the following code (in your scene's initialization):
// In the onChange handlers, the first argument references the observable property
// that has been changed (in this case, the property identifying the currently
// selected item in the table), the second is the property's new value and the third
// is its previous value. We can ignore the first and the third arguments in this
// case. If the newValue is non-null (that is, if the user has made a
// selection from this table), then clear the current selection in the other
// table.
monstersTable1.selectionModel.selectedItem.onChange {(_, newValue, _) =>
if(newValue ne null) monstersTable2.selectionModel.clearSelection()
}
monstersTable2.selectionModel.selectedItem.onChange {(_, newValue, _) =>
if(newValue ne null) monstersTable1.selectionModel.clearSelection()
}
This should do the trick for you, and your handleEditMonster function should now work. You might want to add an assertion to guard against both tables having a current selection, which would indicate a bug in the selection handler logic.
I need to toggle an element ONLY if it is not disabled.
jQuery("#sbutton").toggle(
function () {
if (!jQuery(\'input[name^="choose"]\').attr ( "disabled" )) {
jQuery(\'input[name^="choose"]\').attr ( "checked" , true);
}
},
function () {
jQuery(\'input[name^="choose"]\').removeAttr("Checked");
}
)
Is the IF condition possible?
What you probably want to do (thanks Frédéric):
jQuery("#sbutton").click(function() {
if (jQuery('input[name^="choose"]').is(':disabled'))
return false;
if (jQuery('input[name^="choose"]').is(':checked'))
jQuery('input[name^="choose"]').removeAttr("checked");
else
jQuery('input[name^="choose"]').attr("checked", true);
});
or simply
jQuery("#sbutton").click(function() {
var checkbox = jQuery('input[name^="choose"]');
if (checkbox.is(':disabled'))
return false;
checkbox.attr('checked', !checkbox.is(':checked'));
});
The problem with your code is that you expect the evaluation on disabled to be evaluated on every button click and use the first function if true. It's only called on every other click though, and the other function doesn't care if it's disabled or not. It checks the check box no matter what. You have to either bind on the click event, like I've done, or bind to and unbind from the toggle event depending on whether or not the button is disabled.
In the future it would be easier to help you if you present your code as a fiddle (http://www.jsfiddle.net) and describe more thoroughly what you're trying to do and what it is that's not working.