This is a migrated thread and some comments may be shown as answers.

Search with Batch Grid

2 Answers 129 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Bill
Top achievements
Rank 1
Bill asked on 21 Aug 2018, 05:18 PM

I have a view that has three comboboxes, a submit button and a batch editable grid.

I'm not sure I have it wired up correctly as most items work.  The problem I am having is that my grid is not refreshed after I update.

Steps

1. Call the Index action which returns an empty list to the grid model(to start)

2. Type in a character into the store combobox, which calls an action to populate, and then select one of them

3. Leave the status combobox at Assigned

4. Click the search button

5. Edit the status of one of the items

6. Click save

Save appears to work but my grid should show one less row based on search criteria(as I changed the status of one of them).

Models

[Table("Images")]
    public class SearchResult
    {
        [Key]
        public int ImageId { get; set; }
        public int StatusId { get; set; }
        public string Name { get; set; }
        [Required]
        public string Description { get; set; }
        public int ProjectId { get; set; }
        public int StoreId { get; set; }
    }

    public class Store
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public class Project
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

View

@model List<PhotoReviewTelerik.Models.SearchResult>
@{
    ViewBag.Title = "PhotoReview";
}

<h2>PhotoReview</h2>
<form method="get" action="@Url.Action("Search")" data-pr-ajax="true" data-pr-target="#searchResults">
    <div class="demo-section k-content">
        <h4>Projects</h4>

        @(Html.Kendo().ComboBox()
            .Name("projects")
            .DataTextField("Name")
            .DataValueField("Id")
            .Placeholder("Select Project")
            .Filter("contains")
            .AutoBind(false)
            .MinLength(1)
            .DataSource(source =>
            {
                source.Read(read =>
                {
                    read.Action("GetProjects", "PhotoReview");
                })
                .ServerFiltering(true);
            })
        )
        <div class="demo-hint">Hint: type at least three characters. For example "pro".</div>
    </div>
    <div class="demo-section k-content">
        <h4>Stores</h4>

        @(Html.Kendo().ComboBox()
            .Name("stores")
            .DataTextField("Name")
            .DataValueField("Id")
            .Placeholder("Select Store")
            .Filter("contains")
            .AutoBind(false)
            .MinLength(1)
            .DataSource(source =>
            {
                source.Read(read =>
                {
                    read.Action("GetStores", "PhotoReview");
                })
                .ServerFiltering(true);
            })
        )
        <div class="demo-hint">Hint: type at least three characters. For example "sto".</div>
    </div>
    @(Html.Kendo().ComboBox()
        .Name("status")
        .BindTo(new List<string>() {
          "Assigned",
          "Reviewed"
        })
        .SelectedIndex(0)
        .Suggest(true)
    )
    <div>
        @(Html.Kendo().Button()
            .Name("primaryTextButton")
            .HtmlAttributes(new { type = "submit", @class = "k-primary" })
            .Content("Search"))

    </div>
</form>
@(Html.Kendo().Grid(Model)
        .Name("Grid")
        .Columns(columns =>
        {
            columns.Bound(p => p.ImageId).Title("ImageId");
            columns.Bound(p => p.StatusId).Title("Status");
            columns.Bound(p => p.Name).Title("Name");
            columns.Bound(p => p.Description).Title("Description");
            columns.Bound(p => p.ProjectId).Title("ProjectId");
            columns.Bound(p => p.StoreId).Title("StoreId");
        })
        .ToolBar(toolbar =>
        {
            toolbar.Save().SaveText("Save").CancelText("Cancel"); // The "save" command saves the changed data items.
        })
        .HtmlAttributes(new { style = "height: 550px;" })
        .NoRecords()
        .Pageable(pageable => pageable
            .Input(true)
            .Numeric(false)
            )
        .Sortable()
        .Scrollable(scr => scr.Height(430))
        .Filterable()
        .DataSource(dataSource => dataSource
            .Ajax()
            .Events(events => events.Error("error_handler"))
            //.Events(events =>
            //{
            //    events.RequestEnd("onRequestEnd"); //I've added this
            //})
            .Batch(true)
            .Model(model =>
            {
                model.Id(i => i.ImageId); // Specify the property which is the unique identifier of the model.
                model.Field(i => i.ImageId).Editable(false); // Make the ImageId property not editable.
                model.Field(i => i.Name).Editable(false); //
                model.Field(i => i.ProjectId).Editable(false);
                model.Field(i => i.StoreId).Editable(false);
            })
            .PageSize(20)
            .ServerOperation(false)
            .Update(update => update.Action("Update", "PhotoReview").Data("additionalData"))
            //.Read(read=>read.Action("Search", "PhotReview").Data("additionalData"))
            )
        .Editable(editable => editable.Mode(GridEditMode.InCell))

)
<script>
    function additionalData() {
        return {
            Project: getUrlParameter('projets'),
            Store: getUrlParameter('stores'),
            Status: getUrlParameter('status')
        };
    }
    function getUrlParameter(sParam) {
        var sPageURL = decodeURIComponent(window.location.search.substring(1)),
            sURLVariables = sPageURL.split('&'),
            sParameterName,
            i;

        for (i = 0; i < sURLVariables.length; i++) {
            sParameterName = sURLVariables[i].split('=');

            if (sParameterName[0] === sParam) {
                return sParameterName[1] === undefined ? true : sParameterName[1];
            }
        }
    };
    function error_handler(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 onRequestEnd(e) {
    //    if (e.type === "update") {
    //        var grid = $('#Grid').data('kendoGrid');
    //        grid.dataSource.read();
    //    }
    //}
</script>

@Html.ValidationSummary(false, "", new { @class = "text-danger" })

Controller

using Kendo.Mvc.Extensions;
using Kendo.Mvc.UI;
using PhotoReviewTelerik.Models;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace PhotoReviewTelerik.Controllers
{
    public class PhotoReviewController : Controller
    {
        private PhotoReviewTelerikDb db = new PhotoReviewTelerikDb();
        // GET: PhotoReview
        public ActionResult Index()
        {
            var model = new List<SearchResult>();
            return View("PhotoReview", model);
        }

        public ActionResult Search(int? projects, int? stores, string status)
        {
            int tempStatus = 0;
            if (status == "Assigned")
                tempStatus = 0;
            else
                tempStatus = 1;
            
            var model = db.SearchResults.ToList();
            model = model.Where(p => p.StatusId == tempStatus).ToList();
            if (projects.HasValue)
                model = model.Where(p => p.ProjectId == (int)projects).ToList();
            if (stores.HasValue)
                model = model.Where(p => p.StoreId == (int)stores).ToList();

            return View("PhotoReview", model);
        }

        public ActionResult Update([DataSourceRequest]DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<SearchResult> results, SearchCriteria criteria)
        {
            // Will keep the updated entitites here. Used to return the result later.
            var entities = new List<SearchResult>();
            if (ModelState.IsValid)
            {
                using (var db = new PhotoReviewTelerikDb())
                {
                    foreach (var result in results)
                    {
                        // Create a new Product entity and set its properties from the posted ProductViewModel.
                        var entity = new SearchResult
                        {
                            ImageId = result.ImageId,
                            StatusId = result.StatusId,
                            Name = result.Name,
                            Description = result.Description,
                            ProjectId = result.ProjectId,
                            StoreId = result.StoreId
                        };
                        // Store the entity for later use.
                        entities.Add(entity);
                        // Attach the entity.
                        db.SearchResults.Attach(entity);
                        // Change its state to Modified so Entity Framework can update the existing product instead of creating a new one.
                        db.Entry(entity).State = EntityState.Modified;
                        // Or use ObjectStateManager if using a previous version of Entity Framework.
                        // northwind.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
                    }
                    // Update the entities in the database.
                    db.SaveChanges();
                }
                //redirect to search
                return RedirectToAction("Search", new { projects = criteria.Project, stores = criteria.Store, status = criteria.Status });
            }
            else
            {
                //return View("PhotoReview", results);
                return Json(entities.ToDataSourceResult(request, ModelState, result => new SearchResult
                {
                    ImageId = result.ImageId,
                    StatusId = result.StatusId,
                    Name = result.Name,
                    Description = result.Description,
                    ProjectId = result.ProjectId,
                    StoreId = result.StoreId
                }));
            }
        }

        public JsonResult GetStores(string text)
        {
            text = text.Trim();
            if(!string.IsNullOrEmpty(text))
            {
                var model = db.Stores.ToList();
                model = model.Where(s => s.Name.ToLower().Contains(text.ToLower())).ToList();
                return Json(model, JsonRequestBehavior.AllowGet);
            }
            return Json(new List<Store>(), JsonRequestBehavior.AllowGet);
        }

        public JsonResult GetProjects(string text)
        {
            text = text.Trim();
            if (!string.IsNullOrEmpty(text))
            {
                var model = db.Projects.ToList();
                model = model.Where(s => s.Name.ToLower().Contains(text.ToLower())).ToList();
                return Json(model, JsonRequestBehavior.AllowGet);
            }
            return Json(new List<Project>(), JsonRequestBehavior.AllowGet);
        }
    }
}

2 Answers, 1 is accepted

Sort by
0
Tsvetina
Telerik team
answered on 23 Aug 2018, 09:16 AM
Hello Bill,

Looking at your description and code, I understand that there is no actual filtering applied on the Grid itself, the data is manually filtered only on submit button click. So when the value is modified in the Grid, there is no logic that would prompt the Grid to filter it out.

Another thing I notice is that your Grid is combining local data binding (direct binding to the returned model) and data editing, which is not a supported scenario. The Grid should use either Ajax() binding using a DataSource Read() configuration like the Batch Editing demo, or server binding and editing (InCell editing does not work with server binding).
If you keep the current binding/editing configuration, you will probably start noticing glitches soon (for example rows disappearing when you cancel editing).

To give you an alternative, I am attaching a sample project where the Grid is filtered using external UI, but the actual filtering happens through the DataSource API. In this way, if an item does get modified, this will be reflected in the filtering results.

Regards,
Tsvetina
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Bill
Top achievements
Rank 1
answered on 23 Aug 2018, 12:18 PM
Thanks Tsvetina, I will check it out!
Tags
Grid
Asked by
Bill
Top achievements
Rank 1
Answers by
Tsvetina
Telerik team
Bill
Top achievements
Rank 1
Share this question
or