ExtJs4+: can calculated model field be editable? - extjs4

My model has two data fields: persistent and calculated:
Ext.define('My.model.Value', {
extend: 'Ext.data.Model',
idProperty: 'id',
fields: [
{ name: 'id', type: 'auto' },
{ name: 'percentage', type: 'float' }, // values in 0..1 range
{ name: 'percentageDecimal', type: 'float', persist: false,
calculate: function(v) {
v = v.percentage;
return Ext.isNumber(v) ? v * 100.0 : v;
}
}
]
});
The percentageDecimal field is used in a grid and it is editable.
Question: how can I change my model to automatically update percentage field everytime the percentageDecimal is updated?
I use ExtJs 5.0.1.

I used #adaskos' suggestion as follows:
Ext.define('My.model.Value', {
extend: 'Ext.data.Model',
idProperty: 'id',
fields: [
{ name: 'id', type: 'auto' },
{ name: 'percentage', type: 'float' }, // values in 0..1 range
{ name: 'percentageDecimal', type: 'float', persist: false,
calculate: function(v) {
v = v.percentage;
return Ext.isNumber(v) ? v * 100.0 : v;
}
}
],
set: function (fieldName, value, options) {
if (Ext.isString(fieldName)) {
// single field update
if (fieldName === 'percentageDecimal') {
this.set('percentage', Ext.isNumber(value) ? 0.01 * value : value);
return;
}
} else {
// multiple fields update
if (Ext.isDefined(fieldName.percentageDecimal)) {
var data = Ext.clone(fieldName);
data.percentage = Ext.isNumber(data.percentageDecimal)
? 0.01 * data.percentageDecimal
: data.percentageDecimal;
delete data.percentageDecimal;
this.set(data);
return;
}
}
this.callParent(arguments);
}
});

I don't know if they added an automated way to do this in 5.0.1, but you can always override the set method and whenever an update occurs to percentageDecimal, you recalculate the percentage.
An alternative I prefer: if you expect enough updates but all you want is to display it in a grid, you can remove the extra computed field from the model and set your column with dataIndex: 'percentageDecimal' and change its renderer function to display it as you like (as a decimal).
Like below:
... , { text: 'Percentage', dataIndex: 'percentageDecimal'
, renderer: function (v) {
return Ext.isNumber(v) ? v * 100.0 : v;
}
}

You should use the config options depends to have this updated automatically!
And use the function convert instead of calculate (not sure if it work with calculate, i need to test)
See http://docs.sencha.com/extjs/5.1/5.1.0-apidocs/#!/api/Ext.data.field.Field-cfg-depends

Related

vue-good-table custom sorting

I am using vue-good-table and have the following code so far:
<vue-good-table :columns="columns" :rows="rows"
styleClass="vgt-table condensed striped bordered"
:sort-options="sortOptions"
:search-options="searchOptions"
:select-options="selectOptions"
#on-selected-rows-change="selectionChanged">
</vue-good-table>
sortOptions: {
enabled: true,
initialSortBy: { field: "date", type: "desc" },
}
columns() {
return [
{
label: "Name",
field: "name",
},
{
label: "CreationDate",
field: "date",
type: "date",
formatFn: function (value) {
return value != null ? moment(value).format('YYYY-MM-DD') : null;
},
sortFn(x, y) {
x = moment(x);
y = moment(y);
return x.unix() < y.unix() ? -1 : x.unix() > y.unix() ? 1 : 0;
},
},
]
}
Sorting works fine so far, and there are three states: 'asc', 'desc' and 'none'.
However i would like to achieve the following:
When clicking the column header and the current sorting type is 'none' for any of the columns, i would like to have the data sorted as defined in the initialSortBy property in the sortOptions. So sorted by date in desc order.
I tried using the #on-sort-change event but don't really know how to proceed further as i am quite new to Vue.
onSortChange(params) {
console.log('on-sort-change:');
console.log(params[0].field)
console.log(params[0].type)
if (params[0].type == 'none') {
console.log("default sort")
//TODO sort data as defined in initial sort
}
}

Display the time picker value in the textfield using sencha touch 2

Ext.define("Datetimepicker.view.Main", {
extend: 'Ext.form.Panel',
requires: [
'Ext.TitleBar',
'Ext.field.DatePicker',
'Ext.Spacer',
'Ext.Picker'
],
config: {
fullscreen:'true',
title:'DatatimePicker',
items: [
{
xtype:'fieldset',
items:[
{
xtype:'datepickerfield',
label:'Birthday',
picker:{
yearFrom:1980,
yearTo:2015
},
name:'birthday',
value:new Date()
},
{
xtype:'textfield',
label:'Time',
value:''
//In this textfield i want to display the time picker value
}
}
]
},
{
items:[
{
xtype:'spacer'
},
{
text: 'setValue',
handler: function() {
var datePickerField = Ext.ComponentQuery.query('datepickerfield')[0];
var randomNumber = function(from, to) {
return Math.floor(Math.random() * (to - from + 1) + from);
};
datePickerField.setValue({
month: randomNumber(0, 11),
day : randomNumber(0, 28),
year : randomNumber(1980, 2015)
});
}
},
{ xtype:'spacer'}
]
}
]
}
});
By using above code I'm getting the value of datepicker which successfully display in the first textfield.In the same way I want to display that value of datepicker in another textfield.
Can anyone help me to do this ...thanks in advance
You can do it by setting the value of the textfield every time your picker's value has been changed so here is a solution:
items: [
{
xtype: 'datepickerfield',
label: 'Birthday',
name: 'birthday',
value: new Date(),
listeners: {
change: function(picker, value) {
// This function use to prepend 0 to the month which less than October
function minTwoDigits(n) {
return (n < 10 ? '0' : '') + n;
}
var date = value.getDate(), // Get date's value
month = value.getMonth(); // Get month's value
month += 1; // Increase the number of month by 1 since the index started with 0
var formatMonth = minTwoDigits(month),
year = value.getFullYear(), // Get year's value
formatDate = formatMonth.concat("/",date,"/",year); // Concatenate string
Ext.ComponentQuery.query('#textfield')[0].setValue(formatDate); // Set the value of the textfield with itemID equal to textfield
}
}
},
{
xtype:'textfield',
label:'time',
itemId: 'textfield',
value:''
}
]
If you don't understand anything, feel free to ask. Hope it helps :)

Kendo UI BarChart Data Grouping

Not sure if this is possible. In my example I am using json as the source but this could be any size. In my example on fiddle I would use this data in a shared fashion by only binding two columns ProductFamily (xAxis) and Value (yAxis) but I would like to be able to group the columns by using an aggregate.
In this example without the grouping it shows multiple columns for FamilyA. Can this be grouped into ONE column and the values aggregated regardless of the amount of data?
So the result will show one column for FamilyA of Value 4850 + 4860 = 9710 etc.?
A problem with all examples online is that there is always the correct amount of data for each category. Not sure if this makes sense?
http://jsfiddle.net/jqIndy/ZPUr4/3/
//Sample data (see fiddle for complete sample)
[{
"Client":"",
"Date":"2011-06-01",
"ProductNumber":"5K190",
"ProductName":"CABLE USB",
"ProductFamily":"FamilyC",
"Status":"OPEN",
"Units":5000,
"Value":5150.0,
"ShippedToDestination":"CHINA"
}]
var productDataSource = new kendo.data.DataSource({
data: dr,
//group: {
// field: "ProductFamily",
//},
sort: {
field: "ProductFamily",
dir: "asc"
},
//aggregate: [
// { field: "Value", aggregate: "sum" }
//],
//schema: {
// model: {
// fields: {
// ProductFamily: { type: "string" },
// Value: { type: "number" },
// }
// }
//}
})
$("#product-family-chart").kendoChart({
dataSource: productDataSource,
//autoBind: false,
title: {
text: "Product Family (past 12 months)"
},
seriesDefaults: {
overlay: {
gradient: "none"
},
markers: {
visible: false
},
majorTickSize: 0,
opacity: .8
},
series: [{
type: "column",
field: "Value"
}],
valueAxis: {
line: {
visible: false
},
labels: {
format: "${0}",
skip: 2,
step: 2,
color: "#727f8e"
}
},
categoryAxis: {
field: "ProductFamily"
},
legend: {
visible: false
},
tooltip: {
visible: true,
format: "Value: ${0:N0}"
}
});​
The Kendo UI Chart does not support binding to group aggregates. At least not yet.
My suggestion is to:
Move the aggregate definition, so it's calculated per group:
group: {
field: "ProductFamily",
aggregates: [ {
field: "Value",
aggregate: "sum"
}]
}
Extract the aggregated values in the change handler:
var view = products.view();
var families = $.map(view, function(v) {
return v.value;
});
var values = $.map(view, function(v) {
return v.aggregates.Value.sum;
});
Bind the groups and categories manually:
series: [ {
type: "column",
data: values
}],
categoryAxis: {
categories: families
}
Working demo can be found here: http://jsbin.com/ofuduy/5/edit
I hope this helps.

Sencha Touch Grouper Property Conversion

I have a list reading from a Json store which contains a grouper on a field of type int. This field is called "req" in the sample model below. However, rather than group by the int value, I would like to assign a text value instead, so for example, in case of "1" I would group by "Yes" and in case of "0" I would group by "No". The conversion can be hard coded as it will not change. Where do I make this conversion in my code? Thanks for your help
Ext.define('MyApp.store.MyStore', {
extend: 'Ext.data.Store',
requires: [
'MyApp.model.MyData'
],
config: {
model: 'MyApp.model.MyData',
storeId: 'MyStore',
proxy: {
type: 'ajax',
url: '/path/to/data.json',
reader: {
type: 'json',
rootProperty: 'items'
}
},
grouper: {
property: 'req',
sortProperty: 'req'
},
groupDir: 'DESC'
}
});
Model:
Ext.define('Mypp.model.MyModel', {
extend: 'Ext.data.Model',
config: {
fields: [
{
name: 'example',
type: 'string'
},
{
name: 'req',
type: 'int'
}
]
}
});
Add to the Model a calculated field with convert() function:
Ext.define('Mypp.model.MyModel', {
extend: 'Ext.data.Model',
config: {
fields: [
{
name: 'example',
type: 'string'
},
{
name: 'req',
type: 'int'
},
{
name: 'reqDisplay',
type: 'string',
convert: function (value, record) {
if (value == null) {
var req = record.get('req');
value = req ? 'Yes' : 'No'
}
return value;
}
}
]
}
});
... and use it instead
grouper: {
property: 'reqDisplay',
sortProperty: 'reqDisplay'
},
Cheers, Oleg

ExtJs4 Model with different poxy url's

I have defined a model which I want to use twice but with a different url int he proxy (in fact only the id differs) But how can I manage this?
Ext.define('TesterModel', {
extend: 'Ext.data.Model',
autoLoad: false,
fields: [
{ name: 'prename', type: 'string' },
{ name: 'lastname', type: 'string' },
{ name: 'dept', type: 'string' },
{ name: 'rackName', type: 'string' },
{ name: 'rackIP' , vtype:'IPAddress'}],
proxy: {
type: 'ajax',
url: 'php/getData_db.php?id=',
reader: {
type: 'json',
messageProperty: 'message',
root: 'data',
}
},
constructor: function() {
UrlParams=document.URL.split("?");
if(UrlParams.length > 1) {
SingleUrlParams=Ext.Object.fromQueryString(UrlParams[1]);
this.proxy.url = this.proxy.url + SingleUrlParams.right;
console.log(this.proxy.url);
}
return this;
}});
Ext.ModelMgr.getModel('TesterModel').load(0, { // load user with ID of "0"
success: function(tester) {
var rightPanel=Ext.getCmp('rightTester');
rightPanel.loadRecord(tester); // when tester is loaded successfully, load the data into the form
}
});
I thought that the constructor will be done before loading, but nope, it is done after. It's weired to me.
Any hints, please?
(the main URL it's like: .../index.html?left=xx&right=yy )
so I want to fill up a panel on the left with the one id, and a panel on the right window side eith th right id.
Thanks!
Try .getProxy().url = "what/ever.php"