Committing the changes in Handsontable from outside - handsontable

By Default when we enter a value inside a cell in Handsontable and the press Enter key or go to another cell or other part of the page, the value we have already entered into the cell will be committed automatically (after validation).
But I have a new requirement now. I want to manually commit the changes form outside of Handsontable (e.g. with calling a JavaScript function).
The real story is that I have rendered dropdown control inside some cells in Handsontable. When the user enters a number in a cell without pressing Enter key; and then clicks on the dropdown control in another cell; I do not have access to their new entered value.
I am going to commit their former changes when they click on the dropdown.
Any Idea?
Update:
I created a jsFiddle and did my best to keep it as simple as possible. http://jsfiddle.net/mortezasoft/3c2mN/3/
If you change the Maserati word to something else and without pressing Enter choose an option in dropdown, you can still see the name Maserati is shown as an alert dialog.
<div id="example"></div>
var data = [
["", "Maserati"],
["", ""],
];
$('#example').handsontable({
data: data,
minSpareRows: 1,
colHeaders: true,
contextMenu: true,
cells: function (row, col, prop) {
var cellProperties = {};
if (col===0 && row===0) {
cellProperties.renderer = selectBoxRenderer;
cellProperties.readOnly =true;
}
return cellProperties;
}
});
function selectBoxRenderer(instance, td, row, col, prop, value, cellProperties) {
var $select = $("<select><option></option> <option>Show the name</option></select>");
var $td = $(td);
$select.on('mousedown', function (event) {
event.stopPropagation(); //prevent selection quirk
});
$td.empty().append($select);
$select.change(function () {
//Default value is Maserati but we are gonna change it.
alert($('#example').handsontable('getData')[0][1]);
});
}

You can add instance.destroyEditor() to the mousedown handler on $select. This will commit the changes on first click, but will also require another click to open the select menu.
$select.on('mousedown', function (event) {
event.stopPropagation(); //prevent selection quirk
instance.destroyEditor();
});
The reason behind second click problem is that instance.destroyEditor() re-renders the table, which causes the original select element to be destroyed, so the click event cannot take effect.
To solve this, add
if ($td.find('select').length!=0) return;
at the beginning of the renderer. This way existing select elements will not be overwritten when re-rendering.

Related

How to avoid multiple radio buttons selection when paginating a data table

I'm having a problem here:
When I select a radion button in a page 1 and another one in the same page it works fine, but when I select a radio button in the page number 2, and go back to the page number 1, that first radio button still selected and the one in the page number 2 is also selected, how can I solve this problem? I was looking for a solution here in the forum but couldn't find someone with the same problem.
*[code] $(document).ready(function () { var oTable = $('#example').dataTable({ "bJQueryUI": true, "sPaginationType": "full_numbers" }); }); [/code]*
There is no solution from DataTables itself. You'll have to do it on your own.
What you can do is save the selected value yourself on a click. Imagine you have a table called projectsTable. Then you can write:
var selection = -1;
$("#projectsTable input[type=radio]").on
(
"click",
function()
{
selection = $(this).val();
}
);
Then, you'll have to unselect all the wrong values every time the page changes. Add a callback in the construction of your table for page draw to do that:
//other settings go here, like the dom one
//you can choose your own, no need for this specific one
"dom": "lfBrtip",
"fnDrawCallback":
function(oSettings)
{
$("#projectsTable input[type=radio][value!="+selection+"]").prop('checked', false);
}
Every time the page is changed, this piece of code deselects everything you don't want to be selected any longer.

kendo-datasource autoSync causes navigation placeholder to return to upper left corner of the grid

I'm using kendo-ui with angularJS 1.5 and I have a simple kendo-grid bound to a datasource with transport configured using functions as follows:
private buildDataSource() {
this.dataSource = new kendo.data.DataSource({
autoSync: true,
change: this.dataSourceChangeHandler.bind(this),
error: this.dataSourceErrorHandler.bind(this),
transport: {
read: this.dataSourceRead.bind(this),
create: this.dataSourceCreate.bind(this),
update: this.dataSourceUpdate.bind(this),
destroy: this.dataSourceDestroy.bind(this)
},
[...]
});
}
private dataSourceUpdate(e: kendo.data.DataSourceTransportUpdate) {
var updatedItem: KendoCosto = e.data;
[...]
e.success(updatedItem, undefined, undefined);
}
The grid options looks like this:
this.gridOptions = {
dataSource: this.dataSource,
change: this.gridChangeHandler.bind(this),
editable: {
mode: "incell",
confirmation: false
},
navigatable: true,
selectable: "multiple, cell",
allowCopy: true,
toolbar: [
"create"
],
[...]
The grid works fine and the read, create, update, destroy behave as expected.
My problem is that whenever I change a value in a grid's cell and hit enter, I would like to have keyboard navigation "placeholder" (the grid has navigatable: true) to remain on the edited cell, but it happens to be moved to the upper left corner cell.
This behavior happens only when dataSource's autoSync is set to true.
I've also tried to "set" the current cell via the ".current" method of the grid's api but it doesn't seem to work:
// this is bound to the grid's change event and it is supposed to
// store the currently selected cell in a property of the class
// that builds both the datasource and the grid
private gridChangeHandler(e: kendo.ui.GridNavigateEvent)
{
this.thisGrid = this.thisGrid || e.sender;
this.currentCell = e.sender.current();
}
// Then on the change event of the datasource I do
private dataSourceChangeHandler(event: kendo.data.DataSourceChangeEvent)
{
if (this.currentCell && this.thisGrid) {
this.thisGrid.select(this.currentCell);
this.currentCell = undefined;
}
}
any suggestions ?
Thanks in advance !
--- edit ---
The code I posted/pasted in the comment is absolutely unreadable so I'm repeating the code here:
To have your solution work, I had to modify my dataBound handler this way.
private gridDataBoundHandler(e: kendo.ui.GridDataBoundEvent) {
if (this.thisGrid && this.currentCell) {
setTimeout((() => {
// this.thisGrid.editCell(this.currentCell);
this.thisGrid.current(this.currentCell);
}).bind(this)
, 10);
}
}
without the timeout, the navigation placeholde was still resetting back to the upper left corner.
First, I think the grid change event is the wrong event to attach to as it only fires when the user selects a row/cell with the mouse...it will not fire on tab events.
So, I would use the grid save event, which fires after you make an edit and "commit" the change through enter, tab, mouse off, etc.
Second, the e.sender.current() includes the current identifying information like "grid_active_cell" and "k-state-focused" and "k-dirty-cell", etc. By the time you get to the dataSource change event, the cell has actually lost all that decoration and your this.currentCell is essentially pointing at a non-existent selector. So, you need to grab a more "permanent" identifier.
So, using the grid save event:
save: function (e) {
var row = $(e.sender.current()).closest("tr");
var colIdx = $("td", row).index(e.sender.current());
var model = e.sender.dataItem(row);
currentCell = "tr[data-uid='" + model.uid + "'] td:eq(" + colIdx + ")";
}
And then in the grid DATABOUND event(as the dataSource change event is still followed by events that change the cell focus to the top-left, but grid.dataBound is further in the chain and seems to work better):
dataBound: function (e) {
if (currentCell) {
grid.editCell(currentCell);
grid.current(currentCell);
}
}
Demo(with variable changes as I do not have your whole class, based on a kendo grid demo): http://dojo.telerik.com/#Stephen/OjAsU
Note that this solution(not my implementation, but your technique in general) will break tabbing from cell to cell, i.e. tabbing will commit the edit but the dataSource change event will always put the focus back on the just-edited cell instead of moving to the tabbed-to cell. This breaks user expectation of what tab does. So, you should consider trying to capture the enter key press only instead of relying on the grid events(which fire regardless of tab or enter).

How can I complete an edit with the right arrow key in a Kendo grid cell?

When a Kendo grid cell is open for editing, what is the best way to close the cell (and move to the next cell) with the right arrow key?
Take a look on the following snippet. It is a simple way for doing what you want:
// Bind any keyup interaction on the grid
$("#grid").on("keyup", "input", function(e)
{
// Right arrow keyCode
if (e.keyCode == 39)
{
// Ends current field edition.
// Kendo docs says that editCell method:
// "Switches the specified table cell in edit mode"
// but that doesn't happens and the current cell keeps on edit mode.
var td = $(e.target)
.trigger("blur");
// Find next field
td = td.closest("td").next();
// If no cell was found, look for the next row
if (td.length == 0)
{
td = $(e.target).closest("tr").next().find("td:first");
}
// As ways happens on kendo, a little (ugly)workaround
// for calling editCell, because calling without
// the timer doesn't seem to work.
window.setTimeout(function()
{
grid.editCell(td);
}, 1);
}
});
I don't know why but I could not save a Fiddle for that, I got 500 Internal error. Anyway it seems to achieve what you need. The grid needs to be in edit mode incell.

jqGrid : Image not changing in edit window when pressing the previous and next arrow

I have a jqGrid and in which there is a column which holds an image. When the user click on the edit icon from the page then in the edit window the photo is visible and that has been done by the following command in the edit section of the navGrid -
recreateForm: true,
beforeInitData: function () {
var cm = jQuery("#list3").jqGrid('getColProp', 'img'),
selRowId = jQuery("#list3").jqGrid('getGridParam', 'selrow');
cm.editoptions.src = '/BDED_WEB/resources/images/user'+selRowId+'.jpg';
}
But if I want to go back and forward to the data set by pressing the previous and next arrow in the edit window, then all the data changed but the image is not changing. That means the beforeInitData method is not getting called when the user is clicking on pData or nData button.
How can I change the image also in the edit window when the user press the next and previous arrow buttons?
It looks like you use the demo which I created for the answer.
To implement changing of the image on clicking on the "Next", "Prev" buttons of the edit form (marked yellow on the image below)
one can use afterclickPgButtons callback which set src attribute.
afterclickPgButtons: function () {
var $self = $(this),
selRowId = $self.jqGrid("getGridParam", "selrow");
// "img" below is the column name which have edittype: "image"
$("#img").attr("src", "/BDED_WEB/resources/images/user" + selRowId + ".jpg");
}
The demo demonstrates the modified version of the original demo.

JQuery Vector Map: Tooltip remains displayed on the map after click

I am using JQuery VectorMap.
When I click on a country, the tooltip containing the description is shown.
However, when I click on another country, the previously displayed tooltip is not removed from the screen.
I don't understand why the tooltip of the clicked region stays displayed, since the onRegionClick event does not save the state of the tooltip.
Here is the code:
onRegionClick: function(event, code){
if (gdpData[code]) {
$('#currencyHidden').val(wm2idCurrencyMap[code]);
$('#calculatorCurrencyToHidden').val(wm2idCurrencyMap[code]);
$('#calculatorWmCurrencyToHidden').val(wm2idCurrencyMap[code]);
submitCurrenciesFormWithOptions();
}
},
function submitCurrenciesFormWithOptions() {
// sets the form options and submits the form
$('#currenciesForm').ajaxSubmit(currenciesFormOptions);
//submitCalculatorFormWithOptions();
return false;
}
Thank you !
Checked your onLabelShow function.
onLabelShow: function(e, el, code){
el.html(el.html()+' (GDP - '+gdpData[code]+')');
};
jvectormap example site url. http://jvectormap.com/examples/world-gdp/

Resources