Reputation: 863
I'm working on a piece of code to prevent a Telerik Grid from contacting the server to save a duplicate piece of data. Here is what I have thus far.
View
@(Html.Telerik().Grid<CategoryModel.CategoryUnitsModel>()
.Name("categoryunits-grid")
.DataKeys(keys =>
{
keys.Add(x => x.Id);
keys.Add(x => x.CategoryId);
keys.Add(x => x.UnitId);
})
.DataBinding(dataBinding =>
{
dataBinding.Ajax()
.Select("CategoryUnitsList", "Category", new { categoryId = Model.Id })
.Insert("CategoryUnitsInsert", "Category", new { categoryId = Model.Id })
.Update("CategoryUnitsInsert", "Category", new { categoryId = Model.Id })
.Delete("CategoryUnitsDelete", "Category", new { categoryId = Model.Id });
})
.Columns(columns =>
{
columns.Bound(x => x.UnitId)
.Visible(false);
columns.Bound(x => x.UnitText);
columns.Command(commands =>
{
commands.Edit();
commands.Delete();
})
.Width(100);
})
.ToolBar(commands => commands.Insert())
.Pageable(settings => settings.PageSize(gridPageSize).Position(GridPagerPosition.Both))
.ClientEvents(events => events.OnRowDataBound("onRowDataBound"))
.ClientEvents(events => events.OnSave("onSave"))
.EnableCustomBinding(true))
<script type="text/javascript">
function onRowDataBound(e) {
$(e.row).find('a.t-grid-edit').remove(); //remove Delete button
}
function onSave(e) {
$.getJSON('@Url.Action("CheckForCategoryUnit", "Category")', { categoryId: $("#Id").val(), unitId: $("#UnitText").val() }, function (data) {
if (data) {
alert("Units may not be added twice for a category");
e.preventDefault();
}
else {
}
});
}
</script>
Controller
[HttpPost, GridAction(EnableCustomBinding = true)]
public ActionResult CategoryUnitsList(GridCommand command, int categoryId)
{
if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog))
return AccessDeniedView();
var categoryUnits = _categoryService.GetCategoryUnits(categoryId, command.Page - 1 , command.PageSize);
var categoryUnitsModel = PrepareCategoryUnitsModel(categoryUnits);
var model = new GridModel<CategoryModel.CategoryUnitsModel>
{
Data = categoryUnitsModel,
Total = categoryUnitsModel.Count
};
return new JsonResult
{
Data = model
};
}
public ActionResult CheckForCategoryUnit(int categoryId, int unitId)
{
var categoryUnit = _categoryService.GetCategoryUnitByCategoryIdAndUnitId(categoryId, unitId);
return Json(categoryUnit != null, JsonRequestBehavior.AllowGet);
}
[GridAction(EnableCustomBinding = true)]
public ActionResult CategoryUnitsInsert(GridCommand command, CategoryModel.CategoryUnitsModel model)
{
if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog))
return AccessDeniedView();
var categoryUnit = new CategoryUnits
{
UnitId = Int32.Parse(model.UnitText),
CategoryId = model.CategoryId
};
_categoryService.InsertCategoryUnit(categoryUnit);
return CategoryUnitsList(command, model.CategoryId);
}
At this point and time, I get an alert that I am hitting within my ajax. However, the e.preventDefault() is not stopping the server from going on ahead and saving my data. I've tried several different things concerning this issue, including:
return false, e.stop(), e.returnValue = false, e.stopPropagation().
None have worked thus far. If anyone has any ideas, I'm open to them. The combination of OS and browser I have are Windows XP and IE8. Just adding in case that would help. Thanks.
Kindest Regards, Chad Johnson
Upvotes: 1
Views: 1188
Reputation: 863
Okay guys, I came up with a completely different solution. However, I do have one other issue that I want to ask about.
First off, here is what I did. Instead of catching when I would repeat data, I instead removed that data from the dropdownlist so that the option never happens. Aside from that, I dynamically load the dropdownlist now, thus keeping the data fresh and allowing me to keep from having duplicates.
View
var gridPageSize = EngineContext.Current.Resolve<Nop.Core.Domain.Common.AdminAreaSettings>().GridPageSize;
<table class="adminContent">
<tr>
<td>
@(Html.Telerik().Grid<CategoryModel.CategoryUnitsModel>()
.Name("categoryunits-grid")
.DataKeys(keys =>
{
keys.Add(x => x.Id);
keys.Add(x => x.CategoryId);
keys.Add(x => x.UnitId);
})
.DataBinding(dataBinding =>
{
dataBinding.Ajax()
.Select("CategoryUnitsList", "Category", new { categoryId = Model.Id })
.Insert("CategoryUnitsInsert", "Category", new { categoryId = Model.Id })
.Update("CategoryUnitsInsert", "Category", new { categoryId = Model.Id })
.Delete("CategoryUnitsDelete", "Category", new { categoryId = Model.Id });
})
.Columns(columns =>
{
columns.Bound(x => x.UnitId)
.Visible(false);
columns.Bound(x => x.UnitText);
columns.Command(commands =>
{
commands.Edit();
commands.Delete();
})
.Width(100);
})
.ToolBar(commands => commands.Insert())
.Pageable(settings => settings.PageSize(gridPageSize).Position(GridPagerPosition.Both))
.ClientEvents(events => events.OnRowDataBound("onRowDataBound"))
.ClientEvents(events => events.OnEdit("onEdit"))
.EnableCustomBinding(true))
<script type="text/javascript">
function onRowDataBound(e) {
$(e.row).find('a.t-grid-edit').remove(); //remove Delete button
}
function onEdit(e) {
$.getJSON('@Url.Action("LoadAvailableUnits", "Category")', { categoryId: $("#Id").val() }, function (data) {
var ddl = $("#UnitText").data("tDropDownList");
if (data.length > 0) {
ddl.dataBind(data);
ddl.reload();
}
else {
$('a[class="t-button t-grid-cancel"]').click();
alert("There are no Units left to select from");
}
});
}
</script>
EditorTemplates/CategoryUnit.cshtml
@using Telerik.Web.Mvc.UI;
@Html.Telerik().DropDownList().Name("UnitText")
My Model is the same.
Controller
[HttpPost, GridAction(EnableCustomBinding = true)]
public ActionResult CategoryUnitsList(GridCommand command, int categoryId)
{
if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog))
return AccessDeniedView();
var categoryUnits = _unitsService.GetCategoryUnits(categoryId, command.Page - 1, command.PageSize);
var categoryUnitsModel = PrepareCategoryUnitsModel(categoryUnits);
var model = new GridModel<CategoryModel.CategoryUnitsModel>
{
Data = categoryUnitsModel,
Total = categoryUnitsModel.Count
};
return new JsonResult
{
Data = model
};
}
public JsonResult LoadAvailableUnits(int categoryId)
{
var categoryUnits = _unitsService.GetAvailableUnits(categoryId);
var categoryUnitsModel = PrepareAvailableUnitsInModel(categoryUnits);
var returnData = new SelectList(categoryUnitsModel, "UnitId", "UnitText");
return Json(returnData, JsonRequestBehavior.AllowGet);
}
[GridAction(EnableCustomBinding = true)]
public ActionResult CategoryUnitsInsert(GridCommand command, CategoryModel.CategoryUnitsModel model)
{
if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog))
return AccessDeniedView();
var searchForEntry = _unitsService.GetCategoryUnitByCategoryIdAndUnitId(model.CategoryId, Int32.Parse(model.UnitText));
if (searchForEntry != null)
{
return CategoryUnitsList(command, model.CategoryId);
}
var categoryUnit = new CategoryUnits
{
UnitId = Int32.Parse(model.UnitText),
CategoryId = model.CategoryId
};
_unitsService.InsertCategoryUnit(categoryUnit);
return CategoryUnitsList(command, model.CategoryId);
}
[GridAction(EnableCustomBinding = true)]
public ActionResult CategoryUnitsDelete(GridCommand command, CategoryModel.CategoryUnitsModel model, int id)
{
if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog))
return AccessDeniedView();
var categoryId = model.CategoryId;
_unitsService.DeleteCategoryUnit(model.CategoryId, id);
return CategoryUnitsList(command, categoryId);
}
My new issue is the paging does not work. I'm unsure why it doesn't since I haven't really messed with it. I suspect it's something to do with the way I'm loading the grid. Any help would be appreciated.
Upvotes: 0
Reputation: 863
Thanks for the responses so far. I did try e.returnValue also but it failed like the others unfortuantely, Nathalie.
I've actually come up with a solution similar to what IronMan84 had.
Instead of using OnSave, I waited till during the Insert on my Controller to do the check for duplicate data. Here is what I came up with:
Controller:
[GridAction(EnableCustomBinding = true)]
public ActionResult CategoryUnitsInsert(GridCommand command, CategoryModel.CategoryUnitsModel model)
{
if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog))
return AccessDeniedView();
var searchForEntry = _categoryService.GetCategoryUnitByCategoryIdAndUnitId(model.CategoryId, Int32.Parse(model.UnitText));
if (searchForEntry != null)
{
var scriptText = "alert('Units may not be added twice for a category');";
return JavaScript(scriptText);
}
var categoryUnit = new CategoryUnits
{
UnitId = Int32.Parse(model.UnitText),
CategoryId = model.CategoryId
};
_categoryService.InsertCategoryUnit(categoryUnit);
return CategoryUnitsList(command, model.CategoryId);
}
I just returned a JavaScript action in the case of duplicate data. Thanks all for the help.
Upvotes: 1
Reputation: 341
There is no preventDefault on events in IE.
Look at this thread: preventdefault alternative for ie8
for IE you have to use: e.returnValue
(e.preventDefault) ? e.preventDefault() : e.returnValue = false;
Upvotes: 0
Reputation: 16137
I'm doing a similar check in my application as well, but I handled it in a different way. Instead of trying to do that alert on saving in AJAX I ended up doing it in my controller. If it found any duplicates it would set a value in the ViewData dictionary. Then, on my main page, I have an alert box that will show up with that value.
if(ViewData.ContainsKey("PopupMessage"))
{
var message = ViewData["PopupMessage"].ToString();
<script type="text/javascript">
window.alert('@message');
</script>
}
Upvotes: 0