Loading selected GridView Item in Popup using CallBacks with ASP.Net MVC - javascript

I still relatively new to ASP.Net and the concepts of communicating between client and server. I am using DevExpress tools but I believe this issue is more of a misunderstanding of the concept.
I have a GridView within a partial view that is loaded via an Action #Html.Action('MessageGridView'). This works no problem and data is loaded fine with the index and a returned model.
#Html.DevExpress().GridView(settings =>
{
settings.Width = System.Web.UI.WebControls.Unit.Percentage(100);
settings.Name = "preparedMessagesGrid";
settings.CallbackRouteValues = new { Controller = "Messages", Action = "MessagesGridView" };
settings.KeyFieldName = "Id";
settings.SettingsBehavior.AllowSelectByRowClick = true;
settings.SettingsBehavior.AllowSelectSingleRowOnly = true;
settings.ClientSideEvents.Init = "GridViewInit";
settings.ClientSideEvents.SelectionChanged = "OnSelectionChanged";
settings.ClientSideEvents.BeginCallback = "OnBeginCallback";
settings.SettingsBehavior.AllowEllipsisInText = true;
settings.PreRender = settings.Init = (sender, e) =>
{
MVCxGridView gridView = sender as MVCxGridView;
gridView.Selection.SelectAll();
};
settings.Columns.Add("Name");
settings.Columns.Add("Description");
}).Bind(Model.preparedMessages).GetHtml()
What I am trying to achieve is when the user selects the row I wish the data to be loaded into the popup control when clicked. Is there a way I can set the parameters dynamically for the popup control callback?
#Html.DevExpress().PopupControl(settings =>
{
settings.Name = "pcModalMode";
settings.Width = 100;
settings.AllowDragging = true;
settings.CloseAction = CloseAction.CloseButton;
settings.CloseOnEscape = true;
settings.PopupAnimationType = AnimationType.None;
settings.HeaderText = "Login";
settings.Modal = true;
settings.PopupHorizontalAlign = PopupHorizontalAlign.WindowCenter;
settings.PopupVerticalAlign = PopupVerticalAlign.WindowCenter;
settings.CallbackRouteValues = new { Controller = "Messages", Action = "Load", new { id = THIS NEEDS TO BE SELECTED ID VALUE} };
settings.LoadContentViaCallback = LoadContentViaCallback.OnFirstShow;
}).GetHtml()
It works if I set the value static so I'm one step away from getting this working. What I have researched is that I can get the values from the GridView in javascript using the selection changed event.
function OnSelectionChanged(s, e) {
s.GetSelectedFieldValues("Id", GetSelectedFieldValueCallback);
}
I can then retrieve this value but can I set this to my popup control or am I misunderstanding being relatively new and possibly I could do this server side for when the ViewGrid callback is performed, then set it server side with a session of some sort?

You're just one step away to get currently selected grid value with this function:
function OnSelectionChanged(s, e) {
s.GetSelectedFieldValues('Id', GetSelectedFieldValueCallback);
}
What you need to do is declaring GetSelectedFieldValueCallback method as this (I got from a test that selectedValue contains array with single value for single grid row selection, use zero index to assign the value):
var id; // a global variable set to hold selected row key value from grid
function GetSelectedFieldValueCallback(selectedValue) {
if (selectedValue.length == 0)
return;
id = parseInt(selectedValue[0]);
pcModalMode.PerformCallback();
}
Then setting BeginCallback on PopupControl helper as given below, note that for DevExpress HTML helpers you can use customArgs in client-side to pass action method parameters instead of using CallbackRouteValues with id parameter:
#Html.DevExpress().PopupControl(settings =>
{
settings.Name = "pcModalMode";
// other stuff
settings.CallbackRouteValues = new { Controller = "Messages", Action = "Load" };
settings.ClientSideEvents.BeginCallback = "OnPopUpBeginCallback";
settings.ClientSideEvents.EndCallback = "OnPopUpEndCallback";
// other stuff
}).GetHtml()
// JS function for popup callback
function OnPopUpBeginCallback(s, e) {
e.customArgs["id"] = id; // this sends 'id' as action method parameter to `Load` action
}
// Optional end callback
function OnPopUpEndCallback(s, e) {
if (!pcModalMode.IsVisible())
pcModalMode.Show();
}
Finally, let's putting them all together in view & controller code:
View
<!-- View page -->
<script type="text/javascript">
var id;
function OnSelectionChanged(s, e) {
s.GetSelectedFieldValues('Id', GetSelectedFieldValueCallback);
}
function GetSelectedFieldValueCallback(selectedValue) {
if (selectedValue.length == 0)
return;
id = parseInt(selectedValue[0]);
pcModalMode.PerformCallback();
}
function OnPopUpBeginCallback(s, e) {
e.customArgs["id"] = id;
}
function OnPopUpEndCallback(s, e) {
if (!pcModalMode.IsVisible())
pcModalMode.Show();
}
</script>
GridView (partial view)
#Html.DevExpress().GridView(settings =>
{
settings.Name = "preparedMessagesGrid";
// other stuff
settings.ClientSideEvents.SelectionChanged = "OnSelectionChanged";
}).Bind(Model.preparedMessages).GetHtml()
Popup (partial view)
#Html.DevExpress().PopupControl(settings =>
{
settings.Name = "pcModalMode";
// other stuff
settings.CallbackRouteValues = new { Controller = "Messages", Action = "Load" };
settings.ClientSideEvents.BeginCallback = "OnPopUpBeginCallback";
settings.ClientSideEvents.EndCallback = "OnPopUpEndCallback";
// other stuff
}).GetHtml()
Controller
public class Messages : Controller
{
public ActionResult MessagesGridView()
{
// grid view populating data code lines here
return PartialView("_GridView", data);
}
public ActionResult Load(int id)
{
// code lines to find ID here
return PartialView("_ModalPopup", model);
}
}
References:
(1) Display GridView Row Details in PopupControl Window
(2) How to display detail data within a popup window (MVC)
(3) ASPxClientGridView.GetSelectedFieldValues (DevExpress Documentation)
(4) MVCxClientBeginCallbackEventArgs.customArgs (DevExpress Documentation)

Related

template sdk for creating templates using javascript/jquery

I am trying to create an sdk in javscript/jquery for creating templates based on user input, such as the type of templates - profile template, dialog template. These templates require data from an ajax call for their creation.
User Input should include some config param and type of templates.
Since I don't have much experience creating sdk's, I am trying to create a scalable and flexible sdk which can adopt some more functionalities and properties in future.
I am stuck on the problem that what is the basic and best way to create an javascript/jquery sdk?
var dialogTemplate , var = template2 I have added sample templates. The requirement is when user passes template/templates name in tmpConfig.config.type create that particular template/templates by fetching their data simultaneously for each template/templates.Suppose, when call 'dialog template' create dialog template. when call 'dialog template' and 'template2' create both and append it. These template name can be send in array in config.
Below is what I have tried:-
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="mySDK.js"></script>
</head>
<body>
// container for templates
<div id="tmpBox"></div>
</body>
<script type="text/javascript">
const tmpConfig = {
config: {
type: ['dialog','template2',...,...,....]
},
boxId: '#tmpBox'
};
var mySDK= new tmpSDK(tmpConfig );
mySDK.createtemplate(); // create template
</script>
</html>
mySDK.js
function tmpSDK(confg){
// implementation of sdk
this.config = confg;
}
tmpSDK.prototype.createtemplate= function(){
var idsToAppendTemplate = this.config.boxId;
var templateTypes = this.config.type;
// checking number of templates to create
for(var i=0 ; i < templateTypes.length; i++){
if(templateTypes === 'dialog'){
createDialog(idsToAppendTemplate )
}else if(templateTypes === 'template2'){
createTemplate2 (idsToAppendTemplate )
}
}
}
function getData(ajaxConfig){
$.ajax(){
return data;
}
}
// different templates html defined below:-
var dialogTemplate = function(data){
// play with data
var html = '<div class='dialog-template'>MY Dialog Template</div>';
return html;
}
var template2 = function(data){
// play with data
var html = '<div class='template2'>MY Template2</div>';
return html;
}
tmpSDK.prototype.createDialog = function(id){
var ajaxConfig = {
'url' : 'http://dialog endponts/',
....
}
var data = getData(ajaxConfig);
$(id).append(dialogTemplate(data)); // var dialogTemplate
}
tmpSDK.prototype.createTemplate2 = function(id){
var ajaxConfig = {
'url' : 'http://template2endponts/',
....
}
var data = getData(ajaxConfig);
$(id).append(template2(data) ); //// var template2
}
Please, consider to create your sdk as jQuery module with Class using.
(function ( $ ) {
$.fn.mySdk = function(options) {
const element = $(this);
const sdk = new MySdk(options, element);
element.data('plugin-my-sdk', sdk);
return $(this);
};
$.fn.getMySdk = function() {
const element = $(this);
return element.data('plugin-my-sdk');
};
class MySdk {
constructor(options, element) {
this.element = element;
this.settings = $.extend({
type: 'dialog',
}, options );
this.fetchTemplate().done(this.applyTemplate.bind(this));
}
fetchTemplate() {
return $.post({
url: `${document.location.origin}/your-endpoint-for-getting-template`,
data: {
'id': this.element.attr('id'),
'type': this.settings.type
}
});
}
applyTemplate(template) {
this.element.html(template);
}
apiMethod() {
const yourElement = this.element;
const yourElementId = this.element.attr('id');
const yourType = this.settings.type;
}
}
}( jQuery ));
// This snippet - is example of using your sdk
jQuery(function ($) {
const element = $('#tmpBox');
element.mySdk({
type: 'dialog'
});
const sdk = element.getMySdk();
sdk.apiMethod();
});
What this snippet do?
Wrap jQuery function for creating a not global scope and for avoiding jQuery conflict with $ function name
Uses MySdk class for the element.
This works for the case when there is only one jquery element in collection taking by the selector. In this case - const element = $('#tmpBox'); is taking only one element.
This snippet
this.settings = this.settings = $.extend({
type: 'dialog',
}, options );
merges default options with your options. If there is no option in your options object - then default option will be used
If you need to use jquery collection
For example, your sdk element is $('.tmpBox') where is there are more than 1 element - please, consider to use in mySdk each function for init every element.
const elements = $(this);
element.each(function(){
// init for every element;
})

Loading partial view depending on dropdown selection in MVC

I apologize I am still fairly new to MVC. I currently have a dropdownlist with some options. What I would like to do is depending on the dropdownlist value that I select then I should be able to render a partial view. I want the partial view to load as soon as the user selects from the dropdownlist.
Also, I am able to render my partial view but it's not returning what I need. When I select from the dropdownlist it does not take the functionID..it just returns all of the items regardless of the functionID.
I want the partial view to render based off the functionID.
Thank you very much. Any help is very much appreciated it.
Main View
#Html.DropDownListFor(m => m.FunctionID, new
SelectList(Model.functionList, "FunctionID", "Name"), "Select
Function", new {#id="id"})
<div id="partialPlaceHolder">
</div>
Partial View
#foreach (var items in Model.itemTypeList)
{
<pre> #items.Definitions</pre>
}
Controller
[HttpGet]
public ActionResult ViewOverview()
{
List<Function> functionList;
List<ItemType> itemTypeList;
using (BusinessLogic BLL = new BusinessLogic())
{
functionList = BLL.GetFunctionList();
itemTypeList = BLL.GetItemTypesList();
}
Words viewModel = new Words();
MetricDefinitions(viewModel);
return View(viewModel);
}
[HttpGet]
public ActionResult GetWords()
{
List<Function> functionList;
List<ItemType> itemTypeList;
using (BusinessLogic BLL = new BusinessLogic())
{
functionList = BLL.GetFunctionList();
itemTypeList = BLL.GetItemTypesList();
}
Words viewModel = new Words()
{
itemTypeList = itemTypeList,
functionList = functionList
};
return PartialView("_ViewWords", viewModel);
}
private void MetricDefinitions(Words model)
{
List<Function> functionList;
List<ItemType> itemTypeList;
using (BusinessLogic BLL = new BusinessLogic())
{
functionList = BLL.GetFunctionList();
itemTypeList = BLL.GetItemTypesList();
}
model.functionList = functionList;
model.itemTypeList = itemTypeList;
}
javascript
$(document).ready(function () {
$('#id').change(function () {
var selectedID = $(this).val();
$.get('/Home/GetWords/' + selectedID, function (data) {
$('#partialPlaceHolder').html(data);
/* little fade in effect */
$('#partialPlaceHolder').fadeIn('fast');
});
});
});
I have added NetFiddle. It works here
Can you try to add selectedItem param into action and use jquery .load() function to get partial result into your target element.
[HttpGet]
public ActionResult GetWords(int selectedItem) // add your selectedVal value in controller
{
.....
}
jquery
// it is going to parse partial view into target div
$("#id").on("change", function(){
var url = '#Url.Action("GetWords", "Home")' + "?selectedItem=" + $(this).val();
$("#partialPlaceHolder").load(url, function(){
console.log("It worked");
$('#partialPlaceHolder').fadeIn('fast');
})
})

Text to Html conversion in Sharepoint 2010

I have a SharePoint 2010 list of around 198 items. For the first 30 items Text to Html Javascript function successfully converts text code to Html but when I am trying to select next 31 items and go ahead using the pagination the function does not able to convert Html and display only text codes. Does anyone please who have the code handy to make this work? Below is the code used in SharePoint 2010. Thank you.
<script type="text/javascript">
function TextToHTML(NodeSet, HTMLregexp) {
var CellContent = "";
var i=0;
while (i < NodeSet.length){
try {
CellContent = NodeSet[i].innerText || NodeSet[i].textContent;
if (HTMLregexp.test(CellContent)) {NodeSet[i].innerHTML = CellContent;}
}
catch(err){}
i=i+1;
}
}
// Calendar views
var regexpA = new RegExp("\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*");
TextToHTML(document.getElementsByTagName("a"),regexpA);
// List views
var regexpTD = new RegExp("^\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*$");
TextToHTML(document.getElementsByTagName("TD"),regexpTD);
// This function is call continuesly every 100ms until the length of the main field changes
// after which the convert text to HTML is executed.
//
var postElemLength = 0;
function PostConvertToHtml()
{
if (postElemLength == document.getElementsByTagName("TD").length)
{
setTimeout(PostConvertToHtml,100);
}
else
{
var regexpTD = new RegExp("^\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*$");
TextToHTML(document.getElementsByTagName("TD"),regexpTD);
}
}
// Grouped list views
ExpGroupRenderData = (function (old) {
return function (htmlToRender, groupName, isLoaded) {
var result = old(htmlToRender, groupName, isLoaded);
var regexpTD = new RegExp("^\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*$");
TextToHTML(document.getElementsByTagName("TD"),regexpTD);
// start the periodic callback to check when the element has been changed
if(isLoaded == 'false')
{
postElemLength = document.getElementsByTagName("TD").length;
setTimeout(PostConvertToHtml,100);
}
};
})(ExpGroupRenderData);
// Preview pane views
if (typeof(showpreview1)=="function") {
showpreview1 = (function (old) {
return function (o) {
var result = old(o);
var regexpTD = new RegExp("^\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*$");
TextToHTML(document.getElementsByTagName("TD"),regexpTD);
};
})(showpreview1);
}</script>
Below is the generated text code which needs to be converted to Html. Thanks.
="<div style='position:relative;display:inline-block;width:100%;'>
<div style='width:100%;display:inline-block;text-align:center;border:1px solid "&Project_Status_clr&";position:absolute;color:"&Project_Status_clr&";'> "&Project_Status&"
</div>
<div style='display:inline-block;width: 100%;background-color:"&Project_Status_clr&";text-align:center;border:1px solid;z-index:-1;filter:alpha(opacity=20);opacity:0.2;'>"&Project_Status&"
</div>
</div>"
When generating a string of HTML in a calculated column in SharePoint 2010, you can change the calculated column's value type to "Number" to get the HTML to render in the list view.

AngularJS select items not resetting to first / default value

I'm at my wits end! In angular I've got a controller and a view.
There are 2 dropdowns on the page which need to reset to default once the restart button has been clicked.
I can set the value of the boxes as they render by pushing a "select" option into the collection inside the controller. However, when the reset button is pressed, which runs the init() method again, the dropdowns should be set back to the first value. This doesn't occur, the values for $scope.selectedYear and $scope.selectedReport remain as they did before the reset button was pressed.
This is the full code for the controller
function TreeReportsCHLController($scope, $q, $routeParams, reportsDashboardResource, navigationService, notificationsService, dialogService, entriesManageDashboardResource, $timeout) {
// Methods
var generalError = function () {
notificationsService.error("Ooops", "There was an error fetching the data");
$scope.actionInProgress = false;
}
// Scope
$scope.selectedYear = "";
$scope.init = function () {
$scope.hasCompleted = false;
$scope.actionInProgress = false;
$scope.yearSelected = false;
$scope.reportTypes = ["Choose", "Entered", "ShortListed", "Winner", "Recieved"];
$scope.selectedReport = "";
$scope.entryYears = new Array();
$scope.entryYears.push("Choose a Year");
entriesManageDashboardResource.getEntryYears().then(function (response) {
angular.forEach(response, function (value, key) {
$scope.entryYears.push(value);
});
});
$scope.selectedYear = $scope.entryYears[0];
$scope.selectedReport = $scope.reportTypes[0];
};
$scope.yearHasSelected = function(selectedYear) {
$scope.yearSelected = true;
$scope.selectedYear = selectedYear;
};
$scope.generateFile = function (selectedReport) {
$scope.actionInProgress = true;
var reportDetail = {
entryYear: $scope.selectedYear,
chosenEntryStatus: selectedReport
};
reportsDashboardResource.generateEntriesReportDownloadLink(reportDetail).then(function (response) {
if (response.Successful) {
$scope.hasCompleted = true;
} else {
notificationsService.error("Ooops", response.ErrorMessage);
}
$scope.actionInProgress = false;
}, generalError);
};
$scope.restart = function () {
$scope.init();
}
// Initialise Page
$scope.init();
}
angular.module("umbraco").controller("ReportsDashboardController", TreeReportsCHLController)
this is the code with the dropdowns in it;
<table>
<tr>
<td>Get a report for year: {{selectedYear}}</td>
<td><select ng-model="selectedYear" ng-change="yearHasSelected(selectedYear)" ng-options="year for year in entryYears" no-dirty-check></select></td>
</tr>
<tr ng-show="!hasCompleted && yearSelected">
<td>
Get Report Type:
</td>
<td>
<select ng-model="selectedReport" ng-change="generateFile(selectedReport)" ng-options="status for status in reportTypes" no-dirty-check ng-disabled="actionInProgress"></select>
</td>
</tr>
</table>
I've also done a further test where I simply set $scope.selectedYear to $scope.entryYears[0] within the reset method. When I console.log $scope.selectedYear here, the value confirms it has been changed, but strangely where I've outputted the $scope.selectedYear / {{selectedYear}} to the page for testing, this does not update. It's almost as though the binding between the controller and the view isn't occuring.
Any help?
Thank-you.
Here's a working plunk that is somewhat stripped down since I didn't have access to of the services that your are injecting into your controller. The changes I made in the controller are:
First,
$scope.entryYears = new Array();
becomes
$scope.entryYears = [];
as this is the preferred way to declare an array in js.
Second, I removed $scope.apply() that was wrapping
$scope.selectedYear = $scope.entryYears[0];
$scope.selectedReport = $scope.reportTypes[0];
as this was causing infinite digest cycles.

Make cell readonly in Kendo Grid if condition is met

Let's say I have a data like this:
[
{ID: 1, SomeForeignKeyID: 4, IsFkEnabled: true},
{ID: 2, SomeForeignKeyID: 9, IsFkEnabled: false}
]
Kendo Grid is using this data:
columns.Bound(m => m.ID);
columns.ForeignKey(p => p.SomeForeignKeyID, ViewBag.ForeignKeys as IEnumerable<object>, "Value", "Name");
Here's the problem: how to make ForeignKey column editable, but only in rows, where IsFkEnabled == true? Edit mode is InCell.
Notes:
this solution works for in-cell editing only (inline or popup editing
require a different approach)
the first approach can lead to unwanted visual effects (grid
jumping) under certain circumstances; if you experience that, I
recommend approach #2
approach #2 may not work if you want to use the MVC wrappers (although it may be possible to extend Kendo.Mvc.UI.Fluent.GridEventBuilder); in that case, you'll need to bind the edit handler in JS
Approach #1
Use the grid's edit event and then do something like this:
$("#grid").kendoGrid({
dataSource: dataSource,
height: "300px",
columns: columns,
editable: true,
edit: function (e) {
var fieldName = e.container.find("input").attr("name");
// alternative (if you don't have the name attribute in your editable):
// var columnIndex = this.cellIndex(e.container);
// var fieldName = this.thead.find("th").eq(columnIndex).data("field");
if (!isEditable(fieldName, e.model)) {
this.closeCell(); // prevent editing
}
}
});
/**
* #returns {boolean} True if the column with the given field name is editable
*/
function isEditable(fieldName, model) {
if (fieldName === "SomeForeignKeyID") {
// condition for the field "SomeForeignKeyID"
// (default to true if defining property doesn't exist)
return model.hasOwnProperty("IsFkEnabled") && model.IsFkEnabled;
}
// additional checks, e.g. to only allow editing unsaved rows:
// if (!model.isNew()) { return false; }
return true; // default to editable
}
Demo here (updated for Q1 2014)
To use this via the MVC fluent syntax, simply give the anonymous edit function above a name (e.g. onEdit):
function onEdit(e) {
var fieldName = e.container.find("input").attr("name");
// alternative (if you don't have the name attribute in your editable):
// var columnIndex = this.cellIndex(e.container);
// var fieldName = this.thead.find("th").eq(columnIndex).data("field");
if (!isEditable(fieldName, e.model)) {
this.closeCell(); // prevent editing
}
}
and reference it like this:
#(Html.Kendo().Grid()
.Name("Grid")
.Events(events => events.Edit("onEdit"))
)
The disadvantage to this is that the editor gets created first before the edit event is triggered, which can sometimes have undesirable visual effects.
Approach #2
Extend the grid by overriding its editCell method with a variation that triggers a beforeEdit event; for that to work with grid options, you'll also need to override the init method:
var oEditCell = kendo.ui.Grid.fn.editCell;
var oInit = kendo.ui.Grid.fn.init;
kendo.ui.Grid = kendo.ui.Grid.extend({
init: function () {
oInit.apply(this, arguments);
if (typeof this.options.beforeEdit === "function") {
this.bind("beforeEdit", this.options.beforeEdit.bind(this));
}
},
editCell: function (cell) {
var that = this,
cell = $(cell),
column = that.columns[that.cellIndex(cell)],
model = that._modelForContainer(cell),
event = {
container: cell,
model: model,
field: column.field
};
if (model && this.trigger("beforeEdit", event)) {
// don't edit if prevented in beforeEdit
if (event.isDefaultPrevented()) return;
}
oEditCell.call(this, cell);
}
});
kendo.ui.plugin(kendo.ui.Grid);
then use it similar to #1:
$("#grid").kendoGrid({
dataSource: dataSource,
height: "300px",
columns: columns,
editable: true,
beforeEdit: function(e) {
var columnIndex = this.cellIndex(e.container);
var fieldName = this.thead.find("th").eq(columnIndex).data("field");
if (!isEditable(fieldName, e.model)) {
e.preventDefault();
}
}
});
The difference of this approach is that the editor won't get created (and focused) first. The beforeEdit method is using the same isEditable method from #1.
See a demo for this approach here.
If you want to use this approach with MVC wrappers but don't want / can't extend GridEventBuilder, you can still bind your event handler in JavaScript (place below the grid MVC initializer):
$(function() {
var grid = $("#grid").data("kendoGrid");
grid.bind("beforeEdit", onEdit.bind(grid));
});
None of these approaches worked for me. A very simple implentation looks like this
edit: function (e) {
e.container.find("input[name='Name']").each(function () { $(this).attr("disabled", "disabled") });
}
Where edit is part of the kendo grid declaration and Name is the actual name of the field.
Please try with the below code snippet.
VIEW
<script type="text/javascript">
function errorHandler(e) {
if (e.errors) {
var message = "Errors:\n";
$.each(e.errors, function (key, value) {
if ('errors' in value) {
$.each(value.errors, function () {
message += this + "\n";
});
}
});
alert(message);
}
}
function onGridEdit(arg) {
if (arg.container.find("input[name=IsFkEnabled]").length > 0) {
arg.container.find("input[name=IsFkEnabled]").click(function () {
if ($(this).is(":checked") == false) {
}
else {
arg.model.IsFkEnabled = true;
$("#Grid").data("kendoGrid").closeCell(arg.container);
$("#Grid").data("kendoGrid").editCell(arg.container.next());
}
});
}
if (arg.container.find("input[name=FID]").length > 0) {
if (arg.model.IsFkEnabled == false) {
$("#Grid").data("kendoGrid").closeCell(arg.container)
}
}
}
</script>
<div>
#(Html.Kendo().Grid<MvcApplication1.Models.TestModels>()
.Name("Grid")
.Columns(columns =>
{
columns.Bound(p => p.ID);
columns.Bound(p => p.Name);
columns.Bound(p => p.IsFkEnabled);
columns.ForeignKey(p => p.FID, (System.Collections.IEnumerable)ViewData["TestList"], "Value", "Text");
})
.ToolBar(toolBar => toolBar.Save())
.Editable(editable => editable.Mode(GridEditMode.InCell))
.Pageable()
.Sortable()
.Scrollable()
.Filterable()
.Events(e => e.Edit("onGridEdit"))
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.ServerOperation(false)
.Events(events => events.Error("errorHandler"))
.Model(model =>
{
model.Id(p => p.ID);
model.Field(p => p.ID).Editable(false);
})
.Read(read => read.Action("ForeignKeyColumn_Read", "Home"))
.Update(update => update.Action("ForeignKeyColumn_Update", "Home"))
)
)
</div>
MODEL
namespace MvcApplication1.Models
{
public class TestModels
{
public int ID { get; set; }
public string Name { get; set; }
public bool IsFkEnabled { get; set; }
public int FID { get; set; }
}
}
CONTROLLER
public class HomeController : Controller
{
public ActionResult Index()
{
List<SelectListItem> items = new List<SelectListItem>();
for (int i = 1; i < 6; i++)
{
SelectListItem item = new SelectListItem();
item.Text = "text" + i.ToString();
item.Value = i.ToString();
items.Add(item);
}
ViewData["TestList"] = items;
return View();
}
public ActionResult ForeignKeyColumn_Read([DataSourceRequest] DataSourceRequest request)
{
List<TestModels> models = new List<TestModels>();
for (int i = 1; i < 6; i++)
{
TestModels model = new TestModels();
model.ID = i;
model.Name = "Name" + i;
if (i % 2 == 0)
{
model.IsFkEnabled = true;
}
model.FID = i;
models.Add(model);
}
return Json(models.ToDataSourceResult(request));
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ForeignKeyColumn_Update([DataSourceRequest] DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<TestModels> tests)
{
if (tests != null && ModelState.IsValid)
{
// Save/Update logic comes here
}
return Json(ModelState.ToDataSourceResult());
}
}
If you want to download demo then click here.
The simplest way is to use the dataBound event to conditionally apply one of the special CSS classes to the cells that the grid ignore for editing:
http://dojo.telerik.com/izOka
dataBound: function(e) {
var colIndex = 1;
var rows = this.table.find("tr:not(.k-grouping-row)");
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
var model = this.dataItem(row);
if (!model.Discontinued) {
var cell = $($(row).find("td")[colIndex]);
cell.addClass("k-group-cell");
}
}
},
Another approach is to use your own "editor" function for column definition that provides either an input element or a plain div depending on your condition.
Use Template column instead of Bound column
columns.Template(#<text></text>).ClientTemplate("#=Id#").Title("Id");

Categories

Resources