为typeahead解析JSON的问题

时间:2014-10-31 11:44:40

标签: javascript json typeahead.js bloodhound

我是使用typeahead插件的新手,我的javascript(不是jquery)技能很糟糕。这是我的JSON:

{"Product":[
    {"@ProductCode":"C1010","@CategoryName":"Clips"},       
    {"@ProductCode":"C1012","@CategoryName":"Clips"},
    {"@ProductCode":"C1013","@CategoryName":"Clips"},
    {"@ProductCode":"C1014","@CategoryName":"Clips"},
    {"@ProductCode":"C1015","@CategoryName":"Clips", "EAN":"0987654321"}
]}

我有typeahead包0.10.5这是我的js:

$(document).ready(function () {
    var products = new Bloodhound({
        datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        limit: 100,
        remote: {
            url: 'TypeAhead.ashx?q=%QUERY&cat=prod',
            filter: function (data) {
                return data.Products;
            }
        }
    });

    products.initialize();

    $("#tbSSearch").typeahead({
        highlight: true,
        minLength: 2
    }, {
        source: products.ttAdapter(),
        displayKey: function (products) {
            return products.product.code;
        },
        templates: {
            header:"<h3>Products</h3>"
        }
    });
});

Chrome控制台让我:

  

未捕获的TypeError:无法读取未定义的属性“长度”

但那是在我的jquery.2.1(缩小的)lib而不是上面的js源代码。浏览器在#tbSearch输入下方没有显示弹出窗口。

正如@Mike建议的那样,jsfiddle http://jsfiddle.net/gw0sfptd/1/但我必须修改一些东西才能使用本地json。这也不起作用LOL

大卫建议

编辑,我应该清理我的json。所以现在是:

[{"Code":"C1010","Gtin13":0,"CategoryName":"Clips"},
 {"Code":"C1012","Gtin13":0,"CategoryName":"Clips"},
 {"Code":"C1013","Gtin13":0,"CategoryName":"Clips"}]

和js:

remote: {
    url: 'TypeAhead.ashx?q=%QUERY&cat=prod',
    filter: function (products) {
        return $.map(products.results, function (product) {
            return {
                value: product.Code
            };
        });
    }
}
datumTokenizer: function (datum) {
    return Bloodhound.tokenizers.whitespace(datum.value);
},
queryTokenizer: Bloodhound.tokenizers.whitespace,

但是在firefox控制台中没有工作的typeahead和no(可用)错误。 我想要的输出是产品代码列表,但也是它们所在的类别和gtin13(如果不是null),因为sql搜索所有这三个选项。我应该在客户端为产品创建一个javascript“类”并将json解析为它吗?我还不清楚整个猎犬是如何运作的。 (是的,我查看了样本并阅读了typeahead和bloodhound的文档)我不知道是否可能,但我最终的愿望是,当你从typeahead建议中选择一个项目时,这个产品资源链接到productdetail .aspx并且如果你选择categorydatasource的一个项目(在这个问题中不可见),它将页面重定向到categorydetail.aspx

my chrome console error

2 个答案:

答案 0 :(得分:1)

我写了一个小提琴来演示如何使用typeahead.js来使用你的JSON(本地而不是远程的例子):

http://jsfiddle.net/Fresh/f9rbeqyc/

在下面的回答中,我选择使用ProductCode作为建议,但如果需要,您显然可以使用CategoryName。

我使用的代码的关键部分以及一些注释在这里:

var json = '{"Product":[ ' +
 '{"@ProductCode\":\"C1010\",\"@CategoryName\":\"Clips\"},' +
 '{"@ProductCode\":\"C1012\",\"@CategoryName\":\"Clips\"},' +
 '{"@ProductCode\":\"C1015\",\"@CategoryName\":\"Clips\", \"EAN\":\"0987654321\"}]}';

// Parse the JSON string to a JSON object
var jsonObject = JSON.parse(json);

var products = new Bloodhound({
    // Use $.map() to create an array of ProductCode key value pairs
    local: $.map(jsonObject.Product, function (product) {
        return {
            value: product["@ProductCode"]
        };
    }),
    datumTokenizer: function (datum) {
        // Specify the variable within the datum to use as suggestion data
        // In this case it's the value
        return Bloodhound.tokenizers.whitespace(datum.value);
    },
    queryTokenizer: Bloodhound.tokenizers.whitespace
});

另请注意,datumTokenizer指定要用作建议的值;创建了一个带有名为“value”的键的基准数组,因此我们希望使用“value”作为显示键。在您的示例中,您有“return products.product.code;”这不会起作用,因为你的基准没有一个叫做“代码”的字段,也没有你的JSON(!)。

您应该可以参考我的示例和this回答来获取使用远程工作的预先输入。

答案 1 :(得分:0)

Bergi是对的。您已经确定了大写字母而不是复数:它应该是data.Product,而不是data.Products。或者你引用的JSON只是data.Products,在这种情况下,数组是data.Products.Product

BADGERFISH和ARRAYS

你应该注意的另一件事。看起来这里的JSON来自badgerfish。我不知道你是否知道这意味着什么 - 基本上它是将XML翻译成JSON的一种方式。如果只有一个产品或根本没有产品,格式将不同。例如,以下XML:

<Products>
    <Product ProductCode="C1010" ="Clips"/>
    <Product ProductCode="C1012" ="Clips"/>
</Products>

将提供以下JSON:

{
    "Products": {
        "Product": [
            {"@ProductCode":"C1010","@CategoryName":"Clips"},       
            {"@ProductCode":"C1012","@CategoryName":"Clips"},
        ]
    }
}

但只有一种产品,獾鱼不会知道它是一个阵列,你得到这个:

{
    "Products": {
        "Product": {"@ProductCode":"C1010","@CategoryName":"Clips"}
    }
}

并且没有产品,根本不知道包含"Product"

{
    "Products": {}
}

结果是你应该为这些案件做准备。同样,在我看来,函数displayKey将抛出异常,除非它只收到一个产品。

我在我们的nodejs服务器连接到后端服务器的项目上工作。这些后端传统上使用XML,但现在可选择使用badgerfish使用JSON进行响应。数组的这种情况是如此常见,以至于我们有一个实用函数,它将data.Products.Product作为参数并将其转换为数组,如果它不是一个数组。