Typeahead twitter adds user data to dataset

I use twitter typeahead to show suggestions for categories that are great for me. The problem is displaying subcategories. If a category has sub-categories then expand/collapse icon displayed along with the sentence, if the user selects one of them, subcategories should be shown below it, I succeeded in displaying, but cannot update the dataset type headhead, so when the user selects one, it should be displayed at the input. Please use keyboard on Jsfiddle because i have tried only in keypress . Below is my json array

JSFIDDLE here

 [{ "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 }] 

I tried the following:

 _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

For example: the entertainment category has subcategories films and sports.

Hope someone helps me ....

+6
source share
2 answers

Change v.2

I re-edited , now it works fine.

I removed my previous changes and reorganized the onEnterKeyed function as follows

 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()); 

Deprecated Editing v.1

I reorganize my decision, now it works as expected.

I removed my previous changes and added this line to the getSuggestionNode method.

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

Deprecated below

I solved your problem, although it needs to be improved.

 // 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); 

This way, you don’t need the special updateChild function, although I don’t know how you implement the dropdown stuff, this solution will add the child to the dropdown list and show them instantly without pressing enter in the parent node. You must configure this yourself.

+2
source

Here is a different approach

You can consider each childCategories group as its own data source. Then use Multiple Datasets to automatically apply the title to the children.

The second parameter $.typeahead(options, [*datasets] ) accepts an array of data sets. We can transform each set of children into our own data set as follows:

 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); } }); 

Note that we have defined a header template for elements in this data source. We can do it like this:

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

Elements that were not part of a child group could be added as part of a single ungrouped data 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 part of the group above it dataSources.unshift(dataSource); }; 

This solution has the advantage of minimally overriding the existing type code and deceitful code while working within the framework to provide grouping functionality.

In addition, it provides an intuitive user interface for users who may know the name of the name of the child they are looking for, but do not want him to click on each category to find it. Most local queries can trivially search across all fields.

Working demo in jsFiddle

screenshot

Beyond : I would try not to modify the source code directly. It is very difficult to understand where you made your changes. Instead, try using the CDN for the entire library and write a plugin or wrapper over it. This will facilitate the simplification of future revisions.

+1
source

Source: https://habr.com/ru/post/974139/


All Articles