Algolia autocomplete: How do I highlight items? - search

I use Algolia autocomplete in "standalone" mode, meaning without the commercial Algolia service to return the search results; I have my own server respond with an array of search results.
How do I highlight matches in my returned items/strings (search results)?

The backend must return results that are already highlighted using a tag such as: <mark>this-is-to-be-highlighted</mark>. Here's an example result array for an search for "pie":
const items = [
{ some_attribute: 'Apple <mark>pie</mark>' },
{ some_attribute: 'American <mark>pie</mark>' },
{ some_attribute: 'Chocolate <mark>pie</mark>' }
]
The complete javascript code would then be something like this:
import { autocomplete } from "#algolia/autocomplete-js"
autocomplete({
container: '#search_input',
// ...
getSources({ query }) {
// This would be an example response from your server
const items = [
{ some_attribute: 'Apple <mark>pie</mark>' },
{ some_attribute: 'American <mark>pie</mark>' },
{ some_attribute: 'Chocolate <mark>pie</mark>' }
]
return [
{
sourceId: 'pies',
getItems({ query }) {
const HIGHLIGHT_PRE_TAG = '__aa-highlight__'
const HIGHLIGHT_POST_TAG = '__/aa-highlight__'
return items.map((item) => ({
item,
_highlightResult: {
some_attribute: {
value: item.some_attribute
.replace(/<mark>/g, HIGHLIGHT_PRE_TAG)
.replace(/<\/mark>/g, HIGHLIGHT_POST_TAG)
}
}
}))
},
templates: {
// ...
item({ item, components, html }) {
return html`<div className="aa-ItemWrapper">
<div className="aa-ItemContent">
<div className="aa-ItemContentBody">
<div className="aa-ItemContentTitle">
${components.Highlight({ hit: item, attribute: 'some_attribute' })}
</div>
</div>
</div>
</div>`
},
// ...
}
},
// ...
]
},
// ...
})

Related

Strange behavior on when I press button many times very quick in NODE.JS

I have got 2 cards with 2 candidates, every candidate has a button where user can have a unique vote, the card have a box with total votes also, if the user make a vote for the first candidate, then the value of total in both cards is updated (in a card is substracted in another is added), . But when I press the button many times and very fast, the data returned by the backend is incorrect. Someone can explain what is happening please.
TEMPLATE OF COMPONENT IN ANGULAR
<mat-card class="example-card" *ngFor="let candidate of candidates; let i = index">
<mat-card-actions>
<button mat-raised-button class="button-vote" (click)="saveVote(candidate.userVotes[0], candidate)">
<mat-icon color="accent" aria-hidden="false" aria-label="Example home icon">pan_tool</mat-icon>
</button>
<div class="result" mat-fab>{{candidate.totalVotes}} votos</div>
</mat-card-actions>
</mat-card>
COMPONENENT.TS
export class CandidatesContainerComponent implements OnInit {
candidates!: any[]
constructor(
private candidatesService: CandidatesService,
) { }
ngOnInit(): void {
this.obtainCandidates()
}
obtainCandidates() {
this.candidatesService.getCandidates().subscribe((response: any) => {
this.candidates = response
})
}
saveVote(userVote: any, candidate: object | any) {
this.candidatesService.updateVote(candidate._id, userVote.thisChoosed).subscribe(response => {
if (response) {
this.obtainCandidates()
}
})
}
}
CONTROLLER IN NODE.JS
const updateVote = async ( req = request, res = response ) => {
const { candidateId, thisChoosed } = req.params
const query = thisChoosed === 'true' ? candidateId: { $ne:candidateId }
const previousVote = await Candidate.findOneAndUpdate(
{ _id:query },
{
'$set': { 'userVotes.$[el].thisChoose': false },
'$inc': { 'totalVotes': -1 }
},
{ arrayFilters: [
{"el.user": req.user._id }]
}
)
const newVote = await Candidate.findOneAndUpdate(
{ _id:candidateId },
{
'$set': { 'userVotes.$[el].thisChoose': true },
'$inc': { 'totalVotes': 1 }
},
{
arrayFilters: [ {"el.user": req.user._id }, ], new:true
}
)
res.json( newVote )
}
DATABASE
const VoteSchema = Schema({
user:{
type:Schema.ObjectId,
ref:'User',
required:[true, 'User is required - vote user']
},
thisChoosed:{
type:Boolean,
default:false
},
firstVote:{
type:Boolean,
default:true
}
})
const CandidateSchema = Schema({
names:{
type:String,
required:[true]
},
surnames:{
type:String,
required:[true]
},
userVotes:[VoteSchema],
totalVotes:{
type:Number,
default:0
},
})

How to access ReactQuill Ref when using dynamic import in NextJS?

I'm running into a funny problem. I'm using NextJS for its server-side rendering capabilities and am using ReactQuill as my rich-text editor. To get around ReactQuill's tie to the DOM, I'm dynamically importing it. However, that presents another problem which is that when I try to attach a ref to the ReactQuill component, it's treated as a loadable component instead of the ReactQuill component. I need the ref in order to customize how images are handled when uploaded into the rich-text editor. Right now, the ref returns current:null instead of the function I can use .getEditor() on to customize image handling.
Anybody have any thoughts on how I can address this? I tried ref-forwarding, but it's still applying refs to a loadable component, instead of the React-Quill one. Here's a snapshot of my code.
const ReactQuill = dynamic(import('react-quill'), { ssr: false, loading: () => <p>Loading ...</p> }
);
const ForwardedRefComponent = React.forwardRef((props, ref) => {return (
<ReactQuill {...props} forwardedRef={(el) => {ref = el;}} />
)})
class Create extends Component {
constructor() {
super();
this.reactQuillRef = React.createRef();
}
imageHandler = () => {
console.log(this.reactQuillRef); //this returns current:null, can't use getEditor() on it.
}
render() {
const modules = {
toolbar: {
container: [[{ 'header': [ 2, 3, false] }],
['bold', 'italic', 'underline', 'strike'],
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
[{ 'script': 'sub'}, { 'script': 'super' }],
['link', 'image'],
[{ 'indent': '-1'}, { 'indent': '+1' }],
[{ 'align': [] }],
['blockquote', 'code-block'],],
handlers: {
'image': this.imageHandler
}
}
};
return(
<ForwardedRefComponent
value={this.state.text}
onChange={this.handleChange}
modules={modules}
ref={this.reactQuillRef}/> //this.reactQuillRef is returning current:null instead of the ReactQuill function for me to use .getEditor() on
)
}
}
const mapStateToProps = state => ({
tutorial: state.tutorial,
});
export default connect(
mapStateToProps, {createTutorial}
)(Create);
I share my solution with hope that it helps you too.
Helped from https://github.com/zenoamaro/react-quill/issues/642#issuecomment-717661518
const ReactQuill = dynamic(
async () => {
const { default: RQ } = await import("react-quill");
return ({ forwardedRef, ...props }) => <RQ ref={forwardedRef} {...props} />;
},
{
ssr: false
}
);
export default function QuillWrapper() {
const quillRef = React.useRef(false)
return <>
<ReactQuill forwardedRef={quillRef} />
</>
}
for example you can use the ref to upload image with custom hanlder
import React, { useMemo } from "react";
import dynamic from "next/dynamic";
const ReactQuill = dynamic(
async () => {
const { default: RQ } = await import("react-quill");
return ({ forwardedRef, ...props }) => <RQ ref={forwardedRef} {...props} />;
},
{
ssr: false,
}
);
export default function QuillWrapper({ value, onChange, ...props }) {
const quillRef = React.useRef(false);
// Custom image upload handler
function imgHandler() {
// from https://github.com/quilljs/quill/issues/1089#issuecomment-318066471
const quill = quillRef.current.getEditor();
let fileInput = quill.root.querySelector("input.ql-image[type=file]");
// to prevent duplicate initialization I guess
if (fileInput === null) {
fileInput = document.createElement("input");
fileInput.setAttribute("type", "file");
fileInput.setAttribute(
"accept",
"image/png, image/gif, image/jpeg, image/bmp, image/x-icon"
);
fileInput.classList.add("ql-image");
fileInput.addEventListener("change", () => {
const files = fileInput.files;
const range = quill.getSelection(true);
if (!files || !files.length) {
console.log("No files selected");
return;
}
const formData = new FormData();
formData.append("file", files[0]);
formData.append("uid", uid);
formData.append("img_type", "detail");
quill.enable(false);
console.log(files[0]);
axios
.post("the/url/for/handle/uploading", formData)
.then((response) => {
// after uploading succeed add img tag in the editor.
// for detail visit https://quilljs.com/docs/api/#editor
quill.enable(true);
quill.insertEmbed(range.index, "image", response.data.url);
quill.setSelection(range.index + 1);
fileInput.value = "";
})
.catch((error) => {
console.log("quill image upload failed");
console.log(error);
quill.enable(true);
});
});
quill.root.appendChild(fileInput);
}
fileInput.click();
}
I don't know much about useMemo
but if i don't use the hook,
the editor keeps rerendered resulting in losing focus and I guess perfomance trouble too.
const modules = useMemo(
() => ({
toolbar: {
container: [
[{ font: [] }],
[{ size: ["small", false, "large", "huge"] }], // custom dropdown
["bold", "italic", "underline", "strike"], // toggled buttons
[{ color: [] }, { background: [] }], // dropdown with defaults from theme
[{ script: "sub" }, { script: "super" }], // superscript/subscript
[{ header: 1 }, { header: 2 }], // custom button values
["blockquote", "code-block"],
[{ list: "ordered" }, { list: "bullet" }],
[{ indent: "-1" }, { indent: "+1" }], // outdent/indent
[{ direction: "rtl" }], // text direction
[{ align: [] }],
["link", "image"],
["clean"], // remove formatting button
],
handlers: { image: imgHandler }, // Custom image handler
},
}),
[]
);
return (
<ReactQuill
forwardedRef={quillRef}
modules={modules}
value={value}
onChange={onChange}
{...props}
/>
);
}
In NextJS, React.useRef or React.createRef do not work with dynamic import.
You should Replace
const ReactQuill = dynamic(import('react-quill'), { ssr: false, loading: () => <p>Loading ...</p> }
);
with
import ReactQuill from 'react-quill';
and render after when window is loaded.
import ReactQuill from 'react-quill';
class Create extends Component {
constructor() {
super();
this.reactQuillRef = React.createRef();
this.state = {isWindowLoaded: false};
}
componentDidMount() {
this.setState({...this.state, isWindowLoaded: true});
}
.........
.........
render(){
return (
<div>
{this.isWindowLoaded && <ReactQuil {...this.props}/>}
</div>
)
}
}
Use onChange and pass all the arguments, here one example to use the editor.getHTML()
import React, { Component } from 'react'
import dynamic from 'next/dynamic'
import { render } from 'react-dom'
const QuillNoSSRWrapper = dynamic(import('react-quill'), {
ssr: false,
loading: () => <p>Loading ...</p>,
})
const modules = {
toolbar: [
[{ header: '1' }, { header: '2' }, { font: [] }],
[{ size: [] }],
['bold', 'italic', 'underline', 'strike', 'blockquote'],
[
{ list: 'ordered' },
{ list: 'bullet' },
{ indent: '-1' },
{ indent: '+1' },
],
['link', 'image', 'video'],
['clean'],
],
clipboard: {
// toggle to add extra line breaks when pasting HTML:
matchVisual: false,
},
}
/*
* Quill editor formats
* See https://quilljs.com/docs/formats/
*/
const formats = [
'header',
'font',
'size',
'bold',
'italic',
'underline',
'strike',
'blockquote',
'list',
'bullet',
'indent',
'link',
'image',
'video',
]
class BlogEditor extends Component {
constructor(props) {
super(props)
this.state = { value: null } // You can also pass a Quill Delta here
this.handleChange = this.handleChange.bind(this)
this.editor = React.createRef()
}
handleChange = (content, delta, source, editor) => {
this.setState({ value: editor.getHTML() })
}
render() {
return (
<>
<div dangerouslySetInnerHTML={{ __html: this.state.value }} />
<QuillNoSSRWrapper ref={this.editor} onChange={this.handleChange} modules={modules} formats={formats} theme="snow" />
<QuillNoSSRWrapper value={this.state.value} modules={modules} formats={formats} theme="snow" />
</>
)
}
}
export default BlogEditor
If you want to use ref in Next.js with dynamic import
you can use React.forwardRef API
more info

Vuetify treeview search behavior

Hello and Happy new Year guys,
Again I ask about v-treeview search. When I do my filter, the behavior do not satisfy me.
I updated my version of vuetify to 1.4.0. And I'm using vue 2.5.15
https://codepen.io/anon/pen/PXeMmy?&editors=101
HTML
<div id="app">
<v-container grid-list-md>
<v-layout wrap>
<v-flex xs6>
<!-- Search Field -->
<v-text-field label="search" v-model="search" box>
</v-text-field>
<!-- Treeview -->
<v-treeview :items="filteredTree"
v-model="selected"
active-class="grey lighten-4 indigo--text"
item-key="name"
selected-color="blue"
selectable
hoverable>
</v-treeview>
</v-flex>
<v-flex xs6>
<v-chip v-for="(s , i) in selected" :key="i">
{{s}}
</v-chip>
</v-flex>
</v-layout>
</v-container>
</div>
JS :
new Vue({
el: '#app',
data(){
return{
search: '',
tree: [
{
id: 1,
name: 'Applications',
children: [
{ id: 2, name: 'Calendar' },
{ id: 3, name: 'Chrome' },
{ id: 4, name: 'Webstorm' }
]
},
{
id: 5,
name: 'Languages',
children: [
{ id: 6, name: 'English' },
{ id: 7, name: 'French' },
{ id: 8, name: 'Spannish' }
]
}
],
selected: []
}
},
computed:{
filteredTree: {
get: function() {
let regexp = new RegExp(this.search, "i")
return this.filterTree(this.tree, regexp) || []
},
},
},
methods: {
filterTree: function(tree, filter) {
if (!Array.isArray(tree)) return null
return JSON.parse(JSON.stringify(tree)).filter(function matchName(o) {
let temp;
if (o.name.match(filter)) {
return true;
}
if (!Array.isArray(o.children)) {
return false;
}
temp = o.children.filter(matchName);
if (temp.length) {
o.children = temp;
return true;
}
});
}
}
})
In this exemple when I search "Calen", only "Application -> Calendar" is visible. Until now, it's what I want.
But when I select Calendar, "Application" is also selected; and when I clear the filter, all the children of "Application" are selected too. And I'd like to select "Calendar" and when I clear I don't want its siblings to be selected.
Thank you for reading

Abstract type Node must resolve to an Object type at runtime for field Root.node with value \"\",received \"null\"."

I am implementing a search feature with react and relay.
Below is my schema.js
var { nodeInterface, nodeField } = nodeDefinitions(
(globalId) => {
var { type, id } = fromGlobalId(globalId);
if (type === 'User') {
return getUser(id);
}else if (type === 'Post') {
return getPost(id);
}else if (type === 'Setting') {
return getSetting(id);
}
return null;
},
(obj) => {
if (obj instanceof User) {
return userType;
}else if (obj instanceof Post) {
return postType;
}else if (obj instanceof Setting) {
return settingType;
}
return null;
}
);
var postType = new GraphQLObjectType({
name: 'Post',
fields: {
_id: {
type: new GraphQLNonNull(GraphQLID)
},
createdAt: {
type: GraphQLString
},
id: globalIdField('Post'),
title: {
type: GraphQLString
},
color: {
type: GraphQLString
},
userId: globalIdField('User'),
username: {
type: GraphQLString,
resolve: (post) => getUserById(post.userId),
},
content: {
type: GraphQLString
},
images: {
type: postImageType,
description: "Post's main image links"
}
},
interfaces: [nodeInterface]
});
const {
connectionType: postConnection,
} = connectionDefinitions({name: 'Post', nodeType: postType});
var settingType = new GraphQLObjectType({
name: 'Setting',
fields: {
_id: {
type: new GraphQLNonNull(GraphQLID)
},
id: globalIdField('Setting'),
amount: {
type: GraphQLString
},
all_posts: {
type: postConnection,
args: {
...connectionArgs,
query: {type: GraphQLString}
},
resolve: (rootValue, args) => connectionFromPromisedArray(
getAllPosts(rootValue, args),
args
),
},
},
interfaces: [nodeInterface]
});
var Root = new GraphQLObjectType({
name: 'Root',
fields: () => ({
node: nodeField,
setting: {
type: settingType,
args: {
...connectionArgs,
currency: {type: GraphQLString}
},
resolve: (rootValue, args) => {
return getSetting(args.currency).then(function(data){
return data[0];
}).then(null,function(err){
return err;
});
}
},
})
});
Below is my database.js
export function getAllPosts(params,args) {
let findTitle = {};
let findContent = {};
if (args.query) {
findTitle.title = new RegExp(args.query, 'i');
findContent.content = new RegExp(args.query, 'i');
}
console.log("getAllPosts",args)
return new Promise((resolve, reject) => {
Post.find({$or: [findTitle,findContent]}).sort({createdAt: 'descending'}).exec({}, function(err, posts) {
if (err) {
resolve({})
} else {
resolve(posts)
}
});
})
}
Now I want to fetch all posts by $query variable
So in view I wrote like this
import React, { Component } from 'react';
import Relay from 'react-relay';
class BlogList extends Component {
constructor(props) {
super(props);
this.state = {
query: '',
};
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(){
this.props.relay.setVariables({query: this.state.query});
}
render() {
return (
<div className="input-group col-md-12">
<input type="text" onChange={this.handleChange.bind(this,"query")} value={this.state.query} name="query" placeholder="Enter Title or content"/><br/>
<span className="input-group-btn">
<button type="button" onClick={this.handleSubmit} className="btn btn-info btn-lg">
<i className="glyphicon glyphicon-search"></i>
</button>
</span>
</div>
)
}
};
export default Relay.createContainer(BlogList, {
initialVariables: {
query: ''
},
fragments: {
viewer: () => Relay.QL`
fragment on Setting {
id,
all_posts(first: 10000000,query: $query) {
edges {
node {
id,
_id,
title,
content,
createdAt,
username,
color,
images{
full
}
}
}
}
}
`,
},
});
And in routes I have
const SettingQueries = {
viewer: () => Relay.QL`query{
setting(currency: "USD")
}`,
}
export default [{
path: '/',
component: App,
queries: UserQueries,PostQueries,SettingQueries,
indexRoute: {
component: IndexBody,
},
childRoutes: [
,{
path: 'settings',
component: Setting,
queries: SettingQueries,
}]
}]
Things are working on /graphql as
but when I search from website it generates error in response
{
"data": {
"node": null
},
"errors": [
{
"message": "Abstract type Node must resolve to an Object type at runtime for field Root.node with value \"\",received \"null\".",
"locations": [
{
"line": 2,
"column": 3
}
]
}
]
}
as my web-browser is sending requests as below
Please suggest me what am I missing?
Also If I need to add some additional information please let me know.
The problem might be in your nodeDefinitions() function. First callback, also named idFetcher must return a single object. However, i see in your definition that you return a collection
var { nodeInterface, nodeField } = nodeDefinitions(
(globalId) => {
var { type, id } = fromGlobalId(globalId);
...
}else if (type === 'Post') {
return getPosts(); // this should be getPost(id)
}
);
And thats why your next callback, known as typeResolver fails and returns you a null.
var { nodeInterface, nodeField } = nodeDefinitions(
...
(obj) => {
...
// here you get Promise/Collection instead of single Post instance, therefore condition failed
}else if (obj instanceof Post) {
return postType;
}
return null;
}
);
LordDave's answer revealed one problem in your code. As you commented in his answer, all_posts field of settingType was not working.
If you used mongoose library in your DB code, I see a problem with your query:
Post.find({$or: [findTitle,findContent]}).sort({createdAt: 'descending'}).exec({}, function(err, posts) {
if (err) {
resolve({})
} else {
resolve(posts)
}
});
Based on documentation of exec, change your query to
return Post.find({$or: [findTitle,findContent]}).sort({createdAt: 'descending'}).exec(function(err, posts) {
if (err) {
resolve({})
} else {
resolve(posts)
}
});
As exec returns a promise, you can even do
return Post.find({$or: [findTitle,findContent]}).sort({createdAt: 'descending'}).exec();
Finally I got it working by creating a new type 'postList' and defined it as below
var { nodeInterface, nodeField } = nodeDefinitions(
(globalId) => {
var { type, id } = fromGlobalId(globalId);
if (type === 'User') {
return getUser(id);
}else if (type==='postList') {
return getpostList(id);
} else{
return null;
}
},
(obj) => {
if (obj instanceof User) {
return userType;
}else if (obj instanceof postList) {
return postListType;
}else{
return null;
}
}
);
In database.js
class postList {}
postList.id = "Post_id";
export {postList}
export function getpostList(id) {
return new postList
}
and under root fields as below
var postListType = new GraphQLObjectType({
name: 'postList',
description: 'List of posts',
  fields: () => ({
  id: globalIdField('postList'),
  posts: {
  type: postConnection,
  description: 'List of posts',
  args: {
...connectionArgs,
query: {type: GraphQLString}
},
  resolve: (_, args) => connectionFromPromisedArray(getAllPosts(_,args), args),
  },
}),
interfaces: [nodeInterface],
});
var Root = new GraphQLObjectType({
name: 'Root',
fields: () => ({
node: nodeField,
postList: {
type: postListType,
resolve:(rootValue)=> {
return getpostList()
}
},
})
});
I ran into this issue when I was using an InterfaceType and checked for the InterfaceType before the specialized ObjectType in the if-elseif-else of my TypeResolver

Not Getting Search value in Sencha Touch using searchfield

I want to display predictive text in search field, value for predictive text which comes from server. Here is my code so far:
View:
Ext.define('MyApp.view.AutoSearch', {
extend: 'Ext.dataview.List',
alias : 'widget.mainPanel',
config: {
store : 'AutoSearchStore',
itemTpl: '<div class="myWord">'+
'<div>Word is --<b>{name}</b>--- after search!!!</div>' +
'</div>',
emptyText: '<div class="myWord">No Matching Words</div>',
items: [
{
xtype: 'toolbar',
docked: 'top',
items: [
{
xtype: 'searchfield',
placeHolder: 'Search...',
itemId: 'searchBox'
}
]
}
]
}
});
Store:
Ext.define('MyApp.store.AutoSearchStore',{
extend: 'Ext.data.Store',
config:
{
model: 'MyApp.model.AutoSearchModel',
autoLoad:true,
id:'Contacts',
proxy:
{
type: 'ajax',
url: 'http://alucio.com.np/trunk/dev/sillydic/admin/api/word/categories/SDSILLYTOKEN/650773253e7f157a93c53d47a866204dedc7c363',
reader:
{
rootProperty:''
}
}
}
});
Model:
Ext.define('MyApp.model.AutoSearchModel', {
extend: 'Ext.data.Model',
requires: ['MyApp.model.AutoSearchModelMenu'],
config: {
fields: [
{name:'data', mapping: 'data'},
{name: 'name'},
],
},
});
and
Ext.define('MyApp.model.AutoSearchModelMenu', {
extend: 'Ext.data.Model',
config: {
fields: [
'name',
],
belongsTo: "MyApp.model.AutoSearchModel"
}
});
Controller:
Ext.define('MyApp.controller.SearchAutoComplete', {
extend : 'Ext.app.Controller',
config: {
profile: Ext.os.deviceType.toLowerCase(),
stores : ['MyApp.store.AutoSearchStore'],
models : ['MyApp.model.AutoSearchModel'],
refs: {
myContainer: 'mainPanel'
},
control: {
'mainPanel': {
activate: 'onActivate'
},
'mainPanel searchfield[itemId=searchBox]' : {
clearicontap : 'onClearSearch',
keyup: 'onSearchKeyUp'
}
}
},
onActivate: function() {
console.log('Main container is active--Search');
},
onSearchKeyUp: function(searchField) {
queryString = searchField.getValue();
console.log(this,'Please search by: ' + queryString);
var store = Ext.getStore('AutoSearchStore');
store.clearFilter();
if(queryString){
var thisRegEx = new RegExp(queryString, "i");
store.filterBy(function(record) {
if (thisRegEx.test(record.get('name'))) {
return true;
};
return false;
});
}
},
onClearSearch: function() {
console.log('Clear icon is tapped');
var store = Ext.getStore('AutoSearchStore');
store.clearFilter();
},
init: function() {
console.log('Controller initialized for SearchAutoComplete');
}
});
Json Data Looks Like:
"data":[
{
"name":"paint",
"author":"admin",
"word_id":"1",
"category":"Business",
"is_favourite":"yesStar"
},
{
"name":"abacus",
"author":"admin",
"word_id":"2",
"category":"Education",
"is_favourite":"yesStar"
},
{
"name":"abate",
"author":"admin",
"word_id":"3",
"category":"Education",
"is_favourite":"noStar"
},
{
"name":"testing adsf",
"author":"admin",
"word_id":"7",
"category":"Education",
"is_favourite":"noStar"
},
{
"name":"sprite",
"author":"admin",
"word_id":"6",
"category":"Business",
"is_favourite":"noStar"
},
{
"name":"newword",
"author":"admin",
"word_id":"8",
"category":"Architecture",
"is_favourite":"noStar"
}
]
})
If I type "A", then it displays No Matching Words, but I have words from "A" on json coming from server. How to solve this problem?
Any idea!
Code Sources Link
I don't know why you are using two models but just one thing you need to specify in AutoSearchStore :
reader:
{
rootProperty:'data'
}
instead of
reader:
{
rootProperty:''
}
to get the expected results in the list.
Hope this will be helpful :)

Resources