I've successfully used the igGrid to hook into our Web API. Create, Remove and Delete operations are firing nicely and playing nicely together. The only scenario that is currently failing is this:
In the "iggridupdatingrowadded" event I call "SaveChanges" to the grid to force the API call.
rowAdded: function (e, ui) { var original = ui; ui.owner.grid.saveChanges(function (record, status, response) { var row = this.findRecordByKey(original.rowID); row[original.owner.grid.options.primaryKey] = record[original.owner.grid.options.primaryKey]; this.updateRow(original.rowID, row); }); }
When the transaction commits, it is failing to map the transaction with an -1 ID when it should be 100.
Technical Details:
v14.2
Method: _commitTransaction
this.origDs has a record value of -1.
Unhandled exception at line 244, column 17855 in http://localhost:51580/admin/Scripts/IG/js/infragistics.core.js
0x800a138f - JavaScript runtime error: Unable to set property 'Id' of undefined or null reference
How can I correctly programmatically change the primary key value so the entire grid will function as normal?
Thanks,
Hello,
I am glad that you managed to resolve your issue.
Thank you for sharing your feedback with us and I believe the other members of the community may benefit form your experience.
Please let me know if you have any additional questions regarding this matter.
So the template is tricky. We made the assumption that the template works like the igTemplating. This is INCORRECT. It only allows for one specific value which is ${id} (pay attention to the casing). I have a primary key of Id so I suspected it followed the Primary Key syntax, which is also INCORRECT. If your primary key is called "MyPrimaryKey" then you still specify ${id} in your rest setting template. I guess this also means that the template doesn't support hierarchys or parent child relationships. For example:
DELETE: "/api/location/${locationId}/location/${id}"
Remove a carrier for a specific location. Does the igGrid support this type of syntax? The locationId would come from the row object that was selected.
Our problem is now solved, but I still wanted to make this point clear for others searching for an identical issue.
I've played around with the settings and it still doesn't want to work.
I see why updates are working. It is because our API is grabbing the ID off of the request body, not the URL. The URL for the updates are also wrong. They are being encoded when I expect the value of the ID to be seeded in the URL.
I expect:
[POST] /admin/api/carrier/1 [DELETE] /admin/api/carrier/1
I tried toggling the value encodeRemoveInRequestUri but it did nothing.
The method you aren't familiar with is $.ced.createUri. It formats URL's for us and appends the application root URL if needed. In this case, I tried removing it from the equation and it still encoded the URL.
Sorry I misunderstood what you meant by data binding. I modified the event and now it is correctly seeding the value. We have another event handler for deleting rows, here's the entire igGrid definition:
$.ced.ig.grid({ id: "igGridCarriers", allowPaging: false, allowHiding: false, allowUndoRedo: false, emptyDataText: "THERE ARE NO CARRIERS AVAILABLE. CLICK TO ADD A CARRIER.", primaryKey: "Id", columns: [ { key: "Id", dataType: "number", hidden: true }, { key: "CarrierDescription", dataType: "string", headerText: "Description" }, { key: "StandardCarrierAlphaCode", dataType: "string", headerText: "AlphaCode" }, { key: "Display", dataType: "string", headerText: "Display", unbound: true, template: "${StandardCarrierAlphaCode} - ${CarrierDescription}" }, { key: "SortOrder", dataType: "number", hidden: true }, { key: "CreatedBy", dataType: "number", hidden: true }, { key: "CreatedDate", dataType: "date", hidden: true }, { key: "UpdatedBy", dataType: "number", hidden: true }, { key: "UpdatedDate", dataType: "date", hidden: true }, { key: "Actions", dataType: "string", headerText: "", width: "148px", align: "center", template: "×", unbound: true } ], features: [ { name: "Filtering", columnSettings: [ { columnKey: "Display", allowFiltering: false }, { columnKey: "Actions", allowFiltering: false }, ] }, { name: "Sorting", columnSettings: [ { columnKey: "Display", allowSorting: false }, { columnKey: "Actions", allowSorting: false }, ] }, { name: "Updating", editMode: "cell", autoCommit: false, enableAddRow: true, enableDeleteRow: false, columnSettings: [ { columnKey: "Display", readOnly: true }, { columnKey: "Actions", readOnly: true } ], rowAdding: function (e, ui) { ui.values.CreatedDate = $.ig.formatter(ui.values.CreatedDate || new Date(), "date", "MM/dd/yyyy h:mm:ss tt", true, true, null); ui.values.CreatedBy = ui.values.CreatedBy || 1; ui.values.UpdatedDate = $.ig.formatter(new Date(), "date", "MM/dd/yyyy h:mm:ss tt", true, true, null); ui.values.UpdatedBy = 1; }, rowAdded: function (e, ui) { var original = ui; ui.owner.grid.saveChanges(function (record, status, response) { ui.owner.updateRow(original.rowID, record); original.owner.grid.dataBind(); }); }, editCellEnding: function (e, ui) { if (ui.rowAdding) { return; } if (ui.update === false) { return false; } var row = ui.owner.grid.findRecordByKey(ui.rowID); row.CreatedDate = $.ig.formatter(row.CreatedDate || new Date(), "date", "MM/dd/yyyy h:mm:ss tt", true, true, null); row.CreatedBy = row.CreatedBy || 1; row.UpdatedDate = $.ig.formatter(new Date(), "date", "MM/dd/yyyy h:mm:ss tt", true, true, null); row.UpdatedBy = 1; ui.owner.updateRow(ui.rowID, row); }, editCellEnded: function (e, ui) { if (ui.rowAdding) { return; } ui.owner.grid.dataSource.saveChanges(); } } ], restSettings: { create: { batch: false, template: $.ced.createUri("/api/carrier"), url: $.ced.createUri("/api/carrier") }, update: { batch: false, template: $.ced.createUri("/api/carrier/${Id}"), url: $.ced.createUri("/api/carrier") }, remove: { batch: false, template: $.ced.createUri("/api/carrier/${Id}"), url: $.ced.createUri("/api/carrier") } }, dataSource: $.ced.createUri("/api/carrier") });
Our remove template is setup for deleting items but this is what we see: DELETE /admin/api/carrier/$%7BId%7D HTTP/1.1 The template is escaping the values instead of seeding it with the ID. Updates work great! What gives?
After playing with the settings I see that setting an unbound column up as a primary key does not work for the method findRecordByKey. Nor does it set the data-id attribute on the TR. It is set to undefined.
This sucks. In theory it should work.
It doesn't make sense for an API service to return the entire data source for a POST request. We only return the record that was just created. Furthermore, the grid DOES NOT call the original URI used for the get request. I had to pass in the URL again to reset the data source.
When I read the documentation for igGridUpdating it states:
http://www.igniteui.com/help/iggrid-updating
Updating API
In addition to the updating UI, there is a rich API for adding, updating, and deleting rows programmatically.
When adding a row programmatically, a primary key value is not required. If you do not specify a primary key, a value is provided for you based off of the number of rows in the grid. This can later be processed on the server and replaced with a valid primary key as required by your persistence medium.
I processed the record on the server, now I want to replace the primary key with a valid one from my API. How? Data binding is okay - if and only if it is just for that one record. But we know that's not how it works. I need to only update that single record.