【问题标题】:Re-inserting a Record into an extJS Store将记录重新插入 extJS 存储
【发布时间】:2011-05-16 10:44:03
【问题描述】:

代码

Ext.onReady(
    function() {
         Ext.QuickTips.init();
         Ext.namespace('TimeTracker');
         TimeTracker.dataStore = new Ext.data.JsonStore(
            {
                root: 'timecardEntries',
                url: 'php/scripts/timecardEntry.script.php',
                storeId: 'timesheet',
                autoLoad: true,
                autoSave: true,
                writer: new Ext.data.JsonWriter(
                    {
                      encode: true
                    }
                ),
                fields: [
                    {name: 'id', type: 'integer'},
                    {name: 'user_id', type: 'integer'},
                    {name: 'ticket_id', type: 'integer'},
                    {name: 'description', type: 'string'},
                    {name: 'start_time', type: 'date', dateFormat: 'Y-m-d H:i:s'},
                    {name: 'stop_time', type: 'date', dateFormat: 'Y-m-d H:i:s'},
                    {name: 'client_id', type: 'integer'},
                    {name: 'is_billable', type: 'integer'}
                ]
            }
        );
        TimeTracker.timeEntryGrid = new Ext.grid.EditorGridPanel(
            {
                renderTo: Ext.getBody(),
                store: TimeTracker.dataStore,
                autoFit: true,
                height: 500,
                title: 'Timesheet Entries',
                tbar: [
                    {
                        xtype: 'button',
                        text: 'Add Record',
                        iconCls: 'silk-add',
                        handler: function() {
                            var timecardEntry = TimeTracker.timeEntryGrid.getStore().recordType;
                            var tce = new timecardEntry(
                                {
                                    description: 'New Timesheet Entry',
                                    start_time: new Date().format('m/d/Y H:i:s'),
                                    is_billable: 0
                                }
                            )
                                TimeTracker.timeEntryGrid.stopEditing();
                            var newRow = TimeTracker.dataStore.getCount();
                            TimeTracker.dataStore.insert(newRow, tce);
                            TimeTracker.timeEntryGrid.startEditing(newRow, 0);
                        }
                    }
                ],
                view: new Ext.grid.GridView(
                    {
                        autoFill: true
                    }
                ),
                colModel: new Ext.grid.ColumnModel(
                    {
                        defaults: {
                            sortable: true,
                            editable: true
                        },
                        columns: [
                            {
                                id: 'ticket_number',
                                header: 'Ticket #',
                                dataIndex: 'ticket_number',
                                editor: new Ext.form.TextField({allowBlank: true}),
                                renderer: function(value) {
                                    return (!value) ? 'N/A' : value;
                                }
                            },
                            {
                                id: 'description',
                                header: 'Description',
                                dataIndex: 'description',
                                editor: new Ext.form.TextField({allowBlank: false})
                            },
                            {
                                id: 'start_time',
                                header: 'Start',
                                dataIndex: 'start_time',
                                renderer: Ext.util.Format.dateRenderer('m/d/Y h:i A'),
                                editor: new Ext.form.DateField({allowBlank: false})
                            },
                            {
                                id: 'stop_time',
                                header: 'Stop',
                                dataIndex: 'stop_time',
                                renderer: Ext.util.Format.dateRenderer('m/d/Y h:i A'),
                                editor: new Ext.form.DateField({allowBlank: false})
                            },
                            {
                                id: 'client',
                                header: 'Client',
                                dataIndex: 'client_id',
                                renderer: function(value) {
                                    return (!value) ? 'N/A' : value;
                                }
                            },
                            {
                                id: 'billable',
                                header: 'Billable',
                                dataIndex: 'is_billable',
                                renderer: function(value) {
                                    return (!value) ? 'No' : 'Yes';
                                }                     
                            },
                            {
                                id: 'actions',
                                header: null,

                                xtype: 'actioncolumn',
                                items: [
                                   {
                                       icon: 'assets/images/silk_icons/page_copy.png',
                                       iconCls: 'action_icon',
                                       handler: function(grid, rowIndex, columnIndex) {
                                            // THE PROBLEM STARTS HERE
                                            grid.stopEditing();
                                            var newRow = TimeTracker.dataStore.getCount();
                                            recordClone = grid.store.getAt(rowIndex);
                                            recordClone.data.start_time = new Date().format('Y-m-d H:i:s');
                                            grid.store.insert(newRow, recordClone);
                                            grid.startEditing(newRow, 0);
                                       }
                                   },
                                   {
                                       icon: 'assets/images/silk_icons/page_delete.png',
                                       handler: function(grid, rowIndex, columnIndex) {
                                           alert('called');
                                       }
                                   }
                                ]
                            }
                        ]
                    }
                )
            }
        );
    }
);

目标

当用户单击“复制”按钮时,该商店记录被存储到内存中,其“开始时间”设置为当前日期和时间,并作为新记录重新插入到商店中

目前的结果

我收到以下 JS 错误:Uncaught TypeError: Cannot read property 'data' of undefined

我的问题

对于初学者,我什至不确定我是否正确抓取了当前选定行的数据记录。其次,我不知道我收到的错误消息是什么意思。

一如既往,我们非常感谢任何帮助。

谢谢。

更新 1

经过一些调整,这就是我想出的(复制按钮处理程序的修改代码)

                    {
                        id: 'actions',
                        header: null,

                        xtype: 'actioncolumn',
                        items: [
                       {
                               icon: 'assets/images/silk_icons/page_copy.png',
                               iconCls: 'action_icon',
                               handler: function(grid, rowIndex, columnIndex) {
                                    grid.stopEditing();
                                    var newRow = TimeTracker.dataStore.getCount();
                                    var currentRecord = grid.store.getAt(rowIndex);
                                    var timecardEntry = grid.store.recordType;
                                    tce = new timecardEntry(currentRecord.data);
                                    tce.data.start_time = new Date().format('Y-m-d H:i:s');
                                    grid.store.insert(newRow, tce);
                               }
                           },
                           {
                               icon: 'assets/images/silk_icons/page_delete.png',
                               handler: function(grid, rowIndex, columnIndex) {
                                   alert('called');
                               }
                           }
                        ]
                    }

这就是我正在做的事情:

  1. 停止编辑网格
  2. 获取当前商店中的记录数
  3. 抓取当前选中的记录并将其存储在内存中
  4. 从商店中获取记录类型
  5. 创建存储记录类型的新实例,并传入所选记录中的数据对象。如果您手动创建新记录,则数据对象等效于对象文字(有关详细信息,请参阅我原来的“添加按钮”代码)
  6. 将创建的新对象的 start_time 值更改为今天的日期和时间
  7. 在网格中插入记录
  8. 快乐时光!

请评论这段代码,如果有更好的方法,请告诉我。谢谢!

更新 2:

                               handler: function(grid, rowIndex, columnIndex) {
                                    grid.stopEditing();
                                    var recordClone = grid.store.getAt(rowIndex).copy();
                                    Ext.data.Record.id(recordClone);
                                    if(recordClone) {
                                        grid.store.add(recordClone);
                                    }
                               }

我更新了代码以使用复制和添加方法,它确实有效。但是,当我调用 add() 方法时,我得到一个“e 是未定义的错误”,但是当我刷新页面时,尽管出现了错误消息,但仍会插入记录。想法?

【问题讨论】:

  • 能否提供一些来自 php 脚本的示例数据?

标签: javascript json extjs


【解决方案1】:

在我看来,它没有正确构造 tce 对象。这一行是你应该设置断点的地方:

 tce = new timecardEntry(currentRecord.data);

它似乎成功地构建了一个timecardEntry,但不知何故不是一个正确的记录。了解它正在构建的内容可能会有所帮助。

如果以这种方式戳它并不清楚为什么它会出现在喷口上,请尝试这样做,就像@timdev 建议的那样:

var store = grid.store,
  currentRecord = store.getAt(rowIndex),
  tce;
tce = currentRecord.copy();
tce.set('start_time', new Date().format('Y-m-d H:i:s'));

if (tce) {
  store.add(tce);
}

(您应该能够调用grid.store.add(tce) 而不是insert,因为您在末尾插入。)

【讨论】:

    【解决方案2】:

    写得很好的问题。很好的相关代码,很好地解释了你所坚持的内容。不幸的是,我没有看到任何突出的东西。

    您的脚本看起来基本正确。你已经接近你需要的地方了。

    以下是我刚刚输入的答案,然后重新阅读了您的问题(和代码),并考虑了一些。你可能已经知道这些东西了,但它是为其他人准备的。这也是相关的,因为我在你所做的相关部分没有看到任何错误,所以你可能在其他地方搞砸了。问题是:在哪里以及如何?

    希望有人比我更精疲力尽并找到明显的问题,与此同时,这是我关于如何在 Ext 中调试以及为什么进行调试的潦草:


    你遗漏了一些重要的东西,或者忽略了它。你提到的那个错误信息:Uncaught TypeError: Cannot read property 'data' of undefined -- 哪里发生了?看起来它没有发生在您发布的代码中,它很可能发生在 ExtJS 的内部。

    所以,启动 FireBug,并打开“错误中断”功能。让你的错误发生,然后开始查看右侧的“堆栈”窗格(通常)。堆栈将向您展示如何到达您所在的位置。

    除非我遗漏了某些东西(而且因为我只是在脑海中运行您的代码,我很可能是),否则可能是其他地方的某些错误配置导致了您的错误。

    但是对于任何程序(尤其是 ExtJS,根据我的经验),调试器是你的朋友。

    这样做:

    • 使用 -debug 版本的 ext-base.js 和 ext-all.js(直到一切正常)
    • 使用 firebug 和“错误中断”
    • 学习使用调试器来单步调试代码,并观察您正在操作的数据。
    • 当您发现自己深陷 ExtJS 的内部时,不要放弃。如果您尝试,您会开始感觉到 WTF 正在发生,即使您不完全理解,它也会开始提示您在哪里搞砸了。

    【讨论】:

    • @timdev,感谢您的回答。这是导致它崩溃的确切行: grid.store.insert(newRow, recordClone);我已经把这件事搞砸了,我唯一了解到的是错误发生在 extJS 的深处。
    • 这可能是因为您没有正确克隆您的记录。尝试将recordClone = grid.store.getAt(rowIndex); 更改为:recordClone = grid.store.getAt(rowIndex).copy()。后面可能是Ext.data.Record.id(recordClone);
    • 我正要说这个,确实,你不是在克隆记录。
    • @timdev 和@Drasill,我发布了一些更新的代码。看一看。谢谢!
    • @Levi Hackith - 你可能仍然遇到和以前一样的问题。如果您在尝试将记录插入()到商店之前尝试使用Ext.data.Record.id(tce) 设置记录会怎样?我不太确定 Record() 构造函数的内部细节——而且我不确定你为什么不像我昨天建议的那样只是 copy() 记录——这正是 copy( ) 专为。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-03
    • 1970-01-01
    • 2013-02-13
    • 2013-04-27
    • 2011-05-02
    • 1970-01-01
    相关资源
    最近更新 更多