I dont know how to tell but i still dont get it right. This is my code :
Ext.define("PL.view.list.listOnly", {
extend: 'Ext.form.Panel',
alias: 'widget.listlistonly',
config:{
fullscreen: true,
title: 'Master barang',
items:[{
xtype : 'panel',
layout: {
type: 'fit',
align : 'stretch',
pack : 'start',
},
defaults: {
allowBlank: true,
msgTarget: 'side',
labelWidth: 60,
margin: '5 5 5 5',
},
items:[{
xtype:'list',
height: '100%',
masked: { xtype: 'loadmask',message: 'Loading...' },
scrollable: {
direction: 'vertical',
directionLock: true
},
store:{
fields: [{
name:'szName',
},{
name:'szProductID',
},{
name:'szBarcode',
}],
autoLoad: true,
pageSize: 20,
proxy: {
type: 'ajax',
url: 'store/product/loadData.php',
pageParam: 'param',
reader: {
type: 'json',
rootProperty: 'topics',
}
}
},
variableHeights: false,
useComponents: true,
itemTpl: '<div class="myButton">' +
'<input type="button" name="{szProductID}" value="Edit" ' +
'style="padding:3px;">' +
'</div>' +
'<div class="myContent">'+
'<div>PLU : <b>{szProductID}</b>, Barcode: <b>{szBarcode}</b></b></div>' +
'<div>Nama: <b>{szName}</b></div>' +
'</div>',
}]
}],
scrollable : false,
},
});
And this is what i get from json :
{"topics": [{
"szProductID": 1001,
"szBarcode": 002,
"szName": "STANDARD BLACK"
},{
"szProductID": 1100420020479,
"szBarcode": 1100420020479,
"szName": "STANDARD BLUE"
}],
"totalCount": 2}
As you can see, there is a '002' (szBarcode field), and this is my problem. The list only show '2' instead of '002'. This should show '002' as szBarcode but i dont know how to fix this.
Any help would appreciate
The problem is that barcode: 002 and barcode: 2 mean exactly the same in JSON format. Prepended zeros for numbers just don't count.
There are about four different things you can possibly do.
If you can access the server code, you can change it to send you the barcode field as a string (barcode:"002").
If your barcode ALWAYS has a certain length (say 13), you can work with the number you have, and pad it to the required length again. Please be aware that after a certain length, there are precision issues because numbers are stored in fixed-length memory, while a string's memory always is as long as needed. Sample conversion code:
name:'barcode',
convert:function(value) {
var str = value.toString(),
pad = "0000000000000"; // expand to length of your number
return pad.substring(0, pad.length - str.length) + str);
}
(Bonus: This code does not break when someone does (1) afterwards...)
If you have no other barcode fields in your JSON, you could use a regular expression to add the necessary quotes to the JSON client-side before deserialization.
You could override ExtJS's default JSON serialization/deserialization code. Please note that this is not as easy as it sounds and may have quite some side effects. This is the only suitable way if you want to send barcode as zero-padded JSON numbers back to the server as well.
Related
I have a page containing a ExtJS 4.2.2 dataStore and gridPanel showing items created using information from various tables in a MySQL database.
The purpose of the generated grid is to provide a "confirmation" to the user before any information is actually generated in the database in a table separate to those that originated the initial information, as some items can be flagged to be imported; unflagged items are not imported. The page uses HTML, PHP (with CodeIgniter MVC framework) and ExtJS (which implies Javascript and JQuery).
With my current understanding of ExtJS, I would perform the necessary database insert or update by:
Saving all the changes in the grid to the store
Packaging the store's data into a multidimensional array, which is then assigned into a POST variable in some similar manner to a form
Perform a POST to the same page, picking up the POST variable
Loop through the POST information, passing each row's data to the model to perform the SQL query and INSERT/UPDATE as necessary.
I'm thinking this is a long-winded and most likely inefficient method for doing this; having previously worked with Kendo UI, I would have thought there is some form of "save" action on the store that simply calls a controller/model function that would act on the data in fewer steps.
Having looked at Ext.data.Store's numerous potential candidates (the commitChanges method, update event, the write event, store.sync etc.), I have to say I'm completely bewildered by how I could perform the kind of action I'm thinking of; I need to write the information to a table separate from those that generated the initial information, and none of the above seem to do that.
I would appreciate a "simple words" play-by-play of how to get the "dirty" data from the grid saved to the store, then the store data being passed to a MVC Controller-then-Model function that allows for update/insert to the DB (if that is the best way to do this) - I also appreciate that I will have to modify aspects of my ExtJS code, but what about my current setup isn't helping, if anything?
ExtJS code below renders the grid with data, and not much else:
Ext.Loader.setConfig({
enabled: true
});
Ext.Loader.setPath('Ext.ux', '../ux');
Ext.require([
'Ext.ux.CheckColumn'
]);
Ext.onReady(function(){
Ext.define('ConfirmationModel', {
extend: 'Ext.data.Model',
fields: [
'GroupName', // generated if not a member of a group, will eventually be retrieved if already existing in group by checking import table for JobNo, ItemNo and ItemTypeId
'ItemType',
'ItemTypeId',
'JobNo',
'ItemNo',
'ThicknessDepth',
'Cutter',
'CutterId',
'Source',
'Qty',
'Material',
'MaterialId',
'Type',
'TypeId',
'Work',
'WorkId',
'PaintInternal',
'PaintExternal',
'Notes',
'Documented',
'ImportDate', // fetched by checking import table for jobNo, itemNo and itemTypeId
'ImportCheck' // usually automatically checked if not yet imported
]
});
confirmationStore = Ext.create('Ext.data.Store',{
model: 'ConfirmationModel',
autoLoad: true,
proxy: {
// load using HTTP
type: 'ajax',
url: '<?= $site_url ?>Production/ConfirmationJSON/<?php echo $job_no ?>', // currently pulls all the information from three separate tables, pushes to object arrays then converts to and returns as JSON; will also check import table for existing entries as further work
pageParam: false, //to remove param "page"
startParam: false, //to remove param "start"
limitParam: false, //to remove param "limit"
noCache: false, //to remove param "_dc"
reader: {
type: 'json',
model: 'ConfirmationModel'
}
},
groupField: 'GroupName'
});
confirmationGrid = Ext.create('Ext.grid.Panel', {
width: 1200,
store: confirmationStore,
title: 'Import Confirmation',
tbar: [
{
xtype: 'button',
text: 'Update',
handler: function(){
// function to handle the save/update of information goes here?
document.location.href = '<?php echo site_url() ?>Production/Schedule'; // redirect to next page in steps
}
},
{
xtype: 'button',
text: 'Cancel',
handler: function(){
window.history.back();
}
}
],
columns: [
{ text: 'Item<br />No.', width:50, dataIndex: 'ItemNo' },
{ text: 'Job<br />No.', width: 65, dataIndex: 'JobNo' },
{ text: 'Item Type', width: 70, dataIndex: 'ItemType' },
{ text: 'Thickness<br />Depth', width: 65, dataIndex: 'ThicknessDepth' },
{ text: 'Cutter', width: 65, dataIndex: 'Cutter' },
{ text: 'Source', width: 65, dataIndex: 'Source' },
{ text: 'Qty', width: 40, dataIndex: 'Qty' },
{ text: 'Material', flex: 1, dataIndex: 'Material' },
{ text: 'Type', flex: 2, dataIndex: 'Type' },
{ text: 'Work', flex: 2, dataIndex: 'Work' },
{ text: 'Paint - Internal', flex: 2, dataIndex: 'PaintInternal' },
{ text: 'Paint - External', flex: 2, dataIndex: 'PaintExternal' },
{ text: 'Notes', flex: 2, dataIndex: 'Notes' },
{ text: 'Documented?', width: 75, dataIndex: 'Documented' },
{ text: 'Import<br />Date', width: 60, dataIndex: 'ImportDate' },
{
xtype: 'checkcolumn',
sortable: false,
header: 'Import?',
width: 50,
dataIndex:'ImportCheck'
}
],
features: [{
id: 'group',
ftype: 'groupingsummary',
groupHeaderTpl: '{name}',
enableGroupingMenu: false
}],
renderTo: Ext.get('sencha_confirmation')
});
});
There's no need to save data from the grid to the store, since the content you're seeing in the grid is there because it is already in the store (given that the store is the data provider for the grid).
To send the data in this format, you simply need to configure your proxy's writer's allowSingle: false. This will force the proxy to send through the records it is persisting as an array always, even if there is only one record.
Example:
proxy: {
writer: {
allowSingle: false
},
...
}
This can be accomplished by calling sync() on your store. Sync will automatically create a request to the url specified on your proxy, and will batch together new records, updated records, and deleted records. You can call this manually, or add autoSync: true to your store (I prefer controlling when it's called, but that's up to you).
Re: the MVC side of things, that's dependent on how your application is structured. For example, if you have a "save" button on the grid, you could bind to the button's click event, and in your controller listen for this click event and call your store's sync() method there. Of course, this is just an example: there are an number of events/conditions you could respond to and do the same thing.
I am using Highchart in my page and I wonder if I can make pie chart more dynamic. I want to make slices, where specific text in the name appears, to be shades of green.
Some code:
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
color: '#000000',
connectorColor: '#000000',
formatter: function() {
return '<b>'+ this.point.name +'</b>: '+ this.y;
}
},
showInLegend: true
}
},
colors:['#89ABD5','#3b73b9','#22436b','#08a5e1',
],
series: [{
color:'#89ABD5',
type: 'pie',
name: '',
data: []
},
{
color:'#3b73b9',
type: 'pie',
name: '',
data: []
},
{
color:'#22436b',
type: 'pie',
name: '',
data: []
},
{
color:'#08a5e1',
type: 'pie',
name: '',
data: []
},
]
I have names like: GOOD A, GOOD B, GOOD C, etc.., BAD A, BAD B, BAD C, etc.. and OTHER1, OTHER2, OTHER3, etc..
What I am trying to achieve is when, there is a text GOOD in the name, the slices should be in shades of green, while BAD -> shades of red. Other slices should be by default.
Data is get through getJSON.
This answer depends on how you are generating your series data to add to the chart. Why not put some logic in the series builder to change color based on text in string? Here is some psuedo-code:
//looping through your data elements that you want to be slices.
var sliceTitle;
var sliceColor;
var sliceData = [];
sliceTitle = anElement[i].name;
sliceColor = getColorMatch(sliceTitle);
sliceData = anElement[i].dataStuff;
series[i].name = sliceTitle;
series[i].color = sliceColor;
series[i].data = sliceData;
//continue loop.
...
function getColorMatch(titleText) {
if (titleText.indexOf("GOOD") !== -1) {
return "#somegreencolor"
}
if (titleText.indexOf("BAD") !== -1) {
return "#someredcolor"
}
if (titleText.indexOf("OTHER") !== -1) {
return "#someOthercolor"
}
}
Note that this assumes you do not have cases where the title contains both strings and is case sensitive.
Other cool stuff to do would be to get a palette of greens, reds, and other colors not red or green. Then when you return the color you need have it cycle through the list of available hues for that string title match. That way you wont get all the same depending on how bad/good the values are. For the "other" you can have a palette of blues/yellows. Again, picking one from the list and only repeating if you have more slices than you have colors in your list.
I have looked here for similar queries, and none quite answer my question, either in its entirety, or in a fashion I can understand.
I retrieve a string value from a MySQL database representing a datetime, i.e. "03 Oct, 2013 05:30:45PM" is represented as "20131003173045" in the database. This value is presented in a "Last Login" column in a Kendo Grid as a date. This is all contained within a PHP-oriented webpage using the MVC framework.
Previously I applied a date format in the SQL query to change the string from "20131003173045" to "03 Oct, 2013 05:30:45PM", but this gets presented in the KendoGrid as a string, meaning November Dates can appear before October dates, April dates come up first etc. This understandably is not the desired function, especially when trying to sort by this column.
Sample Code for the page rendering the KendoGrid:
<div class="div1">
<div>
<table id="listGrid"></table>
</div>
</div>
<script>
$(function() {
$("#grid").kendoGrid({
scrollable: false,
groupable: false,
sortable: {
mode: "multiple"
},
resizable: true,
pageable: true,
dataSource:
{
transport:
{
read: {
url: "<?= $site_url ?>Settings/Users/List",
dataType: "json"
},
parameterMap: function (model, operation) {
if (operation == "read") {
return model;
}
else if(model) {
return { "json" : kendo.stringify(model) };
}
else
return "";
}
},
pageSize: 20,
serverPaging: true,
serverSorting: true,
sort: { field: "LastLogin", dir: "desc" },
serverGrouping: true,
serverAggregates: false,
schema: {
total: "total",
data: "data",
groups: "groups"
}
},
toolbar: [ { title: "", template:'<a class="k-button k-button-icontext k-grid-add" href="<?= $site_url ?>Settings/Users/Add/">Add New User</a>' }],
columns: [
//{field: "Id", width: "40px"},
{field: "UserName", title: "Alias", width: "160px"},
{field: "ForeName", title: "Forename", width: "100px"},
{field: "SurName", title: "Surname", width: "160px"},
{field: "Initials", width: "80px"},
{field: "CrmId", title: "CRM ID", width: "100px"},
{field: "Dept", title: "Department", width: "100px"},
{field: "Position"},
// Below is the field in question
{field: "LastLogin", title: "Last Login", width: "160px"},
{field: "BlockedStatus", title: "Status", width: "90px"},
{ title: "", template:'<a class="k-button k-button-icontext k-grid-edit" href="<?= $site_url ?>Settings/Users/Update/#: Id #">Edit</a>' }
]
});
});
</script>
I've looked at the kendo.parseDate and kendo.toString, and combining the two, but can't seem to get anything to work; I either get "null" or "20131003173045", or the page doesn't load.
I can't change the database data, I can only format it as part of the SQL query, which is what I was doing initially.
I need the whole "20131003173045" string to become "03 Oct, 2013 05:30:45PM", and still be ordered in proper chronological order - how can I do this, and if the kendo.parseDate and kendo.toString are the correct tools to use, what am I doing wrong?
What I suggest is implement a schema.parse function that converts that MySQL format to a Date object and then use columns.format for formatting it.
The Schema would be:
schema : {
data : "data",
total : "total",
groups: "groups",
parse : function (d) {
$.each(d.data, function (idx, elem) {
elem.LastLogin = kendo.parseDate(elem.LastLogin, "yyyyMMddHHmmss");
});
return d;
}
}
Now, the columns definition for printing the date would define a format that is the one that you want.
{field: "LastLogin", title: "Last Login", width: "160px", format: "{0:dd MMM, yyyy hh:mm:sstt}" }},
I am trying to use javascript Highcharts to display a chart of rankings from JSON data. I can't seem to get the chart to display.
This is the javascript code:
$(document).ready(function() {
var options = {
chart: {
renderTo: 'drawing',
zoomType: 'x',
width: 900,
height: 222
},
exporting: {
enabled:true
},
title: {
text: url+' - '+keyword
},
credits: {
text: '****',
href: 'http://***/'
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
day: '%b %e '
}
},
yAxis: [{
//min: 1,
allowDecimals: false,
reversed: true,
///: .2,
//maxPadding: .2,
title: {
text: 'Rankings'
}
},],
tooltip: {
crosshairs: true,
shared: true
},
series: [{}]
};
var url = "http://*******/chart.php";
$.getJSON(url, function(data) {
$.each(data, function(arrayID,group) {
$.each(group.data, function(id,val) {
arg = val[0].replace(/Date.UTC\((.*?)\)/, '$1').split(',');
var timestamp = Date.UTC.apply( null , arg );
date=new Date(timestamp);
data[arrayID].data[id][0] = timestamp;
});
});
options.series[0].data = data;
var chart = new Highcharts.Chart(options);
});
});
Our PHP Script gives us this JSON:
[{"name":"Google Rank","data":[["Date.UTC(2013,04,05)","23"],["Date.UTC(2013,04,04)","23"],["Date.UTC(2013,04,03)","22"],["Date.UTC(2013,04,02)","24"],["Date.UTC(2013,04,01)","26"],["Date.UTC(2013,03,31)","24"],["Date.UTC(2013,03,30)","24"],["Date.UTC(2013,03,29)","25"],["Date.UTC(2013,03,28)","25"],["Date.UTC(2013,03,27)","25"],["Date.UTC(2013,03,26)","26"],["Date.UTC(2013,03,25)","25"],["Date.UTC(2013,03,24)","24"],["Date.UTC(2013,03,23)","-"],["Date.UTC(2013,03,22)","10"],["Date.UTC(2013,03,21)","10"],["Date.UTC(2013,03,20)","10"],["Date.UTC(2013,03,19)","10"],["Date.UTC(2013,03,18)","10"],["Date.UTC(2013,03,17)","10"],["Date.UTC(2013,03,16)","9"],["Date.UTC(2013,03,15)","9"],["Date.UTC(2013,03,14)","9"],["Date.UTC(2013,03,13)","9"],["Date.UTC(2013,03,12)","9"]],"visible":"true","pointInterval":"86400000","showInLegend":"false"},{"name":"Bing Rank","data":["Date.UTC(2013,2,9)",9],"visible":"true","pointInterval":"86400000","showInLegend":"false"}]
Note the JSON data represents numbers as strings which could be a problem.
PHP Code which generates the JSON data:
$googledata = array();
while($gkdata = mysql_fetch_assoc($keywordquery)){
$explodedate = explode("-", $gkdata['date']);
$year = $explodedate[0];
$month = $explodedate[1];
$day = $explodedate[2];
$googledata[] = array(
"".$year.",".$month.",".$day."",
$gkdata['grank'] //$gkdata['grank'] should be a number, but is sometimes a dash so it's cast to an accommodating datatype: string.
);
}
$chartdata = array(
array(
"name" => 'Google Rank',
"data" => $googledata,
"visible" => 'true',
"pointInterval" => '86400000',
"showInLegend" => 'false',
),
array(
"name" => 'Bing Rank',
"data" => array(
'Date.UTC(2013,2,9)',
9
),
"visible" => 'true',
"pointInterval" => '86400000',
"showInLegend" => 'false',
)
);
The Highcharts won't display anything other than the chart itself with no data. The Date.UTC(2013,03,12) is supposed to go on the X-Axis & the number next to it is supposed to be the rank number. Can anyone see what is wrong?
The chart takes data as [x,y]. You just need to reverse the order of your data to ['value',datestamp'] if you want the date to be on the y axis.
Edit:
I am not sure from the text what the problem you are having is, but one problem that will arise from your code is that your number data values are being returned as strings, in quotes.
You will need to cast them as integers in your php before json encoding in order for them to come through unquoted, as integers.
You should be seeing an error from this: http://www.highcharts.com/errors/14
You are expecting $gkdata['grank'] to always return a number, it sometimes returns a dash -. The Array Object is using the datatype which best represents the data, and it chooses string. If you want to force it as int, you'll have to use a data structure that only allows integers to be put in it. Then it will puke when you try to put in a dash, which it should be doing, because how do you plot a DASH on a chart?
Had you taken off your blindfold, and looked at the error HighCharts returned to you, you would see this:
Highcharts Error #14 String value sent to series.data, expected Number
This happens if you pass in a string as a data point, for example in a setup like this:
series: [{
data: ["3", "5", "1", "6"]
}]
Highcharts expects the data values to be numbers. The most common reason for this is that data is parsed from CSV or from a XML source, and the implementer forgot to run parseFloat on the parsed value.
For performance reasons internal type casting is not performed, and only the first value is checked (since 2.3).
So fix your code to make grank always a number. HighCharts won't plot strings for performance reasons.
I am trying to get a chart to display using Highcharts. I am pulling data from a mysql db with php and creating arrays of data and inserting them into the Highcharts Jquery.
I need to display the data in this format (not a graphical representation):
mon = 0
tues = 4
wed = 2
thu = 0
fri = 4
sat = 20
sun = 45
With Monday always being first and Sunday last.
But my data is pulled from the DB using a date range and I may only get an array from the database that looks like this:
Array
(
[0] => Array
(
[TotalClicksPerDay] => 35
[weekDay] => 4 (which is my case is Thurs)
)
}
So in this case would need to display:
(the TotalClicksPerDay is the important bit)
mon = 0
tues = 0
wed = 0
thu = 35
fri = 0
sat = 0
sun = 0
How would I add the array values to Highchart and still get the days of the week to show and position 'thu's' value in the correct place?
has anyone done anything similiar? Can you point me on the right direction?
I don't even know how to start.
Here is my highcharts Jquery just so you can see how I am using the arrays:
jQuery(document).ready(function($) {
var chart;
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'column'
},
title: {
text: '$type'
},
subtitle: {
text: 'Xbox landscape'
},
xAxis: {
categories:
$categoryGraph //php array
,labels: {
rotation: 0,
align: 'center',
x: 0,
y: 20,
style: {
fontSize: '8px',
fontFamily: 'Verdana, sans-serif'
}
}
},
yAxis: {
min: 0,
title: {
text: 'Clicks'
}
},
legend: {
enabled: false
}, /*{
layout: 'Vertical',
backgroundColor: '#FFFFFF',
align: 'left',
verticalAlign: 'top',
x: 0,
y: 30,
floating: false,
shadow: true
},*/
tooltip: {
formatter: function() {
return ''+
this.x +': '+ this.y +' Clicks';
}
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
}
},
series: [{name: '$type', data:[$clickTotalArray //php array }]
});
});
});
You are asking for how to parse your data into something that highcharts understands?
Well, the main dynamic options that you want to set correctly would be the xAxis.categories and the series.data, which you seem to have figured out already.
categories
needs to be an array of strings, nothing more or nothing less will be accepted.
eg:- categories=['Mon','Tue','Wed']
data
needs to be an array of array or array of objects or array of values. See documentation for more details
Since your data is mostly simple values, with the xValue being a string and hence falling into categories, your data object needs to be an array of numbers.
eg:- data=[100,200,300]
So now we have the final form of how your data would look like, we need to parse the available data structure/object graph into this form. You have an option to either do this in PHP or JavaScript.
This is how you can do it in javascript, make sure to do this before calling the Highchart constructor, and use the derived objects while setting the options.
var superData = [{
propertyA: 'A',
propertyB: 10
}, {
propertyA: 'B',
propertyB: 15
}, {
propertyA: 'C',
propertyB: 1
}];
var seriesData = [],
categories = [];
for (var i = 0; i < superData.length; i++) {
//you may want to do a parseInt/parseFloat it this value is a string
seriesData.push(superData[i].propertyB);
categories.push(superData[i].propertyA);
}
...
xAxis: {
categories: categories
},
series: [{
name: 'serie',
type: 'column',
data: seriesData
}]
...
Parsing complex JSON into highchart form | Highchart & Highstock # jsFiddle
Refer convert mysql resultset into a (name, data) object to be fed into HighCharts to see how a similar thing can be done in PHP