Is possible to include somehow multiple rest/json request in the same store?
For example I have this api that return json objects:
http://api1.domain.com
{"name":"john"},{"name:"harry"}
http://api2.domain.com
{"name":"peter"},{"name:"fred"}
I want to merge the results from api1 and api2 into one store in order to process it in a single view all concatenated. Result:
{"name":"john"},{"name:"harry"},{"name":"peter"},{"name:"fred"}
Or maybe not concatenated but I can show in a single view calling this two api at the same time:
john
harry
peter
fred
Is this possible?
I'm trying this with no success:
Ext.application({
name: 'sencha',
views: ['Main1'],
models:['AdModel'],
stores:['AdStore1','AdStore2'],
launch: function () {
var store1Obj = Ext.getStore('AdStore1');
var store2Obj = Ext.getStore('AdStore2');
store1Obj.each(function(record){
var copiedRecord = record.copy();
store2Obj.add(copiedRecord);
});
Ext.create('Ext.DataView', {
fullscreen: true,
store: store2Obj,
itemTpl: '<tpl for="."><div><strong>{name}</strong></div></tpl>'
});
}
});
Firstly you are using the wrong syntax for the each method of a store http://docs-origin.sencha.com/touch/2.4/2.4.1-apidocs/#!/api/Ext.data.Store-method-each
Then it is simple to add 2 different data sources together in the same store.
Ext.application({
name: 'Fiddle',
launch: function() {
// Set up a model to use in our Store
Ext.define("User", {
extend: "Ext.data.Model",
config: {
fields: [{
name: "name",
type: "string"
}]
}
});
// Setup the stores
var myStore1 = Ext.create("Ext.data.Store", {
model: "User",
data: [{
"name": "john"
}, {
"name": "harry"
}],
autoLoad: true
});
var myStore2 = Ext.create("Ext.data.Store", {
model: "User",
data: [{
"name": "peter"
}, {
"name": "fred"
}],
autoLoad: true
});
// Loop through each record of store2 adding it to store1
myStore2.each(function(item, index, length) {
myStore1.add(item);
});
Ext.create("Ext.List", {
fullscreen: true,
store: myStore1,
itemTpl: "{name}"
});
}
});
Demo: https://fiddle.sencha.com/#fiddle/g6n
Related
I'm trying to keep the filter value into KendoGrid and reuse it on relaod.
I find some code sample but doesn't working. I used getOptions to store values into localStorage. It's working. I have values into localStorage["kendo-grid-options"]. On reload, value appears into filters on header grid but data don't load. Error in the consoel is :
[! - SessionID: q0pbq0zsol3mjsxtd5mlendu, PageInstanceID: d11a8e2e-d716-43a0-8f4e-679eb87ad167, DateTime: 04/20/2022 20:53:10.894] Message: Uncaught
TypeError: Cannot read properties of undefined (reading 'data')
Impossible to find solution. If somebody has en idea... :)
My code is the following
function LoadSampleQualityControlPlanGridSummary(control,params) {
control.dataSource = new kendo.data.DataSource({ transport: {
read: function (options) {
GetDsBySp("sp_HMI_GetSampleControlPlanList", params, options.success);} }, schema: { model: {
id: "qm_spec_id" }, fields: {
qm_spec_desc: {
type: "string"
},
plan_name: {
type: "string"
} } } }); }
function InitSampleQualityControlPlanSummaryGrid(control) {
control.columns = [ { field: "qm_spec_name", title:
"Name") }, { field: "qm_spec_desc", title: "description")
}, { field: "plan_name", title: "Plan", } ]; }
//On load
_controls.SampleControlPlanSummary = control.findByXmlNode("GSQCP");
_controls.$SampleControlPlanSummary = $(_controls.SampleControlPlanSummary.domElement).data("kendoGrid");
InitSampleQualityControlPlanSummaryGrid(_controls.SampleControlPlanSummary);
var options = localStorage["kendo-grid-options"];
if (options) {
var parsedOptions = JSON.parse(options);
_controls.$SampleControlPlanSummary.setOptions(parsedOptions); _controls.$SampleControlPlanSummary.setDataSource(gridData);
} LoadSampleQualityControlPlanGridSummary(_controls.SampleControlPlanSummary,
paramControl);
Im sending my json data through controller like following:i have written the query here just to prevent making it complicated and messy :
My Controller Returning This:
public JsonResult powerConverter(string regionalManager)
foreach (DataRow dt in dt_power_conv.Rows)
{
_powerConv.turbineName.Add(dt["turbine_name"].ToString());
_powerConv.duration_hrs.Add(double.Parse(dt["duration_hrs"].ToString()));
_powerConv.abb_conv.Add(dt["abb_conv"].ToString());
_powerConv.eei_conv.Add(dt["eei_conv"].ToString());
_powerConv.leit_drive_conv.Add(dt["leit_drive_conv"].ToString());
}
return Json(_powerConv, JsonRequestBehavior.AllowGet);
}
in my view I get it with an Ajax call and simply bind my chart with it:
$.ajax({
dataType: "json",
type: "POST",
url: "#Url.Action("powerConverter","Ranking")",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ "regionalManager": tmpString }),
success: function (result) {
debugger;
$("#powerChart").kendoChart({
dataSource: {
data: result
},
chartArea: {
background: "#fcfcfc",
},
series: [{
axis: "l100km",
type: "column",
// name: "DURATION",
color: "#008080",
field: "duration_hrs",
categoryField: "turbineName"
},
],
categoryAxis: {
axisCrossingValue: [0, 20],
majorGridLines: {
visible: false
},
line: {
visible: true
},
labels: {
rotation: 340
},
},
tooltip: {
visible: true,
// majorUnit:10,
template: " #= value #"
},
});
}
});
I also posted the screen shot of my json,but still its not working,i set the categoryField and field with the exact name im getting from json but the chart shows nothing
It looks like the controller is returning two arrays, one for errorDuration and one for turbineName. Try changing the controller to return an array of objects.
You would want a review of returned json to show
[0] = { duration: 1, turbine: "a" }
[1] = { duration: 2, turbine: "b" }
[2] = { duration: 3, turbine: "c" }
In the chart the config settings for the series the field names have to match exactly the property names of the data elements, thus
field: "duration",
categoryField: "turbine",
Added
The controller code appears to be populating a list of a model class whose fields are also lists. Try updating it to return the Json for a list of objects
For quickness this example shows how using anonymous objects. Strongly typed objects are highly recommended for robustness and Visual Studio intellisense. The field names that you use in your kendo chart configuration will be "turbine_name" and "duration_hours"
// This technique copied from #Paul Rouleau answer to
// https://stackoverflow.com/questions/612689/a-generic-list-of-anonymous-class
// initialize an empty list that will contain objects having two fields
var dataForJson = new List<Tuple<string, double>>()
.Select(t => new {
turbine_name = t.Item1,
duration_hours = t.Item2 }
).ToList();
// go through data table and move data into the list
foreach (DataRow row in myDataTable.Rows)
{
dataForJson.Add (new {
turbine_name = (string)row["turbine_name"],
duration_hours = (double)row["duration_hours"]
});
}
return Json(dataForJson, JsonRequestBehavior.AllowGet);
Note, if you do further research you will find numerous other ways to convert a data table into a Json
I am able to get tree structure for the user stories but want it same for defects also which are related to particular user story so that at a singe screen I can see both user stories and the related defects.
You may use features: [{ftype:'groupingsummary'}] of ExtJS to group defects by user stories and even summarize by some other field, in the code below by PlanEstimate. To group defects by user story Requirement attribute on defect is used, which points to the related story. In this example defects are filtered by Iteration.
Ext.define('CustomApp', {
extend: 'Rally.app.TimeboxScopedApp',
componentCls: 'app',
scopeType: 'iteration',
comboboxConfig: {
fieldLabel: 'Select Iteration:',
labelWidth: 100
},
onScopeChange: function() {
this.makeStore();
},
makeStore: function() {
var filter = Ext.create('Rally.data.wsapi.Filter', {
property: 'Requirement',
operator: '!=',
value: null
});
filter= filter.and(this.getContext().getTimeboxScope().getQueryFilter());
filter.toString();
Ext.create('Rally.data.wsapi.Store', {
model: 'Defect',
fetch: ['ObjectID', 'FormattedID', 'Name', 'State', 'Requirement', 'PlanEstimate'],
autoLoad: true,
filters: [filter],
listeners: {
load: this.onDataLoaded,
scope: this
}
});
},
onDataLoaded: function(store, records){
if (records.length === 0) {
this.notifyNoDefects();
}
else{
if (this.notifier) {
this.notifier.destroy();
}
var that = this;
var promises = [];
_.each(records, function(defect) {
promises.push(this.getStory(defect, this));
},this);
Deft.Promise.all(promises).then({
success: function(results) {
that.defects = results;
that.makeGrid();
}
});
}
},
getStory: function(defect, scope) {
var deferred = Ext.create('Deft.Deferred');
var that = scope;
var storyOid = defect.get('Requirement').ObjectID;
Rally.data.ModelFactory.getModel({
type: 'HierarchicalRequirement',
scope: this,
success: function(model, operation) {
fetch: ['FormattedID','ScheduleState'],
model.load(storyOid, {
scope: this,
success: function(record, operation) {
var storyScheduleState = record.get('ScheduleState');
var storyFid = record.get('FormattedID');
var defectRef = defect.get('_ref');
var defectOid = defect.get('ObjectID');
var defectFid = defect.get('FormattedID');
var defectPlanEstimate = defect.get('PlanEstimate');
var defectName = defect.get('Name');
var defectState = defect.get('State');
var story = defect.get('Requirement');
result = {
"_ref" : defectRef,
"ObjectID" : defectOid,
"FormattedID" : defectFid,
"Name" : defectName,
"PlanEstimate" : defectPlanEstimate,
"State" : defectState,
"Requirement" : story,
"StoryState" : storyScheduleState,
"StoryID" : storyFid
};
deferred.resolve(result);
}
});
}
});
return deferred;
},
makeGrid: function() {
var that = this;
if (this.grid) {
this.grid.destroy();
}
var gridStore = Ext.create('Rally.data.custom.Store', {
data: that.defects,
groupField: 'StoryID',
pageSize: 1000,
});
this.grid = Ext.create('Rally.ui.grid.Grid', {
itemId: 'defectGrid',
store: gridStore,
features: [{ftype:'groupingsummary'}],
minHeight: 500,
columnCfgs: [
{
text: 'Formatted ID', dataIndex: 'FormattedID', xtype: 'templatecolumn',
tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate')
},
{
text: 'Name', dataIndex: 'Name',
},
{
text: 'State', dataIndex: 'State',
summaryRenderer: function() {
return "PlanEstimate Total";
}
},
{
text: 'PlanEstimate', dataIndex: 'PlanEstimate',
summaryType: 'sum'
},
{
text: 'Story', dataIndex: 'Story',
renderer: function(val, meta, record) {
return '' + record.get('Requirement').FormattedID + '';
}
},
{
text: 'Story Schedule State', dataIndex: 'StoryState',
}
]
});
this.add(this.grid);
this.grid.reconfigure(gridStore);
},
notifyNoDefects: function() {
if (this.grid) {
this.grid.destroy();
}
if (this.notifier) {
this.notifier.destroy();
}
this.notifier = Ext.create('Ext.Container',{
xtype: 'container',
itemId: 'notifyContainer',
html: "No Defects found matching selection."
});
this.add( this.notifier);
}
});
I have this treeview wich can have a variable number of children (some nodes can have up to 3 generations of children, some may have only one etc)
What I'm trying to do is expand a certain node when the treeview is loaded. And I have 2 problems:
1) I can't find an event/callback so that I know when the treeview is ready
2) The expand function doesn't always work ( I'll explain )
This is my treeview:
function InitializeTreeview() {
var Children_Merchants = {
transport: {
read: {
url: function (options) {
return kendo.format(websiteRootUrl + '/Merchants/Merchants/?hasParents={0}', hasParent);
}
}
},
schema: {
model: {
model: {
id: "ID",
hasChildren: true,
children: Children_Merchants
}
}
}
};
var Brandowners = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: kendo.format(websiteRootUrl + '/Merchants/GetBrandowners?databaseID={0}', selectedDatabaseID)
}
},
//change: ExpandNode, - if I call expand node like this, it works.
schema: {
model: {
id: "ID",
hasChildren: true,
children: Children_Merchants
}
}
});
$('#treeview').kendoTreeView({
dataSource: Brandowners,
animation: {
collapse: {
duration: 200,
effects: "fadeOut"
},
expand: {
duration: 200,
effects: "fadeIn"
}
},
dataTextField: "Name",
complete: function () { alert('ok'); },
//dataBound : ExpandNode,
select: OnSelect,
expand: CheckIfHasParent
}).data('kendoTreeView');
}
function ExpandNode() {
var treeview;
treeview = $("#treeview").data("kendoTreeView");
var nodeToExpand = treeview.findByText('Adam'); //dummy txt, will have from parameter
treeview.expand(nodeToExpand);
}
The databind works ok, my controllers get called, everything's fine.
So what I tried is hook up the ExpandNode function to a click of a button. The function gets called but nothing happens. BUT if I hook it up to the change event of the parents datasource, it works. Another interesting thing is that the select works so if I replace treeview.expand(...) with treeview.select(...), it works on the click.
So my questions are:
1) What event should I use for loadEnd ( or smth like that ) - so I won't have to bind the function to button click (it's still ok but I preffer on load ended) - P.S. I tried all the ones I found on the kendo forums,like: change, requestEnd, success, dataBound and they don't work. I tried sending the JSON with the property "expanded" set to TRUE, for the node in question, but that only modifies the arrow to show like it's opened, but it doesn't call the controller and load the children.
2) Do you know why ExpandNode works only when binded to the change event? - the most important question to me.
3) If you have suggestions, or have I done something wrong in the initialiation of the treeview, please tell me.
I've copied your code with some free interpretations and the answer your questions is:
What event should I use for loadEnd => dataBound
Do you know why ExpandNode works only when binded to the change event? => No, it works without binding it to change event. If it does not then there is something else in your code.
Suggestions => There is some information missing about your code that might make the difference with what I've implemented.
What is CheckIfHasParent? => I have implemented it as a function that actually does nothing.
What is hasParent? => I've ignored it.
The code as I write it:
$(document).ready(function () {
function InitializeTreeview() {
var Children_Merchants = {
transport: {
read: function (op) {
var id = op.data.ID;
var data = [];
for (var i = 0; i < 10; i++) {
var aux = id * 100 + i;
data.push({ Name: "Name-" + aux, ID: aux});
}
op.success(data);
}
},
schema : {
model: {
model: {
id : "ID",
hasChildren: true,
children : Children_Merchants
}
}
}
};
var Brandowners = new kendo.data.HierarchicalDataSource({
transport: {
read: function (op) {
op.success([
{"Name": "Adam", "ID": 1},
{"Name": "Benjamin", "ID": 2},
{"Name": "Caleb", "ID": 3},
{"Name": "Daniel", "ID": 4},
{"Name": "Ephraim", "ID": 5},
{"Name": "Frank", "ID": 6},
{"Name": "Gideon", "ID": 7}
])
}
},
//change: ExpandNode, - if I call expand node like this, it works.
schema : {
model: {
id : "ID",
hasChildren: true,
children : Children_Merchants
}
}
});
$('#treeview').kendoTreeView({
dataSource : Brandowners,
animation : {
collapse: {
duration: 200,
effects : "fadeOut"
},
expand : {
duration: 200,
effects : "fadeIn"
}
},
dataTextField: "Name",
dataBound : ExpandNode,
expand : CheckIfHasParent
}).data('kendoTreeView');
}
function ExpandNode() {
var treeview;
treeview = $("#treeview").data("kendoTreeView");
var nodeToExpand = treeview.findByText('Adam'); //dummy txt, will have from parameter
treeview.expand(nodeToExpand);
}
function CheckIfHasParent(e) {
}
InitializeTreeview();
});
and you can play with it here : http://jsfiddle.net/OnaBai/dSt2h/
$("#treeview").kendoTreeView({
animation: {
expand: true
},
dataSource: dataSource,
dataBound: function (e) {
var tv = $("#treeview").data("kendoTreeView");
if (tv != null) {
tv.expand(".k-item");
}
},
dataTextField: "test",
dataValueField: "id"
});
For anyone who may be interested:
function ExpandNode() {
var treeview;
var node1;
treeview = $("#treeview").data("kendoTreeView");
var node2;
var myURL = kendo.format(websiteRootUrl + '/Merchants/GetPathForSelectedNode?databaseID={0}&merchantID={1}&brandownerID={2}', selectedDatabaseID,MerID,BowID);
node1 = treeview.dataSource.get(BowID);
node = treeview.findByUid(node1.uid);
var uid = node1.uid;
node.find('span:first-child').trigger('click'); //expand 1st level
$.ajax( {
url: myURL,
dataType: "json",
contentType: 'application/json; charset=utf-8',
success: function(result)
{
var length = result.length;
var lastVal = 1;
for (var i = 1; i < length-1; i++) {
$("#treeview li[data-uid=\'" + uid + "\'] ul.k-group").waitUntilExists (function
() {
i = lastVal; // have to reinitialize i because waitUntilExist's callback will find the i incermented, over the needed value
lastVal++;
node2 = node1.children.get(result[i]);
node = treeview.findByUid(node2.uid);
uid = node2.uid;
node1 = node2;
if(lastVal <= length-1)
node.find('span:first-child').trigger('click'); // keep expanding
else
{
treeview.select(node); // just select last node
currentSelectedNode = node;
}
});
}
if(length == 2) //select 1st child
{
$("#treeview li[data-uid=\'" + uid + "\'] ul.k-group").waitUntilExists (function
() {
node2 = node1.children.get(result[i]);
node = treeview.findByUid(node2.uid);
uid = node2.uid;
node1 = node2;
treeview.select(node); // just select last node
currentSelectedNode = node;
});
}
}
});
}
This is my method. The for loop starts at 1 because the 1st element in my array is the 1st node ID - wich I've already expanded. the .waitUntilExists is Ryan Lester's method (I put a link in the comments above). Many thanks to my colleague, to you OnaBai and, of courese, to Ryan Lester. I hope this helps someone. Cheers
ypu can easily find the treeview is ready for expand by following code which are expanding all the treeview nodes you can also find it by checking perticular id or text
hopw, following example will help you
Ex:
$("#treeview").kendoTreeView({
animation: {
expand: true
},
dataSource: dataSource,
dataBound: function (e) {
var tv = $("#treeview").data("kendoTreeView");
if (tv != null) {
tv.expand(".k-item");
}
},
dataTextField: "test",
dataValueField: "id"
});
I'm trying to load a particular json file into a listview; but sencha proxy doesn't seem to understand the key pairs of "CurrencyName" and "Value". I'm clueless on how to associate those two values into usable data.
Here's the json:
{
"timestamp": 1335294053,
"base": "USD",
"rates": {
"AED": 3.6732,
"AFN": 48.32,
"ALL": 106.040001
}
}
my store:
proxy: {
type: 'ajax',
url: 'http://localhost/CurrencyFX/latest.json',
reader: {
type: 'json',
rootProperty: 'rates'
}
},
my model:
Ext.define('CurrencyFX.model.Currency', {
extend: 'Ext.data.Model',
config: {
fields: [ 'name', 'value' ]
}
});
You'll need to write your own JSON reader subclass to make this work, as the data you are dealing with isn't an array.
Thankfully, doing this is fairly simple. Here is something that should do the job:
Ext.define('Ext.data.reader.Custom', {
extend: 'Ext.data.reader.Json',
alias : 'reader.custom',
getRoot: function(data) {
if (this.rootAccessor) {
data = this.rootAccessor.call(this, data);
}
var values = [],
name;
for (name in data) {
values.push({
name: name,
value: data[name]
});
}
return values;
}
});
Which will work with the following store configuration:
var store = Ext.create('Ext.data.Store', {
fields: ['name', 'value'],
autoLoad: true,
proxy: {
type: 'ajax',
url: '0000.json',
reader: {
type: 'custom',
rootProperty: 'rates'
}
}
});
Notice the reader type is now custom.
I tested this locally with your data and it seemed to work just fine.