【问题标题】:dgrid (onDemandGrid) loads on first time button click, but error on second time button is clickeddgrid(onDemandGrid)在第一次单击按钮时加载,但在第二次单击按钮时出错
【发布时间】:2017-08-10 17:28:21
【问题描述】:

感谢之前的一些帮助,我让 Dojo dgrid 工作了;甚至想出了如何将它与我的休息服务中的数据联系起来。

现在我添加了一个输入框,一个按钮,所有的逻辑都发生在按钮点击上。但是第二次单击该按钮时,即使输入字段中的输入值相同,也会出现错误。

错误:

TypeError: Cannot read property 'element' of undefined in StoreMixin.js:33

包括图片,以便您可以看到我的 console.logs

我读了这个How To reset the OnDemandGrid,但是是否有必要检查网格是否存在并执行不同的逻辑?我不能每次都“更新”一个新的吗?

代码:

<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props='title:"CustomersGrid"'>
    <label for="lastnameStartsWith">Lastname Starts With:</label>
    <input id="lastnameStartsWith" type="text" name="lastnameStartsWith" value="Wag" 
           data-dojo-type="dijit/form/TextBox"
           data-dojo-props="trim:true, propercase:true" />
    <br />
    <br />  
        <button id="queryStudentsButton" data-dojo-type="dijit/form/Button"
        data-dojo-type="dijit/form/Button" 
        data-dojo-props="iconClass:'dijitIconTask'">
            <span>Query</span>
            <script type='dojo/on' data-dojo-event='click'>
    require([
        'dstore/RequestMemory',
        'dstore/Memory',
        'dgrid/OnDemandGrid'
    ], function (RequestMemory, Memory, OnDemandGrid) {
                    var url = '../students/' + dojo.byId('lastnameStartsWith').value; 
                    console.log("query students for dataGrid latsnameStartsWith:" + dojo.byId('lastnameStartsWith').value);             

                    require(['dojo/request'], function(request){
                        request.get(url,
                             {headers: {"Content-Type": 'application/json',
                                        "username": securityConfig.username,
                                        "password": securityConfig.password}}
                               )
                            .then(function(response){
                                //console.log("string response=" + response); 
                                var respJSON = JSON.parse(response);
                                var respDataForDGrid = respJSON.recordset;
                                console.log("got respJSON back, num rows= " + respDataForDGrid.length);     


                                //================================================          
                                // Create an instance of OnDemandGrid referencing the store
                                console.log("Debug1");             

                                var grid2 = new OnDemandGrid({
                                    collection: new Memory({ data: respDataForDGrid }),
                                    columns: {
                                        student_id: 'ID',
                                        student_firstname: 'First Name',
                                        student_lastname: 'Last Name',
                                        student_city: 'City',
                                        student_state: 'State',
                                        student_zip: 'Zip'
                                    }
                                }, 'grid2');                                    

                                console.log("Debug2");             

                                grid2.startup();
                                console.log("Debug3");             

                             },
                             function(error){
                                console.log("Error=" + error); 
                                //dom.byId('studentFeedback').value += response;
                             }); 
                    });
    });
            </script> 
        </button>
<h2>My demoGrid - From JSON RestService (Database)</h2>
<div id='grid2'></div>

</div>  

第 2 部分 -

我尝试在此页面上混合使用您的代码和代码: How To reset the OnDemandGrid

  if (grid2Registered){
    console.log("reuse existing grid"); 
    grid2Registered.set('collection', memStore);
    // refresh: clear the grid and re-queries the store for data. 
    grid2Registered.refresh();  
    }
    else{...    

这里的文档 (https://github.com/SitePen/dgrid/blob/v0.4.3/doc/components/core-components/OnDemandList-and-OnDemandGrid.md) 说:

清除网格并重新查询存储中的数据。如果 keepScrollPosition 在实例或选项上为 true 传递给刷新,将尝试保留当前 滚动位置。 OnDemandList 从刷新返回一个承诺,它 当视图中的项目完成渲染时解决。承诺解决 使用呈现的 QueryResults。

【问题讨论】:

  • 如果您已经创建了网格,如果您的结构/列保持不变,则始终建议(至少这是我所做的)用新商店刷新网格。这样,您就可以避免每次有查询时创建网格的开销。
  • 那么你将如何实现呢?留个柜台?或者检查如何检查我的 grid2 是否以前定义过?
  • 如果您采用模板化方法,即在 html 中定义小部件,您可以使用 data-dojo-attach-point 来引用网格。如果您采用编程方法,您可以为网格分配一个 id(请注意,您使用的每个 dijit 的 id 必须是唯一的)并将其称为 dijit.byId('yourId')。

标签: dojo dgrid


【解决方案1】:

这个太难了!下面是一个工作示例。

首先,我将 onClick 函数从声明式切换到编程式:声明式脚本由 dojo 解析,因此您无法在调试器下检查它们(设置断点等)(至少我不知道如何要做到这一点)。所以在我看来,避免它们是一种很好的做法。

然后,确实该错误是由于重新实例化具有相同 id 的 dgrid,因此您确实需要一种方法来检测 dgrid 已经存在。但是有一个技巧:要让 dijit 系统正确处理 dgrid,它们需要与 dijitRegistry 扩展混合。详情请见here

那么就可以使用registry.byId('grid2')来检测dgrid已经存在了。

我还不得不跳过 respDataForDgrid 部分,直接使用 respJSON(可能是由于与您的服务器端不同(?) - 我在服务器端使用了一个带有 json 数组的简单文本文件)。

    <!DOCTYPE HTML><html lang="en">
<head>
<meta charset="utf-8">
<title>Neal Walters stask overflow test</title>
<link rel="stylesheet"
    href="dojo-release-1.12.2-src/dijit/themes/claro/claro.css"
    media="screen">
<link rel="stylesheet"
    href="dojo-release-1.12.2-src/dgrid/css/dgrid.css" media="screen">

</head>
<body class="claro">
    <div data-dojo-type="dijit/layout/ContentPane"
        data-dojo-props='title:"CustomersGrid"'>
        <label for="lastnameStartsWith">Lastname Starts With:</label> <input
            id="lastnameStartsWith" type="text" name="lastnameStartsWith"
            value="Wag" data-dojo-type="dijit/form/TextBox"
            data-dojo-props="trim:true, propercase:true" /> <br /> <br />
        <button id="queryStudentsButton" data-dojo-type="dijit/form/Button"
            data-dojo-props="iconClass:'dijitIconTask', onClick: myClick">Query</button>
        <h2>My demoGrid - From JSON RestService (Database)</h2>
        <div id='grid2'></div>

    </div>
    <script src="dojo-release-1.12.2-src/dojo/dojo.js"
        data-dojo-config="async:true"></script>
    <script type="text/javascript">
            require(["dojo", "dojo/parser", "dojo/domReady!"],
            function(dojo, parser){
                parser.parse();
            });
        function myClick(){
        var url = 'students/' + dojo.byId('lastnameStartsWith').value, securityConfig = {username: 'john', password: 'Doe'}; 
                    console.log("query students for dataGrid latsnameStartsWith:" + dojo.byId('lastnameStartsWith').value);             

                    require(['dojo/_base/declare', 'dojo/request', "dijit/registry", "dstore/RequestMemory", "dstore/Memory", "dgrid/OnDemandGrid", "dgrid/extensions/DijitRegistry"], function(declare, request, registry, RequestMemory, Memory, OnDemandGrid, DijitRegistry){
                        request.get(url,{})
                            .then(function(response){
                                console.log("string response=" + response); 
                                var respJSON = JSON.parse(response);
                                //var respDataForDGrid = respJSON.recordset;
                                //console.log("got respJSON back, num rows= " + respDataForDGrid.length);     


                                //================================================          
                                // Create an instance of OnDemandGrid referencing the store
                                console.log("Debug1");             
                                var theGrid = registry.byId('grid2');
                                if (theGrid){
                                    theGrid.set('collection', new Memory({data: respJSON}));
                                }else{
                                    var grid2 = new (declare([OnDemandGrid, DijitRegistry]))({
                                        collection: new Memory({ data: respJSON }),
                                        columns: {
                                            student_id: 'ID',
                                            student_firstname: 'First Name',
                                            student_lastname: 'Last Name',
                                            student_city: 'City',
                                            student_state: 'State',
                                            student_zip: 'Zip'
                                        }
                                    }, 'grid2');                                    

                                    console.log("Debug2");             

                                    grid2.startup();
                                    console.log("Debug3"); 
                                }            

                             },
                             function(error){
                                console.log("Error=" + error); 
                                //dom.byId('studentFeedback').value += response;
                             }); 
                    });
        };
            </script>
</body>
</html>

【讨论】:

  • 谢谢,我会继续尝试转向程序化代码;我开始时混合了不同的样本。这是一个很好的学习练习,但我可以看到这将花费比我计划的更多的时间。我刚开始重构我的代码,学习如何使用更多小的纯函数。我已经开始尝试处理 SELECT 逻辑并取得了一些成功(以查找用户单击了哪一行)。你能看看我上面的“第二部分”吗?原始错误消失了,但新行似乎覆盖了旧行(同时显示两个字母)。
  • 我只发布了代码片段:在顶部有这个: 所以不要认为我需要你的 parser.parse。也有这个接近顶部: 以稍微不同的方式获取 dijit/registry跨度>
  • 您确实需要保留 parser.parse。有关说明,请参阅dojotoolkit.org/documentation/tutorials/1.10/declarative。您可以删除“parseOnLoad: false;”部分。对于
  • 我在上面的评论中的意思是“去程序化”(不是声明性的)。根据与旧行重叠的新行,这可能是由于 javascript 错误(可能在您的控制台上可见?),尽管我在您提供的第 2 部分片段中没有看到任何错误。你试过不刷新吗?
  • 我没有像您明确提到的那样在“var grid2 - new ...”上添加 DijitRegistry。实际上,我认为我有“parseOnLoad:true”,当我再次包含 parser.parse 时,它​​告诉我容器结构中的某些菜单项已经存在。在让这个东西工作的路上!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多