【问题标题】:free-jqGrid 4.15.6 ExpandNode producing runtime errorfree-jqGrid 4.15.6 ExpandNode 产生运行时错误
【发布时间】:2018-10-11 16:13:02
【问题描述】:

我最近从最初的 Tony Tomov 的 jqGrid v4.5.4 升级到了 Oleg 的 free-jqGrid 4.15.6。

在使用 4.5.4 时,下面的代码可以完美运行,但在 4.15.6 中,它就不行了。运行时错误是由对位于 forceNodeOpen() 函数中的 expandNode 和 expandRow 的两个调用产生的。给出的错误:

TypeError: rc1 未定义

forceNodeOpen() 函数用于强制当前treegrid 节点的所有祖先节点显示为展开状态。很像目录...如果我们加载初始主题节点,我们希望扩展整个主题层次结构:

// force a node (if expandable) to stay expanded
function forceNodeOpen(rowid)
{
    var record = $("#tree").jqGrid('getRowData', rowid);
    var div = $('tr#'+rowid).find('div.ui-icon.treeclick');
    div.removeClass('ui-icon-triangle-1-e tree-plus').addClass('ui-icon-triangle-1-s tree-minus');
    **$('#tree').jqGrid('expandNode', record);**    
    **$('#tree').jqGrid('expandRow', record);**

    // get all ancestoral parents and expand them
    // *NOTE*: the getAncestorNodes function of grid was not usable for 
    //         some reason as the same code below just would not work 
    //         with the return array from getAncestorNodes
    var parent = $("#tree").jqGrid('getNodeParent', record);
    while(parent)
    {
        forceNodeOpen(parent['id']);
        parent = $("#tree").jqGrid('getNodeParent', parent);
    }
}

// using topic url, get the tree row id
function getTopicID(topic)
{
    var nodes = $('#tree').jqGrid('getRowData');
    var rowid = 1;
    $.each(nodes, function(e,i)
    {
        var url = $(this).attr('url');
        if(url == topic)
        {
            rowid = $(this).attr('id');
            return false;
        }
    });

    return rowid;
}

// post request to help server via ajax
function loadTopic(topic)
{
    // no need to load again
    if(loadedtopic == topic) { return false; }

    // select the topic node
    var rowid = getTopicID(topic);
    loading = true;
    $('#tree').jqGrid('setSelection', rowid);
    forceNodeOpen(rowid);
    loading = false;

    // wipe content
    $('h1#help_content_topic span:first').html('Loading...');
    $('div#help_content').html('');

    // block UI for ajax posting
    blockInterface();

    // request help content
    $.ajax(
    {
        type: 'POST', 
        url: '/index.php',
        data: { 'isajax': 1, 'topic': topic },
        success: function(data)
        { 
            $.unblockUI();
            $('h1#help_content_topic span:first').html(data['topic']);
            $('div#help_content').html(data['content']);
            return false;
        }
    });

    // save current topic to prevent loading same topic again
    loadedtopic = topic;
}

// table of contents
$('#tree').jqGrid({
    url: "topics.php",
    datatype: "xml",
    autowidth: true,
    caption: "Help Topics",
    colNames: ["id","","url"],
    colModel: [
        {name: "id",width:1,hidden:true, key:true},
        {name: "topic", width:150, resizable: false, sortable:false},
        {name: "url",width:1,hidden:true}
    ],
    ExpandColClick: true,
    ExpandColumn: 'topic',
    gridview: false,
    height: 'auto',
    hidegrid: false,
    pager: false,
    rowNum: 200,
    treeGrid: true,
    treeIcons: {leaf:'ui-icon-document-b'},

    // auto-select topic node
    gridComplete: function()
    {
        // save current topic to prevent loading same topic again
        loadedtopic = '<? echo($topic) ?>';
        var rowid = getTopicID('<? echo($topic) ?>');
        $('#tree').jqGrid('setSelection', rowid);
        forceNodeOpen(rowid);
        $.unblockUI();
    },

    // clear initial loading
    loadComplete: function()
    {
        loading = false;
    },

    onSelectRow: function(rowid)
    {
        // ignore initial page loads
        if(loading) { return false; }

        // load the selected topic
        var topic = $("#tree").jqGrid('getCell',rowid,'url');
        loadTopic(topic);
    }
});

forceNodeOpen(rowid) 由 loadTopic() 函数调用,该函数在 treegrid 的 onSelectRow() 事件中调用。

不确定 4.5.4 做了什么让这段代码工作,但 4.15.6 发现这是一个错误。 4.15.6.src.js 中的违规行:

expandNode: function (rc) { 
...
if (p.treedatatype !== "local" && !base.isNodeLoaded.call($($t), p.data[p._index[id]]) && !$t.grid.hDiv.loading) {
// set the value which will be used during processing of the server response
// in readInput
p.treeANode = rc1.rowIndex;
p.datatype = p.treedatatype;
...});

我只包含了上述核心函数中的几行。引发错误的是 p.treeANode = rc1.rowIndex。

我必须错过一些东西,但不知道是什么。希望有人能告诉我该怎么做。如果我在 forceNodeOpen() 函数中标记出两个 expandNode 和 expandRow treegrid 函数调用,系统不会出错并加载所需的主题。但是层次结构并没有按需要扩展。


开始编辑 1


返回主题节点的服务器端代码:

echo("<?xml version='1.0' encoding='UTF-8'?>\n");

require('db.php');

echo("<rows>\n");
echo("<page>1</page>\n");
echo("<total>1</total>\n");
echo("<records>1</records>\n");

$sql = "SELECT node.id, node.parentid, node.topic, node.url, node.lft, node.rgt, (COUNT(node.parentid) - 1) AS depth 
            FROM helptopics AS node, helptopics AS parent 
                WHERE node.lft BETWEEN parent.lft AND parent.rgt
                    GROUP BY node.url ORDER BY node.lft";
$stmt = AMDB::selectStatement($sql);
while($data = $stmt->fetch(PDO::FETCH_ASSOC))
{
    $id = $data['id'];
    $pid = $data['parentid'];
    $topic = $data['topic'];
    $url = $data['url'];
    $lft = $data['lft'];
    $rgt = $data['rgt'];
    $leaf = $rgt - $lft == 1 ? 'true' : 'false';
    $exp = 'false';
    $dep = $data['depth'];

    echo("<row><cell>{$id}</cell><cell>{$topic}</cell><cell>{$url}</cell><cell>{$dep}</cell><cell>{$lft}</cell><cell>{$rgt}</cell><cell>{$leaf}</cell><cell>{$exp}</cell></row>\n");
}

echo("</rows>\n");
exit();

结束编辑 1


【问题讨论】:

  • 你能发布一些演示(例如在 jsfiddle 中),它重现了这个问题吗?我想您没有从colModel 中删除列levelparentisLeafexpandedloadedicon。免费 jqGrid 引入了所谓的“附加属性”,其中属性保存在本地数据中,而不是隐藏在网格的 &lt;td&gt; 元素中。见the old post
  • 我发布了整个 javascript。唯一隐藏的列是“id”和“url”,它们不会导致任何错误(console.logging 和警报已确认)。确切的违规行在源代码 jquery.jqGrid.5.15.6.src.js 的第 19415 行中。我不知道如何在 jsFiddle 中创建它。我没有在问题中包含的唯一代码是加载树的 PHP 脚本。我已将其添加到问题中...
  • 你可以看the lineexpandNode的代码,它显示了rc1将如何被初始化。您将获得 undefined 与您的 dame 数据的值。因此,输入数据 存在问题,您使用它来调用expandNode。只有能够重现问题,我才能分析问题。我不需要任何生成数据的服务器代码。将数据作为文本文件就足够了。我只需要一个小演示,它可以演示问题。
  • 我也是这么想的。但是我在第 14907 行 rc1 = .... 下放了一个 console.log(rc1) ,我得到了 expexted .... 结果。但是在 14915 下 8 行,rc1 突然未定义。
  • @oleg,如果您 PM 我,我很乐意为您提供生产代码的实时链接。然后你可以看看它是如何使用的,也许你可以帮我找出我的错误。

标签: jqgrid free-jqgrid


【解决方案1】:

我看到你使用

var record = $("#tree").jqGrid('getRowData', rowid);

获取TreeGrid的节点数据。这不太好,但它在旧的 jqGrid 中工作,因为它保存了内部 jqGrid 数据两次:一次作为本地数据,一次在网格的隐藏单元格中。

您应该使用getLocalRow 而不是getRowData

var record = $("#tree").jqGrid('getLocalRow', rowid);

该代码适用于旧的 jqGrid 和免费的 jqGrid。此外,即使在 jqGrid 4.5.4 中,getLocalRow 的性能也始终优于 getRowData

【讨论】:

  • 不客气!我建议您在代码中搜索 getRowData 并使用 getLocalRow 如果您将其与 rowid 参数一起使用。您可以使用$('#tree').jqGrid('getGridParam', 'data'),而不是使用不带参数的getRowData。不带参数的方法getRowData枚举网格的所有&lt;td&gt;元素,读取DOM的内容并取消格式化数据。 $('#tree').jqGrid('getGridParam', 'data') 方法只是返回对带有数据数组的对象的引用,其中已经全部填充。
  • @Chance:您还可以从colModel删除不需要的隐藏“id”和“url”列,并改用additionalProperties: ["url"]本地 JavaScript 数据(由getLocalRow.jqGrid('getGridParam', 'data') 返回)将包含url(默认保存id),您可以直接访问它。它将额外提高 TreeGrid 的性能并减少页面使用的内存。
  • 我尝试按照您的建议从 colModel 中删除 id 和 url。我不得不修改 colNames[] 以匹配新的 colModel[] 并添加了附加属性 [“url”],我得到了奇怪的结果,所有节点都只是 ID,并且所有节点都是随机展开/折叠的。 .树完全停止工作。
  • @Chance:我看到您使用XML 格式和repeatitems: true 顺序(没有名称的节点,其中项目的顺序 定义了列)。在这种情况下,转换属性中的列会稍微复杂一些。最简单的方法是返回 JSON 而不是 XML。它将提高解析数据的性能。为此,您需要将第一行以echo("&lt;?xml version='1.0' encoding='UTF-8'?&gt;\n");、... 开头的行替换为一个符号[。每行应该看起来像{"id":"{$id}", "topic":"{$topic}", "url":"{$url}", "level": "{$dep}", "lft": "{$lft}"},,,}
  • @Chance:您只需填写按名称所有需要显示TreeGrid的属性加上levellftrgtisLeafexpanded。您可以在jsonlint.com 中验证测试 JSON 数据的正确性。您也需要将datatype: "xml" 替换为datatype: "json"。或者,您可以提供一些返回服务器的 测试 XML 数据,我会帮助您添加 xmlmap 属性来读取数据。 JSON的使用是推荐的方式,但也支持XML。这当然很慢,但它可以使用相应的选项。
猜你喜欢
相关资源
最近更新 更多
热门标签