AJAX Autocomplete Query from a MYSQL Table - database

I wanted to implement an ajax based autocomplete feature for my searchbox, and i came across, implementing autocomplete in my website.
Now what i wanted to know was that i attach a datasource to the control, but so far i have seen that the datasource requires a textbase schema, can't i like it to a query, where it control calls the query and it returns the records on which the filter of the control must apply.
Hope my question is clear

How do you think you can link it to a query on client-side??
You can link it to an AJAX call to the server, which returns the option-list.
The control's filter will do the rest filtering on that option-list.
The best practice would be, to fire an AJAX on page load, to a server function, which will query to the database (MySQL in your case) and fetch the options-list in json format. Assign the option-list to as an input for autocomplete. (Its obviously better than to fire a ajax-request everytime user starts to type-in the search box.)
If you use jquery it can be something like this.
$(function(){ //runs on page load
$.ajax({
type: "POST",
url: "/searchlist/", //server function that returns the search list
data: '',
dataType: "json",
success: function(json){
search_choices = json.list; // search option list
$("input#searchbox").autocomplete(search_choices, {
max: 4,
scroll: false,
autoFill: true,
multiple: true,
matchContains: true,
multipleSeparator: " ",
width: 180
});
}
});
});
I can provide you with example in libraries other than jquery, but i hope this can make you find your way.
Edit: No, your database needn't to have sorted choices. It is your server function, that should be doing all the sorting. Use,
autocomplete( url_to_server_function, options)
and your server function will get search term (keyword user types in search-box), as get request. Filter your database there, and this is the place where you can hook related words along with the results. Just make a list of everything you want to show as suggestion, and return in serialize json format and let autocomplete to take care of matching and sorting the data.

Related

Kendo multiselect populate previously selected items using odata with paging. (AngularJS)

I'm using the kendo MultiSelect with odata paging and using the angularJS integration. Populating the data from scratch works great. When I want to re-populate the data from initial data then I seem to have a problem.
Cause of the problem:
The data only gets populate from the initial or previous dataset. So, if I the paging size is 10 then only products that exist in the first page will be displayed as normal. All product that don't fall within the first page will just not be displayed.
Possible workarounds:
Increase the page size. I have used this on other pages where the results are quite small. However this is not a realistic work around as we are expecting much bigger datasets in the future ( hence using odata in the first place)
Was thinking we could possibly do some sort of initial sorting. However this could also be slow and could still be a problem if there were more items selected than exist in the first page.
Ideal solution
Is there a way to tell kendo component to load all data based on current value? This will then build the required odata call and populate the component.
Example of the current issue:
http://dojo.telerik.com/ODaLe/2
I worked 2-4 hours to find a solution for this. Dunno if yall would like it, but it might help somebody, so I'd type it here. Following are the steps:
Step 1: Create the data source
First, setup the dataSource object which you would be using for reading remote data (for offline data, improvise by reading the API).
var dataSource = new kendo.data.DataSource({
dataType: "jsonp",
transport: {
read: {
url: options.source,
type: 'POST'
},
},
serverFiltering: true
});
Step 2: Load the selected items
This can be tricky as you need to have the selected item IDs on the client side. For me, I did it by adding a data-options-selected="1;3;9" attribute to my select element. Later, in my JavaScript, I split this attribute by ";" and retrieve an array of selected IDs. Lets say these values are in var valuesArray;
Once we have an array of selected IDs, we need to read them from the data-source. In my case, it was remote, so I ran a dataSource.read() with filters as under:
dataSource.read({
filter: {
logic: 'and',
filters: [
{
field: options.dataValueField,
operator: 'equals',
value: options.value
}
]
}
});
On the server side, this should return an array containing the items having the given identifiers. Thus, we now have those items on the client-side as well.
Step 3: Set values for the widget
Now that the value related data is loaded, we can set the values for the widget using the values() method. Here, $el is the jQuery object representing the select element which I was using for multiSelect.
var oWidget = $el.data('kendoMultiSelect');
oWidget.value(valuesArray);
That's it! One multiselect widget pre-loaded with values, ready to rock and roll. Served my purpose. Dunno if any short-cuts exist.
When using Kendo with Angular, you want to use the k-rebind attribute to refresh the pulldown options + update the picker with the values in your $scope.countries object when it changes.
If you want like the picker to update when $scope.products changes as well, you can initialize the picker using a k-options attr pointed to an object in your controller, and set the k-rebind to that object.
This kendo tutorial provides a useful example, also using odata paging.
http://docs.telerik.com/kendo-ui/web/multiselect/how-to/AngularJS/pre-select-items

How do you update a cached resource in an angular service?

What is a good pattern for updating angular data from a ngResource service that has been cached?
I been trawling posts like this one [1]: How to refresh / invalidate $resource cache in AngularJS, but would be good to hear from angular experts on the right approach for this specific (but pretty general) scenario.
I am looking for a general pattern here. Both in understanding and in implementing angular - I am a novice at it.
I have a pretty standard ngResource service that has a very standard query method, and a custom put method update.
myServices.factory('ThingsService', [
'$resource',
function ($resource) {
return $resource('/api/things/:id', { id: '#id' }, {
query: { method: 'GET', isArray: true, cache: true },
update: {method: 'PUT', cache: true },
});
}]);
I am using it from a controller like this:
$scope.things = ThingsService.query(function (x) {
// must assign these only once data is loaded
$scope.allCount = x.Things.length;
$scope.incomingCount = $filter('filter')(x.Things, { State: 'incoming' }).length;
});
So far so good. The data is returned just fine, and it renders nicely in a dashboard view.
We support in-place-editing and the user can edit the data right there in the dashboard list.
First take a shadow copy of the thing using angular.copy(...) so that we can support buffering of the changes for the user. (just like a dialog box does for a user). Then when they confirm their changes, we call with the shadow copy:
ThingsService.update({ id: currentThing.Id }, { Data: currentThing.Data }, function () {
//TODO: now, if this PUT succeeds,
//I want to update the value of $scope.things array to reflect the changes,
//without going to back to the server for the whole array.
});
This correctly PUTS the changes to the server, which returns an updated thing, but the dashboard view which is bound to the query method is not updated auto-magically. Was kind of hoping angular and the ThingsService and its cache would take care of that for me somehow, you know by updating the cached data. Since the service should know that I just updated one of the items that the service serves up.
So to avoid going all the way back to the server we have told the ThingsService to cache its results, which is a good start. But how are you supposed to update the changed thing in the cached data?
Is there a standard pattern for this kind of update with a ngResource service?
Preferably I wouldn't have to mess with the cache directly. I should not even care that it is cached or how. I just want $scope.things to reflect the posted changes changes.

Backbone.Model.save and don't update client

I want to call save on a Backbone model and have it write data to the server, but not update the client. How do I do this?
To clarify: when Backbone saves a model, it sends all the data to the server, and then retrieves the data from the server and updates it on the client. This second step is what I want not to happen.
To clarify further: The model ('parent' model) has an attribute which is itself a model ('child' model); when it's saved to the server, this child model is converted to JSON. When the parent model updates after the save, the attribute that previously contained a reference to the child model is replaced with the parsed JSON object of the child model that was saved. This is what I need not to happen.
When the data is initially pulled from the server, the parent model "reconstitutes" that object into an appropriate child model, but this is an expensive process and there is no reason to re-do it every time save fires on the parent model, since the child model will never change.
It sounds like you do not want to parse your model when you receive the response from the server on a model.save
You can try something such as:
model.save(attributes,{
success: function() { ... },
parse : false // This will be passed to your parse function as an option
});
You would have to set-up your parse function in your corresponding model as follows:
parse: function(resp,options) {
// don't update model with the server response if {parse:false} is passed to save
if (options && !options.parse) return;
/ ... rest of your parse code ... /
Backbone currently defaults options.parse to true. Here is a short-discussion on the topic.
As discussed in that thread, perhaps you want to consider why you do not want want to update the server response to the client. There may be a cleaner way to achieve the results you desire.
Depending on how/what your server setup is, all you really have to do is issue a regular AJAX request. This is exactly what backbone does in the background so you'll just bypass the client side logic.
You could do this with native JavaScript, but I'm fairly sure you have some other library in use that can make things much easier.
For the completeness of this answer, I'll give an example with jQuery:
$.ajax({
type: "POST",
url: "http://same.as.your.model",
data: { "the" : "model" },
dataType: "JSON",
success: function(){
// once the request has returned
}
});
The $.ajax function also has some additional functionality, and you can read about it in the jQuery docs.
On client you mean Views? If you want to save your model but not render your views which happens since save will trigger a change event, you should call save with option silent:true, or set a custom option like dontchange:true when calling save and check it in when handling change. I prefer the custom option, because silent has side effects (at least in my version of backbone 1.0.0)
a little code:
when you save:
model.save({},{dontchange: true});
you install your event listeners in the view:
this.listenTo(model, 'change', function(model, options){
if (options.dontchange)
return;
this.render();
});
I ran into same problem. model.save(attrs,{patch:true, parse:false}) really did not invoke parse method but model was still merged with server response.
It is not elegant, but this worked for me:
model.clone().save(attrs,{patch:true})
I believe it's best to avoid this situation by clean REST api design.

How can I handle several store instance in the same action using Sencha Touch 2?

I coded a simple application which displays a dataview.List articles in the home page.
Here's a view of my home page :
I can also open a specific article by clicking on it and have its complete description in an other view.
Here's my article view page for a specific article :
To do this I apply a filter in my ArticleController class (here I get the matched record).
onViewArticle: function(record) {
var articleStore = Ext.getStore("ArticleStore");
var selectedArticle = record;
articleStore.filterBy(function(record, id) {
if (selectedArticle.data.id == id)
return (true);
return (false);
});
Ext.Viewport.animateActiveItem(this.getArticleViewConnexContainer(), {
type: "slide", direction: "left"
});
},
And here's my store class :
Ext.define("MyApp.store.ArticleStore", {
extend: "Ext.data.Store",
requires: ["MyApp.model.ArticleModel"],
config: {
model: "MyApp.model.ArticleModel",
proxy: {
type: "ajax",
api: {
create: "http://localhost/MobileApplication/MyApp/services/ArticleService.php?action=create",
read: "http://localhost/MobileApplication/MyApp/services/ArticleService.php?action=read",
update: "http://localhost/MobileApplication/MyApp/services/ArticleService.php?action=update",
destroy: "http://localhost/MobileApplication/MyApp/services/ArticleService.php?action=destroy"
},
extraParams: {
keyword: ""
},
reader: {
type: "json",
rootProperty: "articles",
totalProperty: "total"
}
},
autoLoad: true
}
});
But now, I want to apply another filter in the same action to list others articles (with another specific filter) just below the article description. This involve to use two differents filters I think (one to get back the specific article (already done here) and an other one for the article list I want just below the article description). But how can I do this ? If I apply two filters in the same controller function, the second one will destroy the prevent one because all store data are in the cache. Is there a possible way (like in php MVC frameworks for instance) to send a variable from the controller to the view and display its content (By this way I will have two differents variables and I will can display the content of my two requests on my view)? Or maybe a possible way to handle several stores in the same time ? I'm really lost. Does anyone can help me, please ? Thanks in advance for your help.
There are actually couple questions inside.
Sencha Framework is built with "one store - one view" concept in mind. So if you have two different view presenting information from really one data store, you still would need to have two copies of this store. You can clear/apply back filters if you don't need to show these two views at the same time (it's mostly true in case of phone applications), but I would recommend to have two separate copies.
As far as your scenario - I don't think you need that. When you're displaying particular book you don't need to filter store. You need to just load one record (store.getAt()) and then use this record in your child form.

Issue with Extjs 3.2 grid paging not working

I have multiple store on my page to load data in extjs grid. I am using a js function to load these store. Based on the search button click event I attach the respective store to the grid. Its working fine. In the load function I have lots of params that I need to send to the backend to fetch the results and show in the grid. Now with pagination in place. Is there anyway that I can add that js function call inside the paging so I can pass those params. Because right now if I click next button in paging nothing is getting returned. since the required parameters are missing to fetch the results. I tried all the given sample on internet but nothing is working.
It would be great if somebody can actually post an example on paging passing parameters or calling js function on next button event.
Any help will be really appreciated. Thank you.
below is the load store function that I want to call on my next event on pagination.
function loadStore(prodId, productsName, doctype, criteria, filename, titlename) {
store.removeAll();
store.load({
params: {
// specify params for the first page load if using paging
start: 0,
limit: g_perPage,
ajax: "true",
productId: prodId,
ProductsNameArr: productsName,
assetsname: doctype,
criterianame: criteria,
newfilename: filename,
newtitlename: titlename
}
});
}
http://docs.sencha.com/ext-js/3-4/#!/api/Ext.data.Store-property-baseParams
As Nigel said above the beforeload event is what you are after, see below for an example:
store.on('beforeload',function(store,opts) {
store.baseParams = { param1: 'foo', param2: 'bar', ... }
});
baseParams does not seem particularly useful because it sends static values, not the latest search criteria. Getting the dynamic search criteria is tricky too because the grid (i.e. the form fields) may not exist yet.
The Ext JS devs seem to have consistently mistaken docstring fragments for real documentation making for quite a hellish learning curve with their product. A few real examples here would go a long way.

Resources