Handsontable Select2 Dependent Dropdowns - jquery-select2

I have two select2 dropdowns and I want to change options the second dropdown depending on first dropdown.
For example,
{
data: 'country_id',
editor: 'select2',
renderer: customDropdownRenderer,
select2Options: {
data: {!! $production_units !!} ,
dropdownAutoWidth: true,
}
},
{
data: 'state_id',
editor: 'select2',
renderer: customDropdownRenderer,
select2Options: {
data: [],
dropdownAutoWidth: true,
width: 'resolve'
}
},
Depending on country_id, I want to change select2 options of state_id. I know how to make this work with just select2, but I am not able to figure out how to make it work with handsontable.
I have change select2Options in afterChange, but how to do that?
afterChange: function (change, source) {
if(change)
{
if(change[0][1] == 'country_id')
{
$.get("/api/states?country="+change[0][3], function(data){
//What should be done here?
});
}
}
},

You retrieve all the states for that country. Make sure the states list is in the same format that select2 expects.
Then loop through the columns list and determine the dependent column for the current column that has been modified.
Get the cell properties:
var cellProperties = instance.getCellMeta(rowIndex, dependentColumnIndex);
Update the select2 source:
cellProperties['select2Options'].data = [states list];

Related

Tabulator copyToClipboard method isn't working as anticipated

I am new to the Tabulator plug-in and I am attempting to copy data from one table to another using the Tabulator copyToClipboard method but with no success.
In my application I have created eleven <div> elements (one for the [Crew Leader] and one each for up to ten [Crew Members]) to serve as containers for the Tabulator tables to be instantiated. I am hoping to copy data from the [Crew Leader] table and paste it into each of the affected [Crew Member] tables thus mitigating data re-entry. This sequence of copy/paste events is triggered by the click event bound to a <button> in the header of the [Crew Leader] table. The following function is called by the <button> click event:
function CloneTable() {
// Verify the [Crew Leader] Tabulator table is present....
var tableLeader = Tabulator.prototype.findTable("#CrewLeaderTable");
if (tableLeader.length > 0) {
alert("The Tabulator table #CrewLeaderTable was found.\ntable.length = " + tableLeader.length);
tableLeader.copyToClipboard("all");
alert("The table contents were copied to the clipboard.");
}
else {
alert("The Tabulator table #CrewLeaderTable was not found.");
}
}
The first alert message verifies that the #CrewLeaderTable object has been found as anticipated. However, the second alert verification is never received thus indicating failure of the Tabulator copyToClipboard method.
I have read through as much of the relevant Tabulator documentation as I can find and I am hoping I have simply overlooked something in my setup.
The following is a copy of my Tabulator constructor:
var table = new Tabulator(divid, {
height: "100%",
layout: "fitDataFill",
movableRows: true, //enable user movable rows
tabEndNewRow: true, //create empty new row on tab
rowContextMenu: myActionContextMenu,
keybindings: {
"navUp": true, //enable navUp keybinding using the "up arrow" key
"navDown": true, //enable navDown keybinding using the "down arrow" key
},
columns: [
{ title: "Phase Code", field: "phaseCode", width: 144, editor: "select", editorParams: { values: function (cell) { return window.laborPhaseCodes; } } },
{ title: "Date Worked", field: "dateComp", hozAlign: "center", sorter: "date", editor: dateEditor },
{ title: "Start Time", field: "timeStart", hozAlign: "center", sorter: "time", editor: timeEditor },
{ title: "Finish Time", field: "timeFinish", hozAlign: "center", sorter: "time", editor: timeEditor },
{ title: "Memo", field: "memo", width: 144, hozAlign: "left", editor: "input" },
{ title: "<button type='button' id='btnClone' class='btn btn-success btn-sm py-0' style='font-size:10px;'>Clone</button>", headerSort: false, headerClick: tabCloneTable }
],
cellEdited: function (cell) {
}
});
I have spent a couple of days trying to figure out the best way to "clone" the data from one table into another. The Tabulator documentation is fairly comprehensive but I fear I have overlooked something. Any assistance is greatly appreciated.
It looks like copyToClipboard doesn't return the data, it is maintained internally and not accessible. But, with what you are doing set/getData works fine.
Here is an example, https://jsfiddle.net/nrayburn/19sjg74k/7/.
Basically, what you want to do is call getData on the parent table and setData on the child table.
const crewLeaderTable = Tabulator.prototype.findTable('#CrewLeaderTable')[0];
const crewMemberTable = Tabulator.prototype.findTable('#CrewMember1Table')[0];
const crewLeaderData = crewLeaderTable.getData();
// You could also use replaceData or addData, depending on the requirements
crewMemberTable.setData(crewLeaderData);

ASP.Net MVC 6 Cascading Dropdowns Not Populating [duplicate]

This question already has answers here:
Clear and refresh jQuery Chosen dropdown list
(7 answers)
Closed 6 years ago.
I'm using cascading dropdowns on a page. The first dropdown is being filled from ViewBag
#Html.DropDownList("OrgGroupID",
(IEnumerable<SelectListItem>)ViewBag.OrgGroups,
new Dictionary<string, object>
{
{ "class", "form-control" },
{ "width", "100%" },
{ "data-placeholder", "Select Group..." },
{ "onchange", "groupSelected(this)" }
})
and the second one is being filled when a value is selected from first one. The markup for second dropdown is
#Html.ListBox("Devices",
(IEnumerable<SelectListItem>)ViewBag.Devices,
new Dictionary<string, object>
{
{ "id", "devices"},
{ "class", "chosen-select form-control" },
{ "width", "100%" },
{ "data-placeholder", "Select Devices..." }
})
and the jquery function to fill the second dropdown is
function groupSelected(obj) {
var selectedGroupId = obj.options[obj.selectedIndex].value;
$.ajax({
url: "../Devices/DevicesByGroupId",
type: "GET",
dataType: "JSON",
data: { groupId: selectedGroupId },
success: function (devicesData) {
$("#devices").html("");
$.each(devicesData, function (index, itemData) {
$("#devices").append(
$("<option></option>").val(itemData.Value).html(itemData.Text)
);
});
}
});
}
The api method which is being invoked executes and returns data but for some reason, the values are not appended to the second dropdown.
Please suggest what am I missing here.
#StephenMuecke you saved my day mate! Removing the chose-select class loaded the data. I just found that I had to invoke
$("#devices").trigger("chosen:updated");
to update the listbox. Thanks a lot for pointing me in this direction :)

Angularjs: UI-Grid dynamic dropdown for each row

I am using 'ui-grid/dropdownEditor' for one of my column and I want to dynamically load the drop down options which is unique for each row. I want to load the drop down options dynamically on demand via async http call.
I tried the following without success,
$scope.gridOptions = {
columnDefs: [
{ field: 'priority',
displayName: 'Priority',
editableCellTemplate: 'ui-grid/dropdownEditor',
editDropdownIdLabel: 'id',
editDropdownValueLabel: 'name',
},
]}
onRegisterApi: function(gridApi) {
gridApi.edit.on.beginCellEdit($scope, function(rowEntity, colDef) {
if (colDef.field === "priority") {
localServices.getPriorityById(rowEntity.id).then(function(data) {
colDef.editDropdownOptionsArray = data;
});
}
});
Any suggestion or help to achieve this is appreciated.
You should look into the usage of editDropdownRowEntityOptionsArrayPath instead of editDropdownOptionsArray
editDropdownRowEntityOptionsArrayPath can be used as an alternative to
editDropdownOptionsArray when the contents of the dropdown depend on
the entity backing the row.
Here is a link to tutorial

Exporting CSV from ui-grid with cell display rather than the source value

I have a table done with ui-grid and this table has a column with cellFilter definition like this:
{ field: 'company', cellFilter: 'mapCompany:row.grid.appScope.companyCatalog' }
My gridMenu custom item is configured like this:
gridMenuCustomItems: [
{
title:'Custom Export',
action: function ($event) {
var exportData = uiGridExporterService.getData(this.grid, uiGridExporterConstants.ALL, uiGridExporterConstants.ALL, true);
var csvContent = uiGridExporterService.formatAsCsv([], exportData, this.grid.options.exporterCsvColumnSeparator);
uiGridExporterService.downloadFile (this.grid.options.exporterCsvFilename, csvContent, this.grid.options.exporterOlderExcelCompatibility);
},
order:0
}
]
The table is displayed correctly, but when I try to export to CSV, the Company column is exported with empty value. Here is my Plunkr.
Any suggestion will be appretiated
References
I did some research and according to ui-grid Issue #4948 it works good when the Company column is filled with an static catalog. Here is a Plunkr demostrating that.
As you mentioned, there is an export issue when the values in the column are not static, so I forked your plunker with a solution that creates the company mapping for each data object and adds it as a key-value once you get the company catalog back:
$http.get('https://api.github.com/users/hadley/orgs')
.success(function(data) {
$scope.companyCatalog = data;
angular.forEach($scope.gridOptions.data, function(item) {
var compMap = uiGridFactory.getMapCompany(item.company, $scope.companyCatalog);
item.mappedCo = compMap;
});
});
I've kept the original company column but made it invisible (rather than overwriting it), so it exports with the rest of the data in the csv. New column defs:
columnDefs: [
{ field: 'name' },
{ field: 'mappedCo', name: 'Company'},
{ field: 'company', visible: false }
]
Also, in the case that you were getting your data from a server, you would have to ensure that the data and the catalog returned before you run the mapping function. This solution may not work in your particular use case; I don't know.
I found a solution to the CSV export to be able to display the cell display value.
My mistake was using row.grid instead of this.grid at the mapCompany cell filter:
columnDefs: [
{ field: 'name' },
{ field: 'company', cellFilter: 'mapCompany:row.grid.appScope.companyCatalog' }
],
The right way to use it is using this:
columnDefs: [
{ field: 'name' },
{ field: 'company', cellFilter: 'mapCompany:this.grid.appScope.companyCatalog' }
],
Here is my Plunkr.

kendo ui Combobox binded to a Grid losts it's value and text after Grid's Cancel button pressed

I have two views in database. Bonuses and employees. One(employee)-to-many(bonuses).
I have kendo ui grid (kendo web), which displays ajax results from controller called Bonuses
And an autocompliting element - Employee Combobox binded with Employee filed of a grid.
Grid's datasource:
// bind json result from /Bonuses/GetPagedJsonBonuses
var bonusesDataSource = new kendo.data.DataSource({
transport: {
read: "#Url.Action("GetPagedJsonBonuses", "Bonuses")",
update: {
url: "#Url.Action("Edit", "Bonuses")",
type: "PUT"
},
create: {
url: "#Url.Action("Create", "Bonuses")",
type: "POST"
},
parameterMap: function(options, operation) {
if (operation === "update" || operation === "create") {
// updates the BonusDTO.EmployeeId with selected value
if (newValueEmployeeId !== undefined)
options.EmployeeId = newValueEmployeeId;
}
return options;
}
},
schema: {
data: "Data", // PagedResponse.Data
total: "TotalCount", // PagedResponse.TotalCount
model: {
id: "BonusId", // Data
fields: {
EmployeeId: { type: "number" },
EmployeeLastName: {
type: "string",
editable: true,
//validation: { required: {message: "Employee's last name is required"}}
},
Amount: {
type: "number",
editable: true,
nullable: false,
validation: {
required: { message: "Amount is required to be set" }
}
}
} // fields
} // model
}// schema
});
Grid element looks like this:
// creates bonuses grid control
$("#bonusesGrid").kendoGrid({
dataSource: bonusesDataSource,
toolbar: ["create"],
editable: "inline",
columns: [
"BonusId",
"EmployeeId",
{
field: "EmployeeLastName",
editor: employeeAutocompletingEditor,
template: "#=EmployeeLastName#"
},
"Amount",
{
command: ["edit"],
title: " "
}
],
save: function(e) {
if (newValueEmployeeId !== undefined && newValueEmployeeLastName !== undefined) {
e.model.EmployeeId = newValueEmployeeId; // it's a hack to bind model and autocomplete control
e.model.EmployeeLastName = newValueEmployeeLastName;
}
},
edit: function(e) {
setCurrentValueEmployeeIdAndLastName(e.model.EmployeeId, e.model.EmployeeLastName);
},
cancel: function(e) {
setCurrentValueEmployeeIdAndLastName(e.model.EmployeeId, e.model.EmployeeLastName);
}
});
Autocompleting combobox has it's own datasource using ajax:
// datasource for autocomlete combobox to lookup employees names from
var employeesDataSource = new kendo.data.DataSource({
transport: {
read: "#Url.Action("GetJsonEmployeesByLastName", "Bonuses")",
},
parameterMap: function(options, operation) {
if (operation === "update" || operation === "create") {
setNewValueEmployeeIdAndLastName(options.Id, options.LastName);
}
return options;
},
});
Autocompliting combobox look's like this:
function employeeAutocompletingEditor(container, options) {
$('<input required data-text-field="LastName" data-value-field="EmployeeId" data-bind="value:' + options.field + '"/>')
.appendTo(container)
.kendoComboBox({
// sets the local variables to update values of current row.
change: function() {
setNewValueEmployeeIdAndLastName(this.value(), this.text());
},
dataBinding: function (e) {
console.log("dataBinding: ", e, this.dataItem());
},
dataBound: function (e) {
console.log("dataBound: ", e, this.dataItem());
},
dataSource: employeesDataSource
});
}
I use Editor binding to pass values(EmployeeId) and Text (EmployeeLastName) from grid to combobox.
I also use a hack like temporal variables (newValueEmployeeId, currentValueEmployeeId) to
send selected Employee in combobox and pass it to grid for correct save. A found it's a most common practice to pass a value back to grid.
My problems is:
If I press Edit button on my grid first time The combobox displays current employee's name from grid row:
If I press Cancel button and again press Edit button, combobox doesn't display current value of grid (employee's name)
IF I type some name, change some other values, and Udate(save) value, next time combobox again displays employees name, but only once before Cancel was pressed.
I'm very new in Kendo UI and this problem drives me crazy...
I think that combobox losts it's binding or doesn't update smth. I tried to set values while onBound and onBinding events, but this doesn't help. Please help me with an advice and example.
PS all evenets and functions is my try to debug and find solution.
only one fix helped me:
var employeeList = new List<Employee>()
employeeList.add(new Emplpyee()) // add fake employee record.
return Json(employeeList)
I don't know why, but grid control start make cyclying empty ajax requests if I return empty list of employees or null. This doesn't work:
return Json(new List<Employee>());
return Json(null);
I think it's a problem in kendo combobox itself ,because it's not ready to receive and handle empty list or null as json result.
Also I heared something, that JQuery doesn't support empty or null results anymore...maybe that's the reason

Resources