I am using kendo grid with MVC in a .NET project. Two columns of my grid are templates and those have an input text inside of the template. That way every time the grid loads the input texts are always visible and available for change.
When the user clicks on save, I need to check all the rows of the grid, at client side and get the values of those two columns (the only two have templates) and get the values of the input box. So the result I am expecting is a list with two columns that have the last values inserted by the user in the input boxes and not the original value.
Here is my code:
//Grid Data source
var dataSource = new kendo.data.DataSource({
transport: {
read: { url: "/CsmForecastRegistration/GetForecast", cache: false }
},
error: function (e) {
openDialog(e.errorThrown);
},
batch: true,
pageSize: 20,
schema: {
data: "Data",
total: "Total",
errors: "Errors",
model: {
id: "ForecastItemId",
fields: {
ForecastItemId: { editable: false },
RecordId: { editable: false },
SaleId: { editable: false },
IsUpSell: { editable: false },
BusinessName: { editable: false },
HealthScore: { editable: false },
CurrencySymbol: { editable: false },
ForecastWeekTotalContractValue: { editable: true },
ForecastWeekMonths: { editable: true },
ForecastWeek12Months: { editable: false }
}
}
}
});
$("#grdCsmForecast").kendoGrid({
dataSource: dataSource,
scrollable: true,
dataBound: onDataBound,
toolbar: ["excel"],
excel: {
allPages: true,
fileName: "CSMForecast.xlsx"
},
pageable: true,
columns: [
{ title: "", width: "80px", template: $("#comments-template").html(), attributes: { style: "text-align:center; background-color: white;" } },
{
title: "Contract Details",
columns: [
{ field: "RecordId", title: "RecordId", width: "90px", attributes: { "class": "contractDetailGridStyle" } },
{ field: "SaleId", title: "SaleId", width: "90px", attributes: { "class": "contractDetailGridStyle" } },
{ field: "IsUpSell", title: "Upsell?", width: "75px", attributes: { "class": "contractDetailGridStyle" } },
{ field: "BusinessName", title: "Business Name", width: "250px", attributes: { "class": "contractDetailGridStyle"} },
{ field: "HealthScore", title: "Health Score", width: "95px", attributes: { "class": "contractDetailGridStyle"} },
{ field: "CurrencySymbol", title: "CCY", width: "50px", attributes: { "class": "contractDetailGridStyle" } }
]
},
{
title: "Forecast Week",
columns: [
{ field: "ForecastWeekTotalContractValue", title: "TCV", width: "75px", template: $("#forecast-week-tcv").html(), attributes: { "class": "forecastWeekGridStyle" }, footerTemplate: "#: sum # " },
{ field: "ForecastWeekMonths", title: "Months", width: "70px", template: $("#forecast-weekMonths").html(), attributes: { "class": "forecastWeekGridStyle" } },
{ field: "ForecastWeek12Months", title: "12Month", width: "75px", attributes: { "class": "forecastWeekGridStyle" }, footerTemplate: "#: sum # " }
]
}
]
});
And the templates:
<script id="forecast-week-tcv" type="text/x-kendo-template">
# if(IsNewContract === true ){ #
<span>#=ForecastWeekTotalContractValue#</span>
#}
else{#
<input type="text" value="#=ForecastWeekTotalContractValue#" />
#}#
</script>
<script id="forecast-weekMonths" type="text/x-kendo-template">
# if(IsNewContract === true ){ #
<span>#=ForecastWeekMonths#</span>
#}
else{#
<input type="text" value="#=ForecastWeekMonths#" />
#}#
</script>
So I would like to have a list and send to my MVC the controller all the values of these two inputs:
<input type="text" value="#=ForecastWeekTotalContractValue#" />
<input type="text" value="#=ForecastWeekMonths#" />
Thanks
Try something like this:
function getInputValues() {
let result = [];
$('#grid tbody tr').each((i, tr) => {
let row = {};
$(tr).find('input[type="text"]').each((index, input) => {
row[(index ? "ForecastWeekTotalContractValue" : "ForecastWeekMonths")] = $(input).val();
});
result.push(row);
});
return result;
}
Demo
It just iterates over the elements and adds to an array of objects.
Related
I have a Kendo Master/Detail grid (jquery) that expands all rows to reveal any child records upon page load to provide a grid with a set of default data. However, not all of the rows returned when expanded have child elements to display. I currently have a link provided in a column of the master row, the link is coded using a template:
{
template: `"<a class='_kwJISSearch' style='color:blue; text-decoration:underline; cursor: pointer;'>Edit Case Assignment</a>",`
width: "100px"
}
What I would like to know if I can change the text and what the link is pointing to on the master row if no child elements are returned? I have provided my code below, where I create the columns for the master first, then create the grid with a data-bound, lastly, I coded the detail:
function loadSearchGrid() {
searchOriginalColumnList = [
{
field: "CaseYear",
title: "Case Year",
type: "number",
width: "100px"
},
{
field: "CaseNumber",
title: "Case Number",
width: "100px"
},
{
field: "Full_Style",
title: "Style",
template: "<a href='/Cases/Views/CaseItems/ViewDocket?cy=#=CaseYear#&cn=#=CaseNumber#' target='_blank' style='color: blue; text-decoration:underline' ># if(Full_Style == null || Full_Style == '' ) {# N/A #} else{ # #:Full_Style# #} # </a>",
width: "250px"
},
{
field: "DispInfo",
title: "Disp Info",
width: "175px"
},
{
field: "Max_OA",
title: "OA Date",
format: "{0:MM/dd/yyyy}",
width: "100px"
},
{
field: "Max_Conf",
title: "Conf Date",
format: "{0:MM/dd/yyyy}",
width: "120px"
},
{
field: "Evote_Info",
title: "Evote",
template: "<a href=" + apiUrl +"JISReports/JIS_eVOTE&P_CASEYEAR=#=CaseYear#&P_CASENUMBER=#=CaseNumber#&rs:Command=Render' target='_blank' style='color:blue; text-decoration:underline; cursor: pointer;' ># if(Evote_Info == 'TRUE') {# Evote Info #} else{ # #} # </a>",
width: "100px"
},
{
field: "Ap_T_Related",
title: "Related Case",
//format: "{0:MM/dd/yyyy}",
width: "120px"
},
{
field: "Lead",
title: "Lead",
//format: "{0:MM/dd/yyyy}",
width: "100px"
},
{
field: "Not_Lead",
title: "Not Lead",
//format: "{0:MM/dd/yyyy}",
width: "100px"
},
{
//field: "Ap_T_Related",
//title: "Related Case",
//format: "{0:MM/dd/yyyy}",
template: /*"# if( getDetailGrids() == null ) {# Case Not Assigned #} else{# <a class='_kwJISSearch' style='color:blue; text-decoration:underline; cursor: pointer;'>Edit Case Assignment</a>#}#",//*/"<a class='_kwJISSearch' style='color:blue; text-decoration:underline; cursor: pointer;'>Edit Case Assignment</a>",
width: "100px"
},
];
var searchGridSavedColumns = utils.getGridSavedColumns(searchOriginalColumnList, config.gridSettingsKeys.jisSearch);
grid = $("#grid").kendoGrid({
dataSource: new kendo.data.DataSource({
transport: {
read: {
url: localRoutes.searchUrl,
dataType: "json",
method: "POST",
data: function () {
model = {
PanelType: viewModel.get("selectedPanelType"),
DispFinalInfo: viewModel.get("selectedFinalDisp"),
AssgnComp: viewModel.get("selectedAssignComp"),
ShowComm: viewModel.get("selectedShowComm"),
SortResult: viewModel.get("selectedSortResult"),
Assignment_Select: viewModel.get("selectedAssgnTypes"),
Assignment_For: viewModel.get("selectedSuiteMate"),
SearchCY: viewModel.get("caseYear"),
SearchCN: $('#caseNumber').val(),
Style: viewModel.get("style"),
};
return model;
}
}
},
error: function (e) {
$.unblockUI();
},
pageSize: 50,
schema: {
model: {
id: "CaseUaId",
fields: {
CaseUaId: { type: "string" },
PanelTypes: { type: "string" },
FinalDisp: { type: "string" },
AssignComp: { type: "string" },
ShowComm: { type: "string" },
SortResult: { type: "string" }
}
},
},
}),
pageable: {
refresh: true,
pageSizes: [20, 50, 100, 500]
},
toolbar: ["excel"],
editable: false,
groupable: true,
selectable: true,
filterable: true,
columnMenu: true,
scrollable: true,
reorderable: true,
resizable: true,//setting to allow column headers to be resizeable
autoBind: false,
sortable: {
mode: "multiple",
allowUnsort: true
},
toolbar: kendo.template($("#toolbar").html()),
excel: {
fileName: "JIS Search.xlsx",
allPages: true
},
//Second set of code for Master Detail
detailInit: detailInit,
dataBound: function (e) {
this.expandRow(this.tbody.find("tr.k-master-row"));//.first());
},
columns: (!!searchGridSavedColumns) ? searchGridSavedColumns : searchOriginalColumnList,
}).data("kendoGrid");
///Code to set the column headers as tooltips
grid.thead.kendoTooltip({
filter: "th",
content: function (e) {
var target = e.target;
return $(target).text();
}
});
$("#grid").on("click", "._kwJISSearch", function (e) {
e.preventDefault();
var ca = grid.dataItem($(e.currentTarget).closest("tr"));
var win = $("#_kwJISSearch").data("kendoWindow");
win.title();
win.content("");
win.refresh("/JIS/JISAssignment" +
"?cy=" + ca.CaseYear +
"&cn=" + ca.CaseNumber);
win.center().open().maximize();
});
searchGridSettingsViewModel = utils.createGridSettingsVM("Search Grid Settings", "grid", config.gridSettingsKeys.jisSearch, "gridSettingsTmpl", "gridSettingsDialog", true, true, true, true, 20);
kendo.bind($("#grid").find(".k-grid-toolbar"), searchGridSettingsViewModel);
searchGridLoaded = true;
}//end assignment grid creation
function detailInit(e) {
$("<div/>").appendTo(e.detailCell).kendoGrid({
dataSource: {
//type: "odata",
transport: {
read: {
url: localRoutes.searchAssgnUrl,
dataType: "json",
method: "POST",
data: {
cy: e.data.CaseYear,
cn: e.data.CaseNumber,
showHis: viewModel.get("selectedAssignComp"),
caseY: viewModel.get("caseYear"),
caseN: viewModel.get("caseNumber")
}
}
},
serverPaging: true,
serverSorting: true,
serverFiltering: true,
pageSize: 10,
filter: { field: "Case_Ua_Id", operator: "eq", value: e.data.CaseUaId }
},
scrollable: false,
sortable: true,
pageable: true,
columns: [
//{ field: "CaseUaId", width: "110px" },
{
field: "UserName", title: "User Name",
template: "# if(AssignEndDate == 'Incomplete' ) {# <span style='color:red; font-weight: bold'> #:UserName# </span> #} else{ # #:UserName# #} # ",
width: "70px"
},
{
field: "ReasonDesc", title: "Reason Desc",
template: "# if(ReasonDesc == 'EXPEDITED' || ReasonDesc == 'WALK' ) {# <span style='color:red; font-weight: bold'> #:ReasonDesc# </span> #} else{ # #:ReasonDesc# #} # ",
width: "70px"
},
{ field: "AssignBeginDate", title: "Begin Date", width: "70px" },
{
field: "AssignEndDate", title: "End Date",
template: "# if(Status_Code == 'PENDINGREVIEW' ) {# #:AssignEndDate# <span style='color:blue; font-style: italic'> (Pending Review) </span> #} else{ # #:AssignEndDate# #} # ",
width: "70px"
},
{ field: "DueDate", title: "Due Date", width: "70px" },
{ field: "AssignForLocID", title: "Assignment For", width: "100px" },
{ field: "AssignedByLocID", title: "Assigned By", width: "100px" },
{ field: "Comments", title: "Comments", width: "110px" },
]
});
}//end Case Assignment Detail Grid
You can use JavaScript code inside a template, e.g.:
template: "<a class='_kwJISSearch' style='color:blue; text-decoration:underline; cursor: pointer;'># if (data.childrenProperty && data.childrenProperty.length) { ##Edit Case Assignment## } else { ##No children text here ## } #</a>",
Assuming your master row has an array property for children.
I'm using filter column mode:row in my grid. For my numeric column the menu is showned as below
What i need is a filter in this column as the filter that is used in menu mode
Here is a part of my code
schema: {
data: "results",
total: "total",
model: {
id: "accountingTransactionKey",
fields: {
accountingTransactionKey: { editable: false, nullable: false },
date: { editable: false, nullable: false },
organization: { editable: false, nullable: false },
accountDebit: { editable: false, nullable: true },
costArticleUsed: { editable: false, nullable: true },
accountCredit: { editable: false, nullable: true },
isIntraGroupPartnerOrganization: { editable: false, nullable: true, type: "number" },
currency: { editable: false, nullable: true },
sum: { editable: false, nullable: true, type: "number"},...
...{
field: "sum",
title: "Сумма",
width: "150px",
//format: "{0:n2}",
locked: true,
filterable:
{
multi: true,
cell:
{
operator: "eq",
suggestionOperator: "eq",
showOperators: true
}
},
template: function (dataItem) { return numberWithSpaces(dataItem.sum.toFixed(2)) },
footerTemplate: "<b>" +"#: numberWithSpaces(sum.toFixed(2)) #"+"</b>"
},
There is a soltion for my request?
Thank you
I have tried the following script and it gives me a range filter by using the property extra.
<script>
$(document).ready(function() {
var griddata = createRandomData(50);
$("#grid").kendoGrid({
dataSource: {
data: griddata,
schema: {
model: {
fields: {
City: { type: "string" },
Title: { type: "string" },
BirthDate: { type: "date" },
Age: { type: "number" }
}
}
},
pageSize: 15
},
height: 550,
scrollable: true,
filterable: {
extra: false,
operators: {
string: {
startswith: "Starts with",
eq: "Is equal to",
neq: "Is not equal to"
}
}
},
pageable: true,
columns: [
{
title: "Name",
width: 160,
filterable: false,
template: "#=FirstName# #=LastName#"
},
{
field: "City",
width: 130,
filterable: false,
},
{
field: "Title",
filterable: false,
},
{
field: "BirthDate",
title: "Birth Date",
format: "{0:MM/dd/yyyy HH:mm tt}",
filterable: false,
},
{
field: "Age",
width: 100,
filterable:
{
extra: true
}
}
]
});
});
</script>
If you want to create a customized range filter.
columns: [
{
field: "Age",
filterable: {
cell: { template: betweenAgeFilter }
}
}
]
function betweenAgeFilter(args) {
var filterCell = args.element.parents(".k-filtercell");
filterCell.empty();
filterCell.html('<span style="justify-content:center;"> <span>From:</span><input id="startAge"/><span>To:</span><input id="endAge"/></span>');
$("#startAge").kendoNumericTextBox({
change: function (e) {
var startAge = e.sender.value();
var endAge = $("#endAge").data("kendoNumericTextBox").value();
var dataSource = $("#grid").data("kendoGrid").dataSource;
if (startAge & endAge) {
var filter = { logic: "and", filters: [] };
filter.filters.push({ field: "Age", operator: "gte", value: startAge });
filter.filters.push({ field: "Age", operator: "lte", value: endAge });
dataSource.filter(filter);
}
}
});
$("#endAge").kendoNumericTextBox({
change: function (e) {
var startAge = $("#startAge").data("kendoNumericTextBox").value();
var endAge = e.sender.value();
var dataSource = $("#grid").data("kendoGrid").dataSource;
if (startAge & endAge) {
var filter = { logic: "and", filters: [] };
filter.filters.push({ field: "Age", operator: "gte", value: startAge });
filter.filters.push({ field: "Age", operator: "lte", value: endAge });
dataSource.filter(filter);
}
}
});
}
Requirement 1:
I need the user to the ability to edit content of the grid all the time, meaning as a template, the user should not be required click on the field and then the editor appears.
Requirement 2: I want a kendo editor for the user to enter/edit values.
The following is what I tried, since I don't know how to do this using template I tried out using editor
Grid setup:
dataSource: {
data: $scope.planOverviewModel,
sort: {
field: "TermName",
dir: "asc"
},
schema: {
model: {
fields: {
TermName: { type: "string", editable: false },
InNetwork: { type: "string", editable: true },
OutNetwork: { type: "string", editable: true }
}
}
},
},
columns: [
{ field: "TermName", title: "Term" },
{
field: "InNetwork",
title: "In-Network",
editor: $scope.setupTextBox
},
{
field: "OutNetwork",
title: "Out-Network",
editor: $scope.setupTextBox
}
],
editable: true,
change: function (e) {
console.log("changed");
if (e.action == "itemchange") {
this.sync();
}
}
Editor setup:
$scope.setupTextBox = function(container, options) {
$('<textarea class="form-control" type="text" data-bind="value:' + options.field + '"> </textarea>')
.appendTo(container).kendoEditor({
resizable: {
content: true,
toolbar: true
}
});
};
I have a kendo grid with create, edit and delete buttons. I also have a next button outside the grid. What I want to do is prevent the user from clicking on the next button, if the user doesn't at least create/edit one record first.
<div ng-show="showActivePage === 'PageTwo'" ng-controller="inputFiscalYearController" >
<div kendo-grid="myGrid" k-options="gridOptionsFiscalYear" ></div>
<div ng-click="showActivePage = 'PageThree'"> Next </div>
<div ng-click="showActivePage = 'PageOne'"> Back </div>
</div>
app.controller('inputFiscalYearController', ['$scope', function ($scope) {
$scope.isDisabled = false;
$scope.gridOptionsFiscalYear = {
toolbar: ["create"],
editable: true,
pageable: true,
edit: function(){
alert();
},
columns: [
{
field: "Name",
title: "Name",
width: "250px",
},
{
field: "Surname",
title: "Surname",
width: "250px",
},
{
title: "",
command: ["edit", "destroy"],
width: "105px"
},
],
editable: "inline",
dataSource: {
data: [
],
pageSize: 10,
schema: {
model: {
id: "id",
fields: {
id: { editable: false },
Name: {
type: "string",
validation: {
required: {
message: "*Required"
}
}
},
Surname: {
type: "string",
validation: {
required: {
message: "*Required"
}
}
},
}
}
}
},
}
}]);
I'm not familiar with kendo-ui, but I do know Angular. Couldn't you just do:
<div ng-click="showActivePage = 'PageThree'" disabled="!gridOptionsFiscalYear.data.length"> Next </div>
I'm presuming that gridOptionsFiscalYear.data is where new records will be created.
Edit: didn't have the required negation on the length.
in Kendo UI Grid (with Angularjs) i have the following grid:
<div kendo-grid k-data-source="Table" k-options="thingsOptions" style="height: 365px">
$scope.thingsOptions = {
sortable: "true",
scrollable: "true",
toolbar: [{ name: "create", text: "Aggiungi Prodotto" }],
columns: [
{ field: "Name", title: "Name", width: "50px" },
{ field: "Description", title: "Description", width: "50px" },
{ field: "Price", title: "Price", width: "50px" },
{ field: "Active", title: "Active", template: '<input type="checkbox" disabled="disabled" #= Active ? checked="checked":"" # class="chkbx" />', width: "20px" },
{ command: [{ name: "edit", text: "Modifica" }], title: "", width: "172px" }
],
editable: "inline"
};
How can i make the "Price" field readonly on some condition? I must test a variable and if it is true i want the Price field readonly otherwise writable.
I have tried to add in the "thingsOptions" function:
edit: function (e) {
if(myvar == true)
e.container.find("input[name=Price]").enable(false);
}
But id doesn't work (undefined reference).
Try to use:
edit: function (e) {
if(myvar == true)
$("input[name=Price]").attr("readonly", true);
} else {
$("input[name=Price]").attr("readonly", false);
}
}
Inside the edit function of the grid just manipulate the condition the way you want to use. For closing the cell you can use this.closeCell();
edit: function (e) {
//Size will be editable only when the Area is not empty
if(e.container.find(“input”).attr(“name”) == ‘Price’) {
//Below statement will close the cell and stops the editing.
if(myvar == true){
this.closeCell();
}
}
}
For more info have a look here
columns: [{
editable: false,
field: "Id",
title: "Id",
width: 50,
editor: idEditor,
}, {
title: "Name",
field: "Name",
width: 100
}, {
command: ["edit", "destroy"],
title: " ",
width: "250px"
}]
function idEditor(container, options) {
container.append(options.model.Id);
}