0
votes

I have an order line grid with a custom edit form, whose fields are pre-populated for adding a row. I thought I had this working based on help I received from this question: How to populate add-row form programmatically for Kendo UI grid (AngularJS)

However, though it works in the simplified plunker, there are a couple of issues when trying to implement it in a real project.

Here is an updated plunker to show the issues below: http://plnkr.co/edit/wtW4RzVu7uuhrJJbWvVd?p=preview

Here is the relevant HTML:

<div id="wrapper" class="container-fluid" ng-controller="ticketEntryController">
  <div ng-controller="ticketLineController">
      <div kendo-grid="ticketLineGrid" k-options="getTicketLineGridOptions()"></div>
  </div>
  <button id="addButton" ng-click="addRow()" class="btn btn-primary btn-sm">Add Row</button>

Clicking the addButton button calls $scope.addRow on the ticketEntryController:

(function () {
    'use strict';
    angular.module('app').controller('ticketEntryController', ticketEntryController);

    function ticketEntryController($scope) {
        $scope.lineGrid = {};

        $scope.addRow = function () {
          var item =  {
            itemNo: "TEST 123",
            id: 0,
            itemDescr: "new item description",
            cat: "CAM",
            mfg: "ACME",
            mfgPartNo: "ABC123456",
            itmStat2: "N",
            price: 133,
            qty: 1
          };
          var ticketId = 200;
          $scope.$broadcast('AddRow', ticketId, item);
        }
    }
})();

addRow() above broadcasts to $scope.$on in ticketLineController:

(function () {
    'use strict';
    angular.module('app').controller('ticketLineController', ticketLineController);

    function ticketLineController($scope) {
        $scope.$on('AddRow', function(event, ticketId, item) {
            console.log("ticketLineController, AddRow: " + item.itemNo);

            $scope.ticketId = ticketId;
            $scope.itemForAdd = item;
            $scope.ticketLineGrid.addRow();
        });

        $scope.getTicketLineGridOptions = function () {
            return {
                dataSource: {
                    type: "json", 
                    transport: {
                        read: function (options) {
                          console.log("--- read ---");
                          options.success(ticketLines);
                        },
                        create: function (options) {
                          console.log("--- create ---");
                          ticketLines.push(options.data);
                          options.success(options.data);
                        },
                        update: function (options) {   // Why is it calling "update" for addRow?? 
                          console.log("--- update ---"); 
                          ticketLines.push(options.data); 
                          options.success(options.data);
                        },
                        destroy:function (options) {   // Why is it calling "destroy" for addRow (issue 2)?
                          console.log("--- destroy ---");
                        },
                    },
                    schema: {
                        model: {
                            id: "id",
                            fields: {
                                id: { type: "string" },
                                orderId: { type: "number" },
                                lineNo: { type: "number" },
                                ...
                            },
                        }
                    },
                    sort: [{ field: "ItemNo", dir: "asc" }],
                    pageSize: 50
                },
                ...
                edit: function (e) {
                    if (e.model.isNew()) {
                        e.model.set("orderId", $scope.ticketId);
                        e.model.set("lineNo", 0);
                        e.model.set("id", $scope.ticketId + "_0");
                        ...
                        e.model.set("qty", 1);
                    }
                    var popupWindow = e.container.getKendoWindow();
                    e.container.find(".k-edit-form-container").width("auto");
                    popupWindow.setOptions({
                        width: 640
                    });
                },

Issue #1: When adding a row, "update" is getting called instead of "create" on the grid's dataSource.

Issue #2: After cancelling out of the edit form, the next time you try to add a row, it for some reason calls "destroy" after the "update" To reproduce: 1) Click Add Row 2) Click Cancel in the edit form 3) Click Add Row again 4) Click Update

2
I think this is more of a "feature" of KendoUi, although I can't say for sure. According to the docs the create event should be called but I didn't see it being called. The reason why you see the destroy being called after the update (after a cancel) is likely because the sync command is being invoked and is "destroying" the rows that were added (then cancelled). Each time you invoke addRow the API adds a new object to the "list" even though you may end up not using it (via cancel). Update the ticketId in the ticketEntryController and you will see what happens in the console - JoseM

2 Answers

2
votes

I heard back from Telerik on this, and the reason "update" was being called instead of "create" is that the id field must be empty for a new record (=0 for integer or "" for string id fields). Once I fixed that, both issues were resolved.

On a related note, the record returned from the server POST (to add record) must contain a populated id field, so that subsequent edits call the "update" instead of "create" in the grid.

0
votes

I had exactly the same issue. Actually The ID field is autogenerated in my database and the issue was resolved simply by assigning newly created id back to the ViewModel as below:

        dbContext.Shipping.Add(entity);
        dbContext.SaveChanges();

        //int newID = entity.Id;
        ShippingViewModel.Id = entity.Id;

Hope this would help.