possible bug with Grid display data after adding a new record

9 posts, 1 answers
  1. Toffer
    Toffer avatar
    34 posts
    Member since:
    Sep 2015

    Posted 07 Oct 2015 Link to this post

    Hello,

    I think I may have a found a bug with how a Grid is displaying data after I've added a record to the table it's bound to.  The meat of the problem is in the javascript I'm using to call dataSource.read() after I've added the record.  My first attempt looked as follows:

    <script>
        function NewDefectFeatureSubmitButtonClick(e)
        {
            var defectFeatureGrid = $("#DefectFeatureGrid").data("kendoGrid");
            var newDefectFeatureTextBox = $("#NewDefectFeatureNameTextBox");
     
            var newDefectFeatureName = newDefectFeatureTextBox.val();
     
            var dummyUrl = '@Url.Action("AddDefectFeature", "DefectFeature", new { name = "--V1--" })';
            var url = dummyUrl.replace("--V1--", newDefectFeatureName);
     
            $.ajax(
            {
                dataType: "json",
                type: "POST",
                url: url
            });
     
            Sleep(1000); // needed to allow the ajax call above to complete before re-reading the datasource
            defectFeatureGrid.dataSource.read();
            newDefectFeatureTextBox.val("");
        }
    </script>

    Notice how I'm passing the parameter via the URL...then calling dataSource.read().  This works just fine and the grid updates with the new record...however I felt this looked "hacky" so I wanted to update it to use the data object in the ajax call....which looks like the following: 

     

    <script>
        function NewDefectFeatureSubmitButtonClick(e)
        {
            var defectFeatureGrid = $("#DefectFeatureGrid").data("kendoGrid");
            var newDefectFeatureTextBox = $("#NewDefectFeatureNameTextBox");
     
            var newDefectFeatureName = newDefectFeatureTextBox.val();
     
            var url = '@Url.Action("AddDefectFeature", "DefectFeature")';
     
            $.ajax(
            {
                data: {
                    name: newDefectFeatureName
                },
                dataType: "json",
                type: "POST",
                url: url
            });
     
            Sleep(1000); // needed to allow the ajax call above to complete before re-reading the datasource
            defectFeatureGrid.dataSource.read();
            newDefectFeatureTextBox.val("");
        }
    </script>

    notice here how I'm passing the parameter into the data object for the ajax call, then the same as before calling dataSource.read().  The difference being is in this case, the grid does NOT add the new row.

     

    When I look at the database, the record gets added regardless to how the parameter is passed into the ajax call.

    When I look at the fiddler traces from the read calls:

    • parameter passed via URL - The fiddler trace includes the new record
    • parameter passed via data - The fiddler trace does NOT include the new record even though the database shows it's there.

    I've no idea why this is happening, but it repro's 100% of the time.  Is this a bug?  If not can someone explain to me why it's not?  I have another view where I don't have a choice and I have to pass the parameters via the data object...so I need to get it solved eventually or I'm going to be blocked.

    Here's the rest of my source files for context:

    Controller:

    namespace TPOReports.Controllers
    {
        using System.Web.Configuration;
        using System.Web.Mvc;
        using Kendo.Mvc.UI;
        using Kendo.Mvc.Extensions;
        using TPOReporting;
     
        /// <summary>
        /// controller class for dealing with DefectFeature related actions
        /// </summary>
        public class DefectFeatureController : Controller
        {
            /// <summary>
            /// returns the default view for the this controller
            /// </summary>
            /// <returns>DefectFeatureView</returns>
            [HttpGet]
            public ActionResult DefectFeatureView()
            {
                return View();
            }
     
            /// <summary>
            /// adds a new DefectFeature into the database
            /// </summary>
            /// <param name="name">name of DefectFeature to add</param>
            /// <returns>DefectFeatureView</returns>
            [HttpPost]
            public ActionResult AddDefectFeature(string name)
            {
                DataMaintenance dataMaintenance = new DataMaintenance(WebConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
                dataMaintenance.AddDefectFeature(name);
     
                return RedirectToAction("DefectFeatureView");
            }
     
            /// <summary>
            /// retrieves all DefectFeature objects from the database
            /// </summary>
            /// <returns>a collection of DefectFeature objects as json</returns>
            [HttpPost]
            public ActionResult GetDefectFeatures([DataSourceRequest] DataSourceRequest request)
            {
                DataMaintenance dataMaintenance = new DataMaintenance(WebConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
                var defectFeaturesPayload = dataMaintenance.GetDefectFeatures().Payload;
     
                DataSourceResult result = defectFeaturesPayload.ToDataSourceResult(request);
                return Json(result);
            }
        }
    }

    View with working javascript block:

    @using TPOReporting
     
    @{
        ViewBag.Title = "Defect Feature Maintenance";
        Layout = null;
    }
     
    <script>
        function NewDefectFeatureSubmitButtonClick(e)
        {
            var defectFeatureGrid = $("#DefectFeatureGrid").data("kendoGrid");
            var newDefectFeatureTextBox = $("#NewDefectFeatureNameTextBox");
     
            var newDefectFeatureName = newDefectFeatureTextBox.val();
     
            var dummyUrl = '@Url.Action("AddDefectFeature", "DefectFeature", new { name = "--V1--" })';
            var url = dummyUrl.replace("--V1--", newDefectFeatureName);
     
            $.ajax(
            {
                dataType: "json",
                type: "POST",
                url: url
            });
     
            Sleep(1000); // needed to allow the ajax call above to complete before re-reading the datasource
            defectFeatureGrid.dataSource.read();
            newDefectFeatureTextBox.val("");
        }
    </script>
     
    <div>
        <h2>Defect Features</h2>
        <hr size="3" />
    </div>
     
    <div>
        <table>
            <tr>
                <td>
                    <label>New Defect Feature Name:</label>
                </td>
                <td>
                    @(Html.Kendo().TextBox()
                        .Name("NewDefectFeatureNameTextBox"))
                </td>
                <td>
                    @(Html.Kendo().Button()
                        .Name("NewDefectFeatureSubmitButton")
                        .Content("Submit")
                        .Events(e => e.Click("NewDefectFeatureSubmitButtonClick")))
                </td>
            </tr>
        </table>
    </div>
     
    <div>
        @(Html.Kendo().Grid<DefectFeature>()
            .Columns(c =>
            {
                c.Bound(df => df.Name)
                    .Title("Name");
                c.Bound(df => df.LastUpdate)
                    .Title("Last Update");
            })
            .DataSource(ds => ds
                .Ajax()
                .Read(r => r.Action("GetDefectFeatures", "DefectFeature")))
            .HtmlAttributes(new { style = "height:300px;" })
            .Name("DefectFeatureGrid")
            .Scrollable()
            .Selectable()
            .Sortable())
    </div>

  2. Toffer
    Toffer avatar
    34 posts
    Member since:
    Sep 2015

    Posted 07 Oct 2015 in reply to Toffer Link to this post

    interesting thing to note...on a whim I thought I'd try doing a 2nd dataSource.read() right after the first when passing parameters via the data object to see what happened and as luck would have it, the grid refreshed with the new data.  So I have a workaround I guess...but it looks even more hacky then passing the parameters via the URL.  Thoughts anyone?
  3. UI for ASP.NET MVC is VS 2017 Ready
  4. Vladimir Iliev
    Admin
    Vladimir Iliev avatar
    2172 posts

    Posted 12 Oct 2015 Link to this post

    Hello Toffer,

    Could you please elaborate more on why you are not using the Grid DataSource "Create" operation to create new records? Please note that you can add additional data to the "Create" request as demonstrated below:

    .DataSource(dataSource => dataSource       
        .Ajax()     
        .Create(create => create.Action("Create", "Home").Data("addData"))
     
    function addData() {
        var newDefectFeatureTextBox = $("#NewDefectFeatureNameTextBox");
     
        return {
            name: newDefectFeatureName
        };
    }

    Also you should make sure that the server is returning the created record back to the client side (as described in point 7 from this help article) with it's new ID. 

    Using the above approach the record will be created correctly on the server side, and you will not have to call the DataSource "read" method at all. 


    Regards,
    Vladimir Iliev
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  5. Toffer
    Toffer avatar
    34 posts
    Member since:
    Sep 2015

    Posted 19 Oct 2015 in reply to Vladimir Iliev Link to this post

    Hello Vladimir,

     

    The reason I wasn't using the built in Create function was because I couldn't get it to work.  I followed the example from the article you linked previously and whenever I hit the "Add New Record" button, the new row shows up and I can type in the values, but I can't get it to insert them into the database.  I've tried hitting the enter key, hitting the "Add New Record" button again, tried wiring it up to the "NewDefectFeatureSubmitButtonClick" function...nothing seems to work in order to get the grid to submit the new record.  I'd be fine switching to that if I could get it to work.

  6. Toffer
    Toffer avatar
    34 posts
    Member since:
    Sep 2015

    Posted 19 Oct 2015 in reply to Vladimir Iliev Link to this post

    Something to note...I'm not using Entity Framework.  I'm using Linq to SQL classes.
  7. Toffer
    Toffer avatar
    34 posts
    Member since:
    Sep 2015

    Posted 19 Oct 2015 Link to this post

    Ok, I gave it a try for another couple hours this morning and just cannot get it to work.  I can get a new row to show up and I can enter data into it, but nothing I do gets the Create action to be fired.  Do I have to wire it up to a button or something...or do I need to wire up an event?

     

    I made a brand new project following the instructions on the link you had sent previously to try this out so here's what I have for my controller and action...and I only have the Read and Create methods made because that's what I'm having trouble with...the only difference in my example is that I'm using Linq to Sql classes instead of Entity Framework, but that shouldn't matter.

    Model:

    public class DefectFeatureModel
    {
        public int ID { get; set; }
     
        public string Name { get; set; }
     
        public DateTime LastUpdate { get; set; }
    }

     HomeController:

    public ActionResult DefectFeatures_Read([DataSourceRequest]DataSourceRequest request)
    {
        using (var tpor = new _3POReportingDataContext())
        {
            IQueryable<DefectFeature> defectFeatures = tpor.DefectFeatures;
            DataSourceResult result = defectFeatures.ToDataSourceResult(request);
            return Json(result);
        }
    }
     
    public ActionResult DefectFeatures_Create([DataSourceRequest]DataSourceRequest request, DefectFeatureModel defectFeature)
    {
        if(ModelState.IsValid)
        {
            using (var tpor = new _3POReportingDataContext())
            {
                var entity = new DefectFeature
                {
                    Name = defectFeature.Name,
                    LastUpdate = DateTime.Now
                };
     
                tpor.DefectFeatures.InsertOnSubmit(entity);
                tpor.SubmitChanges();
                defectFeature.ID = entity.ID;
            }
        }
     
        return Json(new[] { defectFeature }.ToDataSourceResult(request, ModelState));
    }

    View:

    @(Html.Kendo().Grid<KendoGridinator.Models.DefectFeatureModel>()
        .Columns(c =>
        {
            c.Bound(df => df.ID);
            c.Bound(df => df.Name);
            c.Bound(df => df.LastUpdate);
        })
        .DataSource(d => d
            .Ajax()
            .Create(c => c.Action("DefectFeatures_Create", "Home"))
            .Model(m =>
            {
                m.Id(df => df.ID);
                m.Field(df => df.ID).Editable(false);
            })
            .Read(r => r.Action("DefectFeatures_Read", "Home")))
        .Editable(e => e.Mode(GridEditMode.InLine))
        .ToolBar(t => t.Create())
        .Name("DefectFeatureGrid"))

    If I can get this to work...then I'd stop trying to get my own solution working for inserting rows...
  8. Toffer
    Toffer avatar
    34 posts
    Member since:
    Sep 2015

    Posted 19 Oct 2015 Link to this post

    I attached a picture of what my grid looks like after I hit the "Add new record" button...what do I do to get the record to insert?
  9. Answer
    Vladimir Iliev
    Admin
    Vladimir Iliev avatar
    2172 posts

    Posted 21 Oct 2015 Link to this post

    Hello Toffer,

    After inspecting the code provided in your last reply it seems that the current behavior is expected with current configuration.  Neither the "Save Changes" button added to the Grid Toolbar nor the rows have edit commands defined which is required to allow user trigger the sync with the server. 

    e.g.:

    .ToolBar(toolbar =>
             {
                 toolbar.Create();
                 toolbar.Save();
             })

    Another option is to bind custom "keydown" event handler to the Grid and listen for "enter" key to save the changes manually using the Grid client-side "saveChanges" method. 

    Regards,
    Vladimir Iliev
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  10. Toffer
    Toffer avatar
    34 posts
    Member since:
    Sep 2015

    Posted 21 Oct 2015 in reply to Vladimir Iliev Link to this post

    ahhh, there it was.  toolbar.Save(); is what I was missing.  I added that and eventually got everything working perfectly.  Now I don't need to create my own UI for adding new rows.

     

    I didn't see anything about the toolbar.Save(); in the documentation from the link you posted in the beginning...did I miss it, or is it possible that's missing from the documentation?  If it's missing...I would love to see it get added...it could save some poor fellow like myself a lot of time.  :)

Back to Top
UI for ASP.NET MVC is VS 2017 Ready