apfelsine: Unable to get property 'data' of undefined or null reference

Hallo,

ich habe eine Asp.Net Webseite auf MVC (Model View Controller Pattern) basierend, die ich mit Visual Studio programmiere. Ich versuche in meiner View einem Kendogrid eine Update Funktion beizubringen. Als normale, nicht ineinander verschachtelte Elemente, wäre das kein Problem, dafür habe ich funktionierende Vorlagen, die allerdings anders konzipiert sind. Aber hier möchte ich aus einer Dropdownliste ein Element auswählen und die gewählte Id soll übertragen werden. Ich habe eine Tabelle mit Produktnamen und jedem Produkt soll ein Report zugewiesen werden können. Ganz rechts gibts Buttons Update und Entfernen. Wenn ich auf Update in einer Zeile klicke, dann wird eine Zeile zum Bearbeiten geöffnet und man kann aus einem Dropdown-Feld einen Reportnamen auswählen (siehe Bild).

Gridview-Beispiel

Wenn die Update Funktion ausgeführt werden soll (ich klicke Button Update), bekomme ich im Browserdebugger den Fehler unable to get property 'data' of undefined or null reference. Im Schema wurde sowohl FullReportName als auch ReportId deklariert. Aber in der Anzeige setze ich an die Stelle für FullReportName eine Dropdownliste, die ReportId zurückliefert. Möglicherweise kommt der Fehler daher, das die Wahl der Dropdownliste das Feld "FullReportName" nicht setzt. Das liegt daran, das ich mir nicht sicher bin, wie ich das bewerkstelligen soll, weil mir nicht klar ist, ob und wie ich das entsprechende Element "FullReportName" ansprechen kann. Weil ich kein normales Textfeld habe sondern ein Dropdownfeld, das ReportsId heißt und auch eine Id als Value liefert. Ich könnte natürlich mit einem Eventhandler arbeiten, ein weiteres unsichtbares Feld anhängen, das ich so nenne, aber mir ist nicht klar ob ich das brauche oder ob das KendoGrid dafür bereits eine Funktion bietet, die mir unbekannt ist. Und es ist auch nicht klar, ob das mein Problem behebt.

Automatisch generierter Code

<tr class="k-grid-edit-row" role="row" data-role="editable" data-uid="c5639ca8-3a49-4e08-bd2f-118493b1d149"> <td role="gridcell" data-container-for="FullProductName"> <input name="FullProductName" class="k-input k-textbox valid" type="text" data-bind="value:FullProductName"> </td> <td role="gridcell" data-container-for="FullReportsName"> <select name="ReportsId" class="valid" id="ReportsId" data-val-number="The field ReportsId must be a number." data-val="true" data-bind="value:ReportsId"> <option selected="selected" value="0">*</option> <option value="2">Fahrradtageskarte_Report.rpt</option> <option value="10">Online-Ticket FTT V2_upload.rpt</option> <option value="11">Online-Ticket V6.rpt</option> </select> </td> <td role="gridcell"> <a class="k-button k-button-icontext k-grid-update" href="#"> <span class="k-icon k-update"></span>Update</a> <a class="k-button k-button-icontext k-grid-cancel" href="#"> <span class="k-icon k-cancel"></span>Abbrechen</a> </td></tr>

Die Dropdownliste (im Originaldokument deklariert unter dem KendoGrid Code)

<td class="adminData"> @Html.DropDownListFor(model => model.ReportsId, Model.AvailableReports) @Html.ValidationMessageFor(model => model.AddReportsId) </td>

KendoGrid

$("#ReportsProductList").kendoGrid({ dataSource: { type: "json", transport: { read: { url: "@Html.Raw(Url.Action("ReportsProductList", "TicketPrint"))", type: "POST", dataType: "json", data: addAntiForgeryToken }, update: function (e){ var updatedItem = e.data.Id; var reportsid = $('#AddReportsId').val(); var surl = "/TicketPrint/UpdateReportsProduct/" + updatedItem.toString() + "/" + reportsid; request = $.ajax({ cache: false, type: 'POST', url: surl, data: addAntiForgeryToken, dataType: 'json', success: function (result) { e.success(result); }, error: function (result) { e.error(result) }}); }, destroy: { url: "@Html.Raw(Url.Action("ReportsProductDelete","TicketPrint", new RouteValueDictionary { { "Namespaces", "Nop.Plugin.AboTicketSystem20.Controllers" }, { "area", "" } }))", } }, schema: { data: "Data", total: "Total", errors: "Errors", model: { id: "Id", fields: { Id: { editable: false, type: "number" }, ReportsProductId: { editable: false, type: "number" }, ProductId :{ editable: false, type: "number" }, ReportsId: { editable: false, type: "number" }, ReportsProductId: { editable: false, type: "number" }, FullProductName: { editable: true, type: "string" }, FullReportName: { editable: false, type: "string" } } } }, requestEnd: function (e) { if (e.type == "update") { //Tabelle aktualisieren this.read(); } }, error: function (e) { display_kendoui_grid_error(e); // Cancel the changes this.cancelChanges(); }, pageSize: 10, serverPaging: true, serverFiltering: true, serverSorting: true }, pageable: { refresh: true, numeric: false, previousNext: false, info: false }, editable: { confirmation: "@T("Admin.Common.DeleteConfirmation")", mode: "inline" }, scrollable: false, columns: [{ field: "FullProductName", title: "@T("plugins.dds.ticketprint.product.name")", width: 400 }, { field: "FullReportsName", title: "@T("plugins.dds.ticketprint.reports.name")", width: 200, editor: function (container, options) { $('#ReportsId').appendTo(container); //**hier erwartet Kendogrid sicher keine Id sondern einen Text** } }, { command: [ { name: "edit", text: { edit: "@T("Admin.Common.Edit")", update: "@T("Admin.Common.Update")", cancel: "@T("Admin.Common.Cancel")" } },{ name: "destroy", text: "@T("Admin.Common.Delete")" }] } ] }); });

Danke im Voraus für konstruktive Tipps lg apfelsine

Akzeptierte Antworten zum Thema:

  1. @@apfelsine

    Automatisch generierter Code

    ?? Das heißt, KendoGrid generiert solch fehlerhaften HTML-Code?

    <td role="gridcell" data-container-for="FullProductName"> <input name="FullProductName" class="k-input k-textbox valid" type="text" data-bind="value:FullProductName"> </td>

    Fehler: das Eingabefeld hat keine Beschriftung.

    <td role="gridcell" data-container-for="FullReportsName"> <select name="ReportsId" class="valid" id="ReportsId" data-val-number="The field ReportsId must be a number." data-val="true" data-bind="value:ReportsId"> <option selected="selected" value="0">*</option> <option value="2">Fahrradtageskarte_Report.rpt</option> <option value="10">Online-Ticket FTT V2_upload.rpt</option> <option value="11">Online-Ticket V6.rpt</option> </select> </td>

    Dito.

    <td role="gridcell"> <a class="k-button k-button-icontext k-grid-update" href="#"> <span class="k-icon k-update"></span>Update</a> <a class="k-button k-button-icontext k-grid-cancel" href="#"> <span class="k-icon k-cancel"></span>Abbrechen</a> </td></tr>

    href="#" ist ein sicheres Zeichen, dass die a-Elemente hier falsch verwendet werden; es müssen buttons sein. Das sind keine Links zu anderen Seiten/Stellen, sondern Aktionen auf der Seite.

    LLAP 🖖

    -- “When UX doesn’t consider all users, shouldn’t it be known as ‘Some User Experience’ or... SUX? #a11y” —Billy Gregory
    1. @@apfelsine

      Automatisch generierter Code

      ?? Das heißt, KendoGrid generiert solch fehlerhaften HTML-Code?

      yep!

      der Part den ich anpassen muss ist hier, und nur hier:

      KendoGrid

      $("#ReportsProductList").kendoGrid({ dataSource: { type: "json", transport: { read: { url: "@Html.Raw(Url.Action("ReportsProductList", "TicketPrint"))", type: "POST", dataType: "json", data: addAntiForgeryToken }, update: function (e){ var updatedItem = e.data.Id; var reportsid = $('#AddReportsId').val(); var surl = "/TicketPrint/UpdateReportsProduct/" + updatedItem.toString() + "/" + reportsid; request = $.ajax({ cache: false, type: 'POST', url: surl, data: addAntiForgeryToken, dataType: 'json', success: function (result) { e.success(result); }, error: function (result) { e.error(result) }}); }, destroy: { url: "@Html.Raw(Url.Action("ReportsProductDelete","TicketPrint", new RouteValueDictionary { { "Namespaces", "Nop.Plugin.AboTicketSystem20.Controllers" }, { "area", "" } }))", } }, schema: { data: "Data", total: "Total", errors: "Errors", model: { id: "Id", fields: { Id: { editable: false, type: "number" }, ReportsProductId: { editable: false, type: "number" }, ProductId :{ editable: false, type: "number" }, ReportsId: { editable: false, type: "number" }, ReportsProductId: { editable: false, type: "number" }, FullProductName: { editable: true, type: "string" }, FullReportName: { editable: false, type: "string" } } } }, requestEnd: function (e) { if (e.type == "update") { //Tabelle aktualisieren this.read(); } }, error: function (e) { display_kendoui_grid_error(e); // Cancel the changes this.cancelChanges(); }, pageSize: 10, serverPaging: true, serverFiltering: true, serverSorting: true }, pageable: { refresh: true, numeric: false, previousNext: false, info: false }, editable: { confirmation: "@T("Admin.Common.DeleteConfirmation")", mode: "inline" }, scrollable: false, columns: [{ field: "FullProductName", title: "@T("plugins.dds.ticketprint.product.name")", width: 400 }, { field: "FullReportsName", title: "@T("plugins.dds.ticketprint.reports.name")", width: 200, editor: function (container, options) { $('#ReportsId').appendTo(container); //**hier erwartet Kendogrid sicher keine Id sondern einen Text** } }, { command: [ { name: "edit", text: { edit: "@T("Admin.Common.Edit")", update: "@T("Admin.Common.Update")", cancel: "@T("Admin.Common.Cancel")" } },{ name: "destroy", text: "@T("Admin.Common.Delete")" }] } ] }); });
    2. Hallo Gunnar,

      Fehler: das Eingabefeld hat keine Beschriftung.

      In diesem Fall würde ich sagen: doch, hat es. Die Tabellenüberschrift.

      Rolf

      -- sumpsi - posui - clusi
      1. @@Rolf B

        Fehler: das Eingabefeld hat keine Beschriftung.

        In diesem Fall würde ich sagen: doch, hat es. Die Tabellenüberschrift.

        Das würdest du vielleicht sagen. Für einen Nutzer, der den Inhalt nicht-visuell wahrnimmt, ist die Tabellenüberschrift weit davon entfernt, Beschriftung für ein Eingabefeld zu sein (im doppelten Sinne des Wortes).

        Es ist immer wieder erschreckend, wie wenig Grundverständnis von HTML bei vielen JavaScript-Entwicklern vorhanden ist.

        LLAP 🖖

        -- “When UX doesn’t consider all users, shouldn’t it be known as ‘Some User Experience’ or... SUX? #a11y” —Billy Gregory
        1. Es ist immer wieder erschreckend, wie wenig Grundverständnis von HTML bei vielen JavaScript-Entwicklern vorhanden ist.

          Leider oder eher glücklicherweise sind wir alle nur Menschen. Die Perfektion in der eigenen Fehlerhaftigkeit zu finden anstatt sie zu verurteilen, ist immer wieder eine Herausforderung. Das einzige was ich mit Sicherheit erwarten kann, ist das nichts wirklich perfekt und wasserdicht ist.

  2. Hallo apfelsine,

    mit Kendo habe ich mich auch eine Zeit herumgeprügelt und es eigentlich aufgegeben. Ich habe mehr Zeit damit verbracht, gegen Kendos eigene Vorstellungen von Programmablauf anzukämpfen, als sinnvolle Arbeit zu leisten.

    Whatever. Es gibt nur eine Zeile, die ein Data-Property anpackt:

    var updatedItem = e.data.Id;

    Setz doch da mal einen Breakpoint und guck dir an, was in e steht.

    Rolf

    -- sumpsi - posui - clusi
    1. Ja, ich würde gerne darauf verzichten. Es bedeutet natürlich dann mehr Arbeit. Ich hege ja noch die Hoffnung, das ich irgendwann endlich so weit dahinter steige, das es mich nicht ständig bremst. Leider ist dieses Grid zigfach im Projekt im Einsatz. Für Standardsachen ganz nett, aber für mich schwer nachvollziehbar was man wann wie schreiben muss. Was hast du dann gemacht? Ein Grid zu Fuß erstellt?

      Zum Thema: Der Debugger kommt garnicht erst in die Update Funktion selbst hin. vielleicht kann ich das ja nicht mit einer ajax Anweisung machen. Aber ich habe Beispiele gesehen, wo das verwendet wurde....

      Der Fehler tritt auf in kendo.web.min.js (13,7749)

      "TypeError: Cannot read property 'data' of undefined

      at init.setup (http://localhost:15536/Administration/Scripts/kendo/2014.1.318/kendo.web.min.js:13:7756) at init.create (http://localhost:15536/Administration/Scripts/kendo/2014.1.318/kendo.web.min.js:13:7407) at Object.<anonymous> (http://localhost:15536/Administration/Scripts/kendo/2014.1.318/kendo.web.min.js:13:14516) at Function.Deferred (http://localhost:15536/Administration/Scripts/jquery-1.10.2.min.js:4:27904) at init._promise (http://localhost:15536/Administration/Scripts/kendo/2014.1.318/kendo.web.min.js:13:14467) at init._send (http://localhost:15536/Administration/Scripts/kendo/2014.1.318/kendo.web.min.js:13:14834) at init.sync (http://localhost:15536/Administration/Scripts/kendo/2014.1.318/kendo.web.min.js:13:12436) at init.saveRow (http://localhost:15536/Administration/Scripts/kendo/2014.1.318/kendo.web.min.js:25:1943) at HTMLAnchorElement.<anonymous> (http://localhost:15536/Administration/Scripts/kendo/2014.1.318/kendo.web.min.js:24:30555) at HTMLTableRowElement.dispatch (http://localhost:15536/Administration/Scripts/jquery-1.10.2.min.js:5:14129)"
      1. Mit der minifizierten Version wirst du es schwer haben vernünftiges Debugging zu betreiben. Am besten du tauschst die Version erstmal gegen die originale, nicht-minifizierte Version aus. Dann solltest du mit den Chrome DevTools "Pause on Excpetions" aktivieren, hierdurch pausiert der Debugger automatisch an der Stelle, wo der JavaScript-Fehler auftritt. Du hast dann einen lesbaren Stacktrace und lesbare Variablen beim Debugging.

  3. Ich habe jetzt meinen Code entsprechend diesem Beispiel umgebaut. Der selektierte Report ist jetzt ordnungsgemäß im Feld eingetragen und auch im Debugger angezeigt. Allerdings erhalte ich nach wie vor die gleiche Fehlermeldung. Der Debugger zeigt mir, das die Id=0 ist. Sie sollte jedoch einen Wert größer 0 enthalten!

    Nach dem was ich in anderen Hilfeseiten und Foren gefunden habe, muss irgendwo ein Syntaxfehler sein. Oder ein Feld heißt nicht so wie erwartet…

    Hier der Inhalt des Data Feldes:

    (/images/8c22de0c-3169-4883-af07-b0bad74a47c5.jpg

    Auffällig ist, das hier unter "data" die Id auf 0 ist. Da sollte sich eigentlich eine andere Zahl größer 0 befinden

    Alle involvierten Elemente

    ×××××××××××××× C# ×××××××× public class ReportsModel(): BaseNopModel{ public int Id {get;set;} public int ReportsId {get;set;} public string FileName {get;set;} public string FileType {get;set;} public string FileLink {get;set;} } public class ReportsProductModel : BaseNopModel { public int Id { get; set; } public int ReportsProductId { get; set; } //obsolet public int ProductId { get; set; } public string FullProductName { get; set; } public ReportsModel Report { get; set; } public class DDSTicketPrintController{ [HttpPost] public ActionResult ReportsProductList() { var reportsproducts = _reportsProductService.GetCollectionWithAllProducts(); var productsModel = reportsproducts .Select(x => { var rModel = new ReportsProductModel() { Id = x.Id, ReportsProductId = x.Id,// TODO: to be deleted! ProductId = x.TicexproductId }; var product = _aboProductService.GetById(x.TicexproductId); rModel.FullProductName = (product != null) ? product.Info1 : "Unavailable"; var reports = _reportsService.GetById(x.ReportsId); var reportModel = new ReportsModel(); reportModel.FileLink= (reports != null) ? reports.FileLink : "Unavailable"; reportModel.FileName= (reports != null) ? reports.FileName : "Unavailable"; reportModel.FileType= (reports != null) ? reports.FileType : "Unavailable"; reportModel.Id = (reports != null) ? reports.Id : 0; reportModel.ReportsId = (reports != null) ? reports.Id : 0; rModel.Report = reportModel; return rModel; }) .ToList(); var gridModel = new DataSourceResult() //GridModel<ReportsProductModel> { Data = productsModel, Total = reportsproducts.Count }; } } [HttpPost] public ActionResult ReportsProductUpdate(ReportsProductModel model) { var product = _reportsProductService.GetById(model.Id); if (product != null) { product.ReportsId = model.Report.Id; product.TicexProductId = model.ProductId; _reportsProductService.UpdateReportsProductRecord(product); } return ReportsProductList(); } JAVASCRIPT: $(document).ready(function () { $("#ReportsProductList").kendoGrid({ dataSource: { type: "json", transport: { read: { url: "/DDSTicketPrint/ReportsProductList", type: "POST", dataType: "json", data: addAntiForgeryToken }, update: { url: "/DDSTicketPrint/ReportsProductUpdate", type: "POST", dataType: "json", data: addAntiForgeryToken }, destroy: { url: "/DDSTicketPrint/ReportsProductDelete", } }, schema: { data: "Data", total: "Total", errors: "Errors", model: { id: "Id", fields: { Id: { editable: false, type: "number" }, ReportsProductId: { editable: false, type: "number" }, ProductId: { editable: false, type: "number" }, Report:{ defaultValue:{ReportsId:0, FileName:"none"}}, ReportsProductId: { editable: false, type: "number" }, FullProductName: { editable: false, type: "string" } } } }, requestEnd: function (e) { if (e.type == "update") { //Tabelle aktualisieren this.read(); } }, error: function (e) { display_kendoui_grid_error(e); // Cancel the changes this.cancelChanges(); }, pageSize: 10, serverPaging: true, serverFiltering: true, serverSorting: true }, pageable: { refresh: true, numeric: false, previousNext: false, info: false }, editable: { confirmation: "Sind Sie sicher, dass Sie diesen Artikel löschen wollen?", mode: "inline" }, scrollable: false, columns: [{ field: "FullProductName", title: "Produkt", width: 400 }, { field: "Report", title: "Reportname", width: 200, template: "#=Report.FileName#", editor: ReportsDropDownEditor }, { command: [ { name: "edit", text: { edit: "Bearbeiten", update: "Update", cancel: "Abbrechen" } },{ name: "destroy", text: "Löschen" }] } ] }); }); function ReportsDropDownEditor(container, options) { $('<input required name="' + options.field + '"/>') .appendTo(container) .kendoDropDownList({ autoBind: false, dataTextField: "FileName", dataValueField: "ReportsId", dataSource: { type: "odata", transport: { read: { url: "/DDSTicketPrint/ReportsList", type: "POST", dataType: "json", data: addAntiForgeryToken } }, schema: { data: "Data", total: "Total", errors: "Errors", model: { id: "ReportsId", fields: { Id: { type: "number" }, FileName: { defaultValue: { ReportsId: 0, FileName: "none" } }, } } } } }); }
    1. Hallo apfelsine,

      sehr schwierig nachzuvollziehen - der Auslöser der Fehlermeldung ist jedenfalls nicht e.data, das ist ja gefüllt.

      Javascript-Syntaxfehler sieht man in der Konsole der Browser-Entwicklungswerkzeuge.

      Ein unwichtiges Problem ist, dass Du in der fields-Definition den Key ReportsProductId doppelt hast.

      Eine Merkwürdigkeit ist deine ReportsProductList() Methode, ich sehe kein return Statement für das ActionResult. Das sollte einen Compile-Fehler von C# geben.

      Die von dir gelb hinterlegte Id ist die aus dem ReportsModel, da sehe ich keine Stelle im C# Code, die das befüllt. Die Id des ReportsProductModel steht etwas tiefer und ist 11.

      Ich habe mich mit Kendo-Batchupdates nicht wirklich beschäftigt und kann daher keine Erfahrungen zitieren. Es ist aber BATCH-Update, d.h. das Grid schickt alle Änderungen zum Server. Du nimmst nur eine Zeile entgegen. Und wenn das Grid eigentlich ein Array schickt - erwartet es dan ein gleichartiges Array zurück? Ich weiß es nicht, das habe ich jetzt beim schnellen Blick in die Kendo-Doku nicht gesehen, aber da solltest Du mal genauer hinschauen.

      Rolf

      -- sumpsi - posui - clusi
      1. Hallo Rolf,

        sehr schwierig nachzuvollziehen - der Auslöser der Fehlermeldung ist jedenfalls nicht e.data, das ist ja gefüllt.

        ja tut mir leid, ich tue mich schwer es kürzer zu fassen.

        Javascript-Syntaxfehler sieht man in der Konsole der Browser-Entwicklungswerkzeuge.

        bis auf den einen zeigt meine nix an…

        Ein unwichtiges Problem ist, dass Du in der fields-Definition den Key ReportsProductId doppelt hast.

        Eine Merkwürdigkeit ist deine ReportsProductList() Methode, ich sehe kein return Statement für das ActionResult. Das sollte einen Compile-Fehler von C# geben.

        huch, da ist mir eine Zeile beim kopieren abhanden gekommen. Da steht eigentlich

        return Json(gridModel);

        Die von dir gelb hinterlegte Id ist die aus dem ReportsModel, da sehe ich keine Stelle im C# Code, die das befüllt. Die Id des ReportsProductModel steht etwas tiefer und ist 11.

        Entweder bin ich betrunken... Es ist genau umgekehrt. kopfkratz Die Id ist die von ReportsProductModel. Das sieht man daran, das in der selben Ebene auch die Variablen Report, ProductId steht. Filename, Filetype, Reportid all das gehört zu ReportModel und die sind auch alle mit Werten gefüllt

        Ich habe mich mit Kendo-Batchupdates nicht wirklich beschäftigt und kann daher keine Erfahrungen zitieren. Es ist aber BATCH-Update, d.h. das Grid schickt alle Änderungen zum Server. Du nimmst nur eine Zeile entgegen. Und wenn das Grid eigentlich ein Array schickt - erwartet es dan ein gleichartiges Array zurück? Ich weiß es nicht, das habe ich jetzt beim schnellen Blick in die Kendo-Doku nicht gesehen, aber da solltest Du mal genauer hinschauen.

        ok danke ich schaue mal nach

  4. Hallo,

    ich habe jetzt eine abgespeckte Version in Kendo UI Dojo eingefügt. Ich habe auch nochmal ein anderes Beispiel genommen. Basierend auf diesem Beispiel: https://dojo.telerik.com/EqORe/2 Habe ich meinen Code angepasst, aber es funktioniert nicht. Ich sehe es einfach nicht. Ich komme einfach nicht weiter. Mein Problemcode: https://dojo.telerik.com/UluTOn/2

    1. Hat sich erledigt, ich habe es jetzt endlich herausgefunden. Statt Report in der Spalte in das Feld zu schreiben wurde ReportId erwartet. Ich habe es so oft geändert, ich weiß schon nicht mehr was zur Ausgangsversion nun die Behebung des Fehlers wäre. Egal, es funktioniert endlich. Genug Zeit damit verplempert.

      Wen es interessiert, es sieht jetzt so aus:

      var dataSource = new kendo.data.DataSource({ type: "json", transport: { read: { url: myurl, type: "POST", dataType: "json", data: addAntiForgeryToken }, update: { url: myurl, type: "POST", dataType: "json", data: addAntiForgeryToken } }, pageSize: 20, schema: { data: "Data", total: "Total", errors: "Errors", model: { id: "Id", fields: { Id:{ editable:false, nullable:true}, ProductId: { editable: false, nullable: true }, FullProductName: { editable: false, validation: { required: true } }, Report: { editable:true } } } }, requestEnd: function (e) { if (e.type == "update") { //Tabelle aktualisieren this.read(); } }, }); $("#ReportsProductList").kendoGrid({ dataSource: dataSource, pageable: true, height: 550, columns: [ { field: "FullProductName", title: "@T("plugins.dds.ticketprint.product.name")" }, { field: "ReportsId", title: "@T("plugins.dds.ticketprint.reports.name")", width: 200, template: "#=Report.FileName#", editor: ReportsDropDownEditor }, { command: "edit", title: " ", width: "150px" }], editable: "inline" });