【问题标题】:Twitter typeahead add custom data to datasetTwitter typeahead 将自定义数据添加到数据集
【发布时间】:2014-10-14 17:04:25
【问题描述】:

我正在使用twitter typeahead 来显示适合我的类别建议。 问题在于子类别的显示。如果category has sub-categories then expand/collapse icon 与建议一起显示,如果用户选择其中一个子类别,则必须在其下方显示子类别,我在显示部分成功,但 cannot update the dataset 提前输入,这样当用户选择一个子类别时类别它应该显示在输入中。 Please use keyboard on Jsfiddle because i have tried only in keypress。以下是我的json数组

JSFIDDLEhere

[{
    "id": "38",
    "value": "Entertaintment",
    "parent_id": "27",
    "children": "1",
    "childCategories": [{
        "id": "28",
        "value": "Movies",
        "parent_id": "38"
    }, {
        "id": "29",
        "value": "Sports",
        "parent_id": "38"
    }]
}, {
    "id": "40",
    "value": "eeen",
    "parent_id": "27",
    "children": "1",
    "childCategories": [{
        "id": "41",
        "value": "een child 1",
        "parent_id": "40"
    }]
}, {
    "id": "41",
    "value": "een child 1",
    "parent_id": "40",
    "children": "0",
    "childCategories": false
}]

我尝试了以下方法:

_onEnterKeyed: function onEnterKeyed(type, $e) {
    var cursorDatum, topSuggestionDatum;
    cursorDatum = this.dropdown.getDatumForCursor();
    topSuggestionDatum = this.dropdown.getDatumForTopSuggestion();
    //My custom condition, if category has children show sub-categories below 
    if (cursorDatum.raw && cursorDatum.raw.children == "1") {
        //below line is my failed try  
        //this.dropdown.updateChild('',cursorDatum.raw.childCategories,false); 
        var that = this, onSuggestionClick, onSuggestionMouseEnter, onSuggestionMouseLeave;
        var childHTML='';
        $('.ttchild').remove();
        //adding the sub-categories to dropdown
        $.each(cursorDatum.raw.childCategories,function(i,v){
            childHTML += '<div class="tt-suggestion ttchild"><div class="suggestions"><span>'+this.value+'</span></div></div>';
        });
        $(childHTML).insertAfter('.tt-cursor');
        return;
    }

    if (cursorDatum) {
        this._select(cursorDatum);
        $e.preventDefault();
    } 
    else if (this.autoselect && topSuggestionDatum) {
        this._select(topSuggestionDatum);
        $e.preventDefault();
    }
},

//This is my custom function trying to update the dataset, but i know its totally wrong.
updateChild: function updateChild(query,childs) {
    var that = this;
    this.query = query;
    this.canceled = false;
    this.source(query, render);

    function render(childs) {
        if (!that.canceled && query === that.query) {
            that._render(query, childs);
        }
    }
},

JSFIDDLE here

例如:娱乐类别包含电影和体育子类别。

希望有人能帮助我......

【问题讨论】:

  • 我对它进行了一点修改,但它没有正确保存值。看起来在生成 html 之后添加了“haschildren”按钮,因此由于索引错误,因此添加了额外的按钮。希望这在某种程度上对您有所帮助,但是现在挖掘您一直在破解的整个typeahead.bundle file 是一座太远的桥梁。 jsfiddle.net/82hmLprb/1
  • 所有数据都是通过bloodhound添加的。它创建令牌、哈希和缓存。我认为如果我们可以更新寻血猎犬对象中的项目,一切都会好起来的
  • @Nouphal.M 嘿,我怎么还没拿到赏金呢,我解决了你的问题!

标签: javascript jquery twitter-bootstrap autocomplete bootstrap-typeahead


【解决方案1】:

编辑 v.2

我再次refactored,现在它完美运行。

我删除了我之前的编辑并重构onEnterKeyed函数如下

var dataSet = this.dropdown.datasets[0];

// childHTML is replaced by childDom
// var childHTML='';
var childDom = $('<div></div>');
$('.ttchild').remove();
$.each(cursorDatum.raw.childCategories,function(i,v){

    var div = $('<div class="tt-suggestion ttchild"></div>');
    div.append('<div class="suggestions"><span>'+this.value+'</span></div>');


    var suggestion = v;

    // TODO console log this is duplicated from dataset
    var datasetKey = "ttDataset", valueKey = "ttValue", datumKey = "ttDatum";


    // this is what makes it show in the input box
    // set these data for the child element.
    div.data(datasetKey, dataSet.name);
    div.data(valueKey, dataSet.displayFn(suggestion));
    div.data(datumKey, suggestion);

    childDom.append(div);
});

// childHtml is replaced by childDom
$('.tt-cursor').append(childDom.children());

不推荐使用的编辑 v.1

refactored我的解决方案,现在它按预期工作。

我删除了我之前的编辑并在getSuggestionNode 方法中添加了这一行。

for (var key in suggestion.childCategories) {
    var value = suggestion.childCategories[key];
    $el.append(getSuggestionNode(value));
}

以下已弃用

solved你的问题,虽然它需要你改进。

// I added this line
// add the child nodes to the suggestions.
suggestions = suggestions.reduce(function(res, num) { res.push(num); for (var i=0;i<num.children;i++) res.push(num.childCategories[i]);  return res; }, [])

// nodes are calculated based on suggestions
// but child nodes are not added to suggestions so their data is not set (see below line)
nodes = _.map(suggestions, getSuggestionNode);

// inside the suggestions.map function
// here .data sets the necessary values required to render the input on cursor change.
// since child nodes are not mapped they are ignored.
$el = $(html.suggestion).append(that.templates.suggestion(suggestion))
    .data(datasetKey, that.name)
    .data(valueKey, that.displayFn(suggestion))
    .data(datumKey, suggestion);

所以你不需要自定义updateChild 函数,虽然我不知道你是如何实现下拉的,这个解决方案会将孩子添加到下拉列表中并立即显示它们,而无需在父节点中按 enter .您应该自行配置。

【讨论】:

  • 这些条目是重复的,它们不建议在 texbox 中。下拉菜单是预先输入插件的一部分。
  • 但是这里的子类别在启动时显示。我只需要在“娱乐”条目上按回车键时才显示它。即我正在寻找的是在“输入”键事件和鼠标单击时添加和删除项目。我希望你明白我的意思..
  • 您重构的链接无效。我怎么能看到你的解决方案?
  • @Nouphal.M 这是有效的,它正在工作,jsfiddle.net/8nqk6qrr。此外,如果您无法使其工作,我使用gist,请在您的 jsfiddle 中尝试它,它会起作用。你本可以在之前告诉我的,我很期待那份赏金。
  • 已授予您的赏金。 :)
【解决方案2】:

这是一种不同的方法

您可以将每组childCategories 视为它自己的数据源。然后使用Multiple Datasets 范式自动为子项应用标题。

$.typeahead(options, <i>[*datasets]</i>) 的第二个参数采用数据集数组。我们可以像这样将每组子元素转换成它自己的数据集:

var dataSources = [];
$.each(movies, function(index, movieItem) {
    if (movieItem.childCategories) {
        var bloodhoundEngine = createBlounhoud(movieItem.childCategories, 'value');
        var dataSource = {
            name: movieItem.value,
            displayKey: 'value',
            source: bloodhoundEngine.ttAdapter(),
            templates: {
                header: '<h3 class="typeahead-group">' + movieItem.value + '</h3>'
            }
        };
        dataSources.push(dataSource);
    }
});

请注意,我们已经为此数据源中的项目定义了一个标题模板。我们可以这样设计:

.typeahead-group {
  margin: 0 20px 5px 10px;
  padding: 3px 0;
  border-bottom: 1px solid #ccc;
}

不属于子组的元素都可以作为单个 ungrouped 数据源的一部分添加:

var ungrouped = [];
$.each(movies, function(index, movieItem) {
    if (!movieItem.childCategories) {
        ungrouped.push(movieItem);
    }
});

function addUngroupedItems() {
    var bloodhoundEngine = createBlounhoud(ungrouped, 'value');
    var dataSource = {
        name: 'ungrouped',
        displayKey: 'value',
        source: bloodhoundEngine.ttAdapter()
    };
    // add to first position of array so it doesn't look like it's part of the group above it
    dataSources.unshift(dataSource);
};

此解决方案的优势在于,在框架内工作以提供分组功能的同时,最低限度地覆盖了现有的 typeahead 和 Bloodhound 代码。

此外,它还为可能知道他们正在寻找的子项的名称的用户提供了一个直观的用户界面,但不希望必须单击每个类别才能找到它。大多数本地搜索可以轻松搜索所有字段。

Working Demo in jsFiddle

旁白:我会尽量避免直接修改源代码。这使得很难看到您在哪里进行了自己的修改。相反,尝试为整个库使用 CDN,并在其上编写插件或包装器。这将使纳入未来的修订变得更加容易。

【讨论】:

  • 在您的示例中,我无法选择值为“eeen”的元素
  • @Nouphal.M,是的,这将是这种方法的一个限制。如果您希望它们可以自行选择,您当然可以将父项添加到未排序列表中。不完全是你的想法。但仍然提供了一个相对直观的界面,展示了某种分组方式。
  • 我想在下拉列表中添加一个展开/折叠按钮,如果任何项目有子类别并且能够动态添加/删除子元素。
猜你喜欢
  • 1970-01-01
  • 2019-11-08
  • 2023-03-06
  • 1970-01-01
  • 2015-08-09
  • 2017-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多