i'm using solr+haystack(django plugin) on the backend and the search is working fine;
While Django(and Haystack) with its templates is doing everything for me(I mean its pretty simple to configure and use), ExtJS4 is a little more complex;
The question is how to use Solr using ExtJS4?
An example is very much appreciated;
Thanks for any help and sorry for my English;
As ExtJS4 is a MVC framework, the solution is done like MVC;
The controller/Search.js
Ext.define('yourapp.controller.Search',{
extend:'Ext.app.Controller',
stores:[
'Searches'
],
views:[
'search.Search',
'search.SearchList'
],
models:[
'Search'
],
init:function(){
this.control({
"search":{
'keyup':this.search,
},
});
},
search:function(inputedTxt, e, eOpts){
this.getSearchesStore().load({
//When sending a request, q will rely to request.POST['q'] on server-side;
//inputedTxt.getValue() -- a value, entered in textfield (or whatever)
params:{
q:inputedTxt.getValue()
},
callback:function(result){
if(result[0]){
//do something with the result
//i'd been creating a window with a grid inside. "Grid"'s view is written below.
}
}
}
});
The models/Search.js
Ext.define('yourapp.model.Search',{
extend:'Ext.data.Model',
fields:[
{name:'name', type:'string'}
]
});
The store/Searches.js
Ext.define('yourapp.store.Searches',{
extend:'Ext.data.Store',
storeId: "searchStore",
model:'yourapp.model.Search',
autoLoad: false,
proxy:{
type:'ajax',
// server-side url
url: '/searchlist/',
actionMethods:{create: "POST", read: "POST", update: "POST", destroy: "POST"},
reader:{
type:'json',
root:'searches'
}
}
});
The view/search/Search.js
//a Text field to input text;
Ext.define('yourapp.view.search.Search',{
extend:'Ext.form.field.Text',
alias: 'widget.search',
id: "searchView",
enableKeyEvents: true,
initComponent:function(){
this.callParent(arguments);
}
});
The view/search/SearchList.js
//a view for a result
Ext.define('yourapp.view.search.SearchList',{
extend: 'Ext.grid.Panel',
alias:'widget.searchlist',
title: 'search result',
store: 'Searches',
columns:[
{
header:'Name',
dataIndex:'name',
flex:1
}
]
});
Somewhere in the view/Viewport.js xtype: 'search', should be inserted for a text field to be displayed.
That's all for a ExtJS4 part.
On server-side -- Django:
'haystack' and Solr should be installed and configured (by 'configured' i mean: search should already work on the server-side);
In someapp/view.py
def searchlist(request):
from haystack.query import SearchQuerySet
# POST["q"] should be receivedt from our client-side
searchText = request.POST["q"]
sqs = SearchQuerySet().filter(name=searchText)
data = []
for result in sqs:
data.append({"name": result.object.name})
return HttpResponse('{ success:true, searches:'+simplejson.dumps(data)+'}', mimetype = 'application/json')
Finally in your urls.py you should add:
(r'^searchlist/','someapp.views.searchlist'),
That was for it. Best wishes.
P.S.
I know this is not the greatest answer and there's lack of explanation, but as for me, I rather prefer a code example than verbal explanation.
SOLR has JSON output from its queries using wt=json param and can readily be consumed by ExtJS.
http://wiki.apache.org/solr/SolJSON?action=fullsearch&context=180&value=jsonp&titlesearch=Titles#JSON_Response_Writer
if you need to use jsonp you can specify a callback function via this param json.wrf=callback
Related
I'm using ExtJs 5.1.1 and I've written a simple view with a grid, and selecting one row the corresponding model property are editable in some text fields.
When editing is completed the button 'save' call Model.save() method, which use the rest proxy configured to write the changes on the server.
The call made by the proxy are two, first is OPTIONS call to know which method are allowed, second call is a PUT.
My problem is PUT json contains only the changed attributes.
I would like that my application sends all the attributes in PUT, instead only the changed subset.
Is this a proxy configuration, or should I use another kind of proxy, like ajax?
Some code snippet:
Model:
Ext.define('myApp.model.CvModel', {
extend: 'Ext.data.Model',
alias: 'viewmodel.cv',
idProperty : 'code',
proxy: {
type: 'rest',
url: 'http://localhost:8080/CV/resource/rest/cvs/CodeSystem/Domain',
paramsAsJson: true,
reader: {
type: 'json',
rootProperty: 'Test_data'
}
},
fields: [{
...
Controller:
onSave: function () {
var selCv = this.getViewModel().get('selectedCv');
selCv.save();
....
You need to specify a writer config on your proxy with writeAllFields: true. By default it's false, and the default writer itself is just {type: 'json'}.
I am playing with the ExtJs4 cartracker application written by existdisolve. I was able to change his queries from rest requests to ajax requests. I also modified the api calls to use ajax to make ajax requests for updates.
I am not getting form or url data passed to my cfc. Instead, in firebug I see JSON passed. I am confused if it is not passed in the form or the url, how is this passed and how do I get to the data? I have tried deserialized the form and url and dumping these after the deserialize and I am told that it is not json.
Where would I find the json?
I am not allowed to post a picture. But it looks like this in the xhr window:
JSON
Active true
ColorID null
Shortname red
Longname Blood Red
So if it is being passed why can I not get to it?
Edit:
#existdissolve - I replaced the rest.js with ajax.js which looks like this:
/**
* Abstract REST proxy
*/
Ext.define('CarTracker6.proxy.Ajax', {
extend: 'Ext.data.proxy.Ajax',
alias: 'proxy.baseajax',
/*format: 'json',*/
limitParam: 'max',
startParam: 'offset',
sortParam: 'sortorder',
writer : {
type : 'ajax',
encode : false,
writeAllFields : true,
root : 'data',
allowSingle : true,
batch : false,
method: 'post',
params: { record: 'record' },
writeRecords : function(request, data) {
request.jsonData = data;
return request;
}
},
reader: {
type: 'json',
root: 'data',
totalProperty: 'count'
},
api: {
read: 'api/option/colors.cfc?method=getcolors',
create: 'api/option/colors.cfc?method=addcolors',
update: 'api/option/colors.cfc?method=updatecolors',
destroy: 'api/option/colors.cfc?method=deletecolors'
}
});
My read works perfectly and I can call the correct cfcs for colors, statuses, etc. and retrieve the requisite data. I am looking to pass parameters to the CFCs and that is not working.
see http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.data.writer.Json-cfg-encode:
if the encode property of your writer is set to false, all data is sent as raw post body. Instead, you can use
encode: true,
root: 'data', // must be set if encode is true
I try to display some data in my Sencha touch application, but it doesn't work... and i can't find what I'm doing wrong.
My webSiste return a json object who look like this
[{"name":"a","id":1}]
the script is getting the Json and display it:
Ext.regApplication({ name: 'Command',
phoneStartupScreen: 'phone-startup.png',
phoneIcon: 'apple-touch-icon.png',
launch: function(){
this.viewport = new Ext.Panel(
{
layout: 'fit',
fullscreen: true,
items: [{xtype: 'list',
itemTpl: new Ext.XTemplate('<div>{name}</div>'),
store: stores
}],
dockedItems: [{xtype: "toolbar",
dock: "top",
title: 'MovieCommand',
items: [{ui: 'back',text: 'back',handler: function(){}}]
}]
});
}
});
Ext.regModel('Commands', {
fields: ['name', 'id' ]
});
var stores = new Ext.data.Store(
{model: 'Commands',
proxy: {type: 'scripttag',
url: 'http://localhost:8080/GTI710/commandes/liste.htm',
format: 'sencha',
reader: new Ext.data.JsonReader ({
type: 'json',
})
},
});
stores.load();
I don't have any error in the java script but nothing is displayed.
I just want to have the "a" displayed but it doesn't work, I don't know why...
The ScriptTagProxy, which you are using, requires a response from server that's composed of legitimate Javascript code.
Specifically, the code is a callback function with the desired JSON data you what as the its first argument:
someCallback([{"name":"a","id":1}]);
The name of someCallback is generated dynamically by Sencha Touch when the request is sent. In other words, your attempt to store the response with a static file will not work.
The name of someCallback is passed as a parameter in the GET request sent by Sencha Touch, the key of which defaults to callback.
If you don't want to have a web server as the data source, checkout Ext.util.JSONP.
I found the very nice demo by Oleg (http://www.ok-soft-gmbh.com/jqGrid/FillToolbarSearchFilter.htm) which shows a "jqGrid toolbar search with autocomplete using local data" but have trouble to get this to work for json via ajax. Is there a good reason why the autocomplete feature won't work - even if I force the grid to be local after loading?
$(document).ready(function() {
var mygrid = $("#mylist"),
mygetUniqueNames = function(columnName) {
var texts = mygrid.jqGrid('getCol',columnName), uniqueTexts = [],
textsLength = texts.length, text, textsMap = {}, i;
for (i=0;i<textsLength;i++) {
text = texts[i];
if (text !== undefined && textsMap[text] === undefined) {
// to test whether the texts is unique we place it in the map.
textsMap[text] = true;
uniqueTexts.push(text);
}
}
return uniqueTexts;
};
mygrid.jqGrid({
url:'autocompleteTest.php',
datatype: "json",
colNames:['name', 'City','stateCd'],
colModel:[
{name:'name',index:'name',width:225, search: true},
{name:'City',index:'City',width:125},
{name:'stateCd',index:'stateCd',width:75},
],
rowNum: 100,
loadonce : true,
sortname: 'name',
sortorder: 'desc',
sortable: true,
viewrecords: true,
rownumbers: true,
sortorder: "desc",
ignoreCase: true,
pager: '#mypager',
height: "auto",
caption: "How to use filterToolbar better with data from server"
}).jqGrid('navGrid','#mypager',
{edit:false, add:false, del:false, search:false, refresh:false});
mygrid.jqGrid('setColProp', 'name',
{
searchoptions: {
sopt:['bw'],
dataInit: function(elem) {
$(elem).autocomplete({
source:mygetUniqueNames('name'),
delay:0,
minLength:0
});
}
}
});
mygrid.jqGrid('filterToolbar',
{stringResult:true, searchOnEnter:true, defaultSearch:"bw"});
});
It is difficult to provide an example in case of the usage of remote source parameter of jQuery UI Autocomplete. The main problem is that your question is about jqGrid which is pure JavaScript solution. If we would discuss the server part of tha solution we would have too options. Many users uses different languages: Java, C#, VB, PHP and so on. For example I personally prefer C#. Then we would have to choose the technology which we use: ASP.NET MVC, WCF, ASPX web service and so on. For example I would choose WCF. Then we should define the database access technology, for example, Entity Framework, LINQ to SQL, SqlDataReader, SqlDataAdapter and so on. Let us I would choose Entity Framework and would provide you the corresponding code example, but it would help you not really if you use for example PHP and MySQL.
So I just describe which interface should have the server for the remote source parameter of jQuery UI Autocomplete without any code.
You should replace in my example the source parameter to your server url like following:
dataInit: function(elem) {
$(elem).autocomplete({
source:'yourSearchUrl.php',
minLength:2
});
}
If the user types two characters (the value can be changed by minLength option), for example 'ab' then the autocomplete will make HTTP GET request with the parameter term=ab:
yourSearchUrl.php?term=ab
your server should answer with the JSON data in the same format as for the local source. I used the string array format in my previous example. Another supported format is array of objects with label/value/both properties like
[
{
"id": "Dromas ardeola",
"label": "Crab-Plover",
"value": "Crab-Plover"
},
{
"id": "Larus sabini",
"label": "Sabine`s Gull",
"value": "Sabine`s Gull"
},
{
"id": "Vanellus gregarius",
"label": "Sociable Lapwing",
"value": "Sociable Lapwing"
},
{
"id": "Oenanthe isabellina",
"label": "Isabelline Wheatear",
"value": "Isabelline Wheatear"
}
]
read the documentation for more information.
If you need to implement more complex scenario and send some additional data to the server or convert the server response in any way you can use custom source callback function. In the case you should use source: function(request, response) {/*your implementation*/}, where the request would be an object having term property (request.term). Inside of your implementation your should make ajax request to the server manually. The response would be callback function which you should call after your custom ajax request will be finished (inside of success event handler). The response function should be called with the parameter which should be array in the same format as mygetUniqueNames returns. I recommend you to examine the source code from the jQuery Autocomplete demo.
To de able to provide unique data from one column of tabele you should just use SELECT DISTINCT SQL statement which are supported in the most databases.
I hope that my description would help you.
UPDATED: If you have the local source the solution you could find in my old answer which you already use. What you just need to do is to call the filterToolbar after the source array are filled. Because you load the data from the server your should move the call of filterToolbar inside of loadComplete. You use loadonce:true jqGrid option which switch the datatype from 'json' to 'local' after the first data loading. So you can include in the loadComplete event handler of your grid the code like the following:
var grid = $('#list');
grid({
url:'autocompleteTest.php',
datatype: 'json',
loadonce: true,
// ... other parameters
loadComplete: function(data) {
if (grid.getGridParam('datatype') === 'json') {
// build the set 'source' parameter of the autocomplete
grid.jqGrid('setColProp', 'name', {
searchoptions: {
sopt:['bw'],
dataInit: function(elem) {
$(elem).autocomplete({
source:mygetUniqueNames('name'),
delay:0,
minLength:0
});
}
}
});
mygrid.jqGrid('filterToolbar',
{stringResult:true,searchOnEnter:true,
defaultSearch:"bw"});
}
}
});
If you will need to reload the data from the server (change the datatype to 'json' and call grid.trigger('reloadGrid')) you will have to change the code above so that you first destroy the autocomplete widget with $('#gs_name').autocomplete('destroy') and then create it one more time with the same code like inside of dataInit.
I have a JSONStore like :
OrdersStore = Ext.extend(Ext.data.JsonStore, {
constructor: function(cfg) {
cfg = cfg || {};
OrdersStore.superclass.constructor.call(this, Ext.apply({
storeId: 'ordersStore',
url: '/ajaxSupport.action',
root: 'rows',
baseParams: {
action: 'getorderlegsearchgrid'
},
fields: [
{
name: 'orderId'
}
]
},
cfg));
}
});
new OrdersStore();
This store is attached to a grid : 'pendingOrdersGrid'.
When I do:
alert(Ext.util.JSON.encode(this.pendingOrdersGrid.getStore().getAt(0)));
I hope to get the first record. But I get 'null'
I can't give you a complete answer from this information but some hints:
don't extend a store with a fixed storeId, url or fields! That's really bad design
if possible use browser that supports a console (Firefox with firebug or IE with developer toolbar [or FF4/IE9]) and debug the content of your store in the console.
to read the content of a record try something like this.pendingOrdersGrid.getStore().getAt(0).data.orderId