Good day everyone, I'm new user to Extjs 4. Right now, I have a problem in creating a simple paging (a test run just to familiarized on this). Please take a look at the example below.
//creating a store data first
var itemsPerPage = 2;
var productivity = Ext.create('Ext.data.Store',{
fields : ['name','aht','numberOfCalls'],
pageSize: itemsPerPage,
autoLoad: true,
data:{'items':[
{name: 'Magelyn Cunanan', aht:'6:00', numberOfCalls:'50'},
{name:'Martin Dejaresco', aht:'7:30', numberOfCalls:'40'},
{name:'Emerson Dela Pena', aht:'8:00', numberOfCalls:'45'}
]},
proxy: {
type: 'ajax',
url: 'pagingstore.js',
reader: {
type: 'json',
root: 'items',
totalProperty:'total'
}
}
});
productivity.load({
params:{
start:0,
limit: itemsPerPage
}
});
then on my paging,
//... some code here. by the way this is a viewport container
region: 'center',
xtype: 'tabpanel',
autoScroll: true,
activeTab: 2,
items: [{
title: 'Agent\'s Productivity',
xtype: 'gridpanel',
store: productivity,
//for flex, indicates the amount of space this component will take up in its parent container. eg. if 1 this will take 100% of the container
columns: [
{text: 'Agent name',dataIndex: 'name', flex: 1},
{text: 'Handling Time',dataIndex:'aht',flex:1},
{text: 'Number of calls' ,dataIndex: 'numberOfCalls',flex:1}
],
dockedItems:[{
xtype: 'pagingtoolbar',
store: productivity,
dock: 'bottom',
displayInfo: true
}],
all of these codes that I mentioned earlier are inside in app.js. The problem is when I run the program. The data that I stored doesn't appeared on the grid. It shows only no results plus 0 displays on the dockedItems.. I'm using this just to familiarize on how the extjs works and I need to use this extjs for my programming project in the future.
your answer and explanations to your answer is highly appreciated :)
thank you
What is apparent from your code:
you use inline data plus ajax proxy. These two are mutually exclusive - you either want some inline data or you want to pull data from a server via ajax.
proxy url points to a file (at least I guess it from the name pagingstore.js. This is not going to work as server side has to honor start and limit parameters, it has to return only matching recors and it has to return total number of records for paging to work.
you must never fiddle with start and limit yourself when loading the store. Store already knows what to do and sends these parameters automatically.
For inline paging just need to code this
pageSize: itemsPerPage
proxy: {
type: 'memory',
enablePaging: true
}
oh boy.. I made myself difficult on this one :) but thanks for the reference
Related
I am visualizing multiple dataset on a Chart JS. Whenever I enable/disable a dataset. This dataset would create an instance of its data. On my case, it is xAxes.
and when I enable another dataset:
I want to disable creating another instance of xAxes and every it would share the same fixed axes.
xAxes: [{
type: 'time',
distribution: 'linear',
ticks: {
source: 'data'
},
time: {
parser: 'HH:mm:ss',
unit: 'hour',
unitStepSize: 1,
//min: '00:00:00',
//max: '23:59:59'
}
}],
Update: 1
I used round: 'hour', to include in xAxes.time. It looks fixed. However, I don't know why points always go to corners and spread freely with time as shown:
Update: 2
I removed
/*ticks: {
source: 'data'
},*/
Now it is scaled.
Removing the
ticks: {
source: 'data'
},
made the graph scaled with time.
I create 3 numberfields in a form:
{
xtype: 'numberfield',
fieldLabel: 'Inhuur',
name: 'inhuurPrijs',
inputId: 'inhuurPrijs',
emptyText: '0'
},
{
xtype: 'numberfield',
fieldLabel: 'Marge %',
inputId: 'inhuurMarge',
emptyText: '0',
maxValue: 100,
minValue: -100
},
{
xtype: 'numberfield',
fieldLabel: 'Verhuur',
inputId: 'verhuurPrijs',
emptyText: '0'
},
In field 'inhuurPrijs' i fill in a number. For example 100. Based on the field 'inhuurMarge' i want to make the price in 'verhuurPrijs'. inhuurMarge is a percentage field. So when the user choose the value '10' the 'verhuurPrijs' should be 110.
I tried listeners but those aren't working. And to make it even more complicated.....if i fill in 'inhuurPrijs' & 'verhuurPrijs' i want to calculate the percentage between them and place that in 'inhuurMarge'
Is this possible in a form?
You can use listeners, attach them to the fields to detect when changes are made and run your calculation and update the total.
Fiddle
Here is the code in case the above link breaks:
Ext.application({
name: 'Fiddle',
launch: function() {
Ext.create('Ext.form.Panel', {
title: 'Basic Form',
renderTo: Ext.getBody(),
bodyPadding: 5,
width: 350,
defaults: {
xtype: 'numberfield',
listeners: {
change: function(field, newVal, oldVal) {
console.log("Calculating");
var amount = Ext.getCmp('fieldAmount').getValue();
var markup = Ext.getCmp('feildMarkup').getValue();
var total = Ext.getCmp('fieldTotal');
if (amount > 0 && markup > 0) {
total.setValue(
amount + ((markup/amount) * 100)
);
}
}
}
},
items: [{
fieldLabel: 'amount',
name: 'amount',
id: 'fieldAmount'
}, {
fieldLabel: 'markup',
name: 'markup',
id: 'feildMarkup'
}, {
fieldLabel: 'total',
name: 'total',
id: 'fieldTotal'
}]
});
}
});
Note: You should probably disable the total / calculated field so that it cannot be manually edited.
Another solution I've implemented, is to add listeners on update/datachanged event of the store and not on the form fields, in this way all the magic happens even if you change data somewhere else, even from console, not only that particular form.
myStore.on('update', function(store, rec, op, fields, details, eOpts){
// run this only if desired fields have changed
if (fields && fields.some(function(item){
return /^amount/.test(item); // if field name starts with 'amount'
//return ['field_1', 'or_field_2', 'percentage_3'].indexOf(item) >= 0; // validation based on custom names, of course that still can be done using RegEx
})
) {
// custom number round function, see bellow why
var total = Ext.Number.round(rec.get('amount_one') * rec.get('amount_two') / 100);
rec.set('total', total);
}
});
I have the total field in my Model, and retrieve it's default value from the server (if you want), but I'm setting persist: false on it, in order not to send it back to the server.
Regarding custom number round method, I've discovered hard way that JavaScript rounding methods are not quite precise, meaning:
Number((1.005).toFixed(2)); // 1 instead of 1.01
Math.round(1.005*100)/100; // 1 instead of 1.01
Jack Moore built a custom function which seems to correct this which I've implemented in Ext.Number class, so all the credits for this goes to him: http://www.jacklmoore.com/notes/rounding-in-javascript/
function round(value, decimals) {
return Number(Math.round(value+'e'+decimals)+'e-'+decimals);
}
Another improvement is that it's using direct record access (or even associated data if needed), and not ComponentQuery which isn't so performant.
Lately I'm avoiding Ext.getCmp() as much as possible, but if I need to address components in the view (or event parent views) I'm using this.getView().lookupReference() or selectors like .up() or .down() instead.
I have an enhnaced grid connected to a JSONRest and i have it populating after the grid starts up.
I'm confused as to how to update the Grid store when a new query is performed, can anyone help ?
var store = new JsonRest({
target: "rest/search"
});
dataStore = new ObjectStore({ objectStore: store });
/*set up layout*/
var layout = [[
{'name': 'Name', 'field': 'col1', noresize: true, 'width': '100%'},
]];
/*create a new grid:*/
grid = new EnhancedGrid({
id: 'grid',
store: dataStore,
structure: layout,
selectable: true,
selector: false,
selectionMode: 'none',
escapeHTMLInData: false,
autoHeight:true,
plugins: {
pagination: {
pageSizes: ["10", "25", "50"],
description: true,
pageStepper: true,
maxPageStep: 4,
defaultPageSize: 5,
sizeSwitch: true,
position: 'bottom'
}
}
}, document.createElement('div'));
grid.setQuery({
term: "term",
category: "category"
});
grid.startup();
Doing a store.query does hit my back end, but how do i repopulate the Grid with the results?
store.query({term: "newterm", category: "newcategory"},
{
start: 10,
count: 10,
}).then(function(data){
});
In order to populate the grid, you shouldn't be performing a store query directly - you should be instructing the grid to use the store, and it will query it itself.
You already appear to be assigning the store instance in your call to the DataGrid constructor, and you're properly wrapping it with dojo/data/ObjectStore (since dojox grid doesn't support dojo/store), so it's not clear to me why you are even attempting to perform a query beyond that. You should see a network request to your service as soon as you call grid.startup().
If you're seeing a network request being made when you create the grid but you're not seeing results in the grid, chances are your service does not actually follow the conventions that dojo/store/JsonRest expects. See http://dojotoolkit.org/reference-guide/1.9/quickstart/rest.html for information on what is expected in requests and responses.
If you're actually asking how to tell the grid to use a different store at some point in the future, call grid.setStore(newstore).
Just wondering if anyone can help me with this issue. I have a Gridx connected to a JSONRest store. It works but when the grid starts up it seems to make a call to my server. I dont want this to happen. The server call takes two parameters and i only want this to be called when i query the store.
my code:
var restStore = new
dojo.store.JsonRest({target: "search"});
grid = new Grid({
id: 'grid',
cacheClass: Cache,
store: restStore,
autoHeight:true,
pageSize: 10,
modules: [
Pagination,
PaginationBar
],
paginationBarSizes: [10, 25, 50],
paginationBarVisibleSteppers: 4,
paginationBarGotoButton: false,
paginationBarDescription: true,
structure: [
{id: "description", field: 'description', width: '100%',
formatter: formatter,
}
]
});
query to the store which works
grid.model.clearCache();
grid.store.query({term : term, category : category}).then(function(results){
});
Also if i have the gridx inside another widget, it gets called again when the other widget starts up.
Any body any ideas how i get around this?
Gridx takes a 'query' parameter in it's initialization arguments, which sets initial query for the store. gridx queries the store on startup to populate itself for the first time. just specify
.......
query: {term : term, category : category},
......
in gridx initialization and it will perform that query for you on startup to populate your grid
I got some problems loading data into a form which I pushed onSelect.
(loading details for a specific list item)
onProductSelect: function(_dataView, _record)
{
Ext.getCmp('products').push({
title: _record.data.name,
data: _record.data,
styleHtmlContent: true,
xtype: 'productDetails'
});
}
I am pushing another view (productDetails) onto my productView (which is a navigationView). The data (_record.data) is available in the new pushed view via
tpl: '{someField}'
Now I'd like to know how to get this data (the fields data) into a textfield or a button (or sth like this) of a form.
If someone has a better idea how to get the data into the view/form or how to change the views (from list to detail) please let me know :)
here are some suggestions to your code:
1.use of underbar ('_') inside Sencha Touch is meant for variables which have get/set/apply/update. Although you are using local variables, it is best practice.
2.the word '_record' hopefully is a record. If so then you should use:
name = _record.get('name');
data = _record.getData();
The best way to fill a form is to use a formpanel and add the values to the formpanel, while all fields have a popper name assigned:
If your data are:
data = {name: 'Kurt001', password: '12er51wfA!'}
You could use this:
Ext.define('App.view.ProductDetails', {
extend: 'Ext.form.Panel',
xtype: 'productdetails',
config: {
cls: 'product-details',
scrollable: null,
layout: 'vbox',
defaults: {
labelAlign: 'top',
clearIcon: false
},
items: [{
xtype: 'textfield',
name: 'name'
}, {
xtype: 'passwordfield',
name: 'password'
}, {
xtype: 'button',
itemId: 'btnLogin'
}]
}
});
And to add the data simply use:
Ext.Viewport.down('.productdetails').setValues(data);
Alternative:
var view = Ext.Viewport.down('.productdetails')
view.down('.textfield').setValue(data.name);
view.down('.passwordfield').setValue(data.password);
Alternative
view.down('.field[name=name]').setValue(data.name);
view.down('.field[name=password]').setValue(data.password);
To get the data from one view to the next you can follow different options:
1.Set the data to the current view and grab them from that view. It looks like you have a list. So you can apply the data to the list:
view.down('.list').myData = data;
Extended version would be to create a custom list with myData inside the config.
That way you could use:
view.down('.list').setMyData(data);
or in your case
_dataview.setMyData(data);
2.Use a store. As you are passing a record already you might want to add a selected field to your store model and simply set the flag.