1

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

IyaTaisho
  • 863
  • 19
  • 42

4 Answers4

1

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.

IyaTaisho
  • 863
  • 19
  • 42
0

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>
    }
Corey Adler
  • 15,897
  • 18
  • 66
  • 80
  • I see what you mean. The only issue I have with your solution is I don't want to refresh the page and show the popup immediately while keeping the grid's insert open. – IyaTaisho Oct 23 '12 at 19:04
0

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; 
Community
  • 1
  • 1
  • I tried e.returnValue and am now receiving the following error: Error: Array or arguments object expected – IyaTaisho Oct 23 '12 at 18:34
0

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.

IyaTaisho
  • 863
  • 19
  • 42
  • Just a heads up: StackOverflow is not really a "forum", but rather a place for questions and answers. What you've done here is answered your own question with another question. If an answer has helped, but not completely, upvote, then add a comment (like this one) and ask for more information. Also update your original question (the one at the top of the page) with more details on the solution as it progresses. Thanks. – Heretic Monkey Oct 24 '12 at 20:05
  • My apologies. I'll mark this one as done and post another question. – IyaTaisho Oct 25 '12 at 12:06