I'm stucked into a problem that I need to pass my schema and my json to my constructor. First of all, I'm using Reactabular to develop a SPA, but in this library I can only start the application using a function that they have created called generateRows, but I have my own objects to inject, so I don't want to generate rows.
In my component i have this chunk of code:
class AllFeaturesTable extends React.Component {
constructor(props) {
super(props);
this.state = {
rows: generateRows(5, schema),
searchColumn: 'all',
query: {}, // search query
sortingColumns: null,
columns: this.getColumns(),
pagination: {
page: 1,
perPage: 5
}
};
When I pass my rows as json object array everything works great untill I try to edit these values, and makes sense why i cannot edit this data. I can't because i didn't passed the schema(as you guys can see in the generaterows they took as parameter the schema).
My question is how can I achieve this? pass in my this.state.row the schema and my rows.
This is my rows:
const predefinedRows = [
{ "combustivel" : "Flex",
"imagem" : null,
"marca" : "Volkswagem",
"modelo" : "Gol",
"placa" : "FFF-5498",
"valor" : 20000
},
{ "combustivel" : "Gasolina",
"imagem" : null,
"marca" : "Volkswagem",
"modelo" : "Fox",
"placa" : "FOX-4125",
"valor" : "20000"
},
{ "combustivel" : "Alcool",
"imagem" : "http://carros.ig.com.br/fotos/2010/290_193/Fusca2_290_193.jpg",
"marca" : "Volkswagen",
"modelo" : "Fusca",
"placa" : "PAI-4121",
"valor" : "20000"
}
];
and this my schema :
const schema = {
type: 'object',
properties: {
combustivel: {
type: 'string'
},
imagem: {
type: 'string'
},
marca: {
type: 'string'
},
modelo: {
type: 'string'
},
placa: {
type: 'string'
},
valor: {
type: 'integer'
}
},
required: ['combustivel', 'imagem', 'marca', 'modelo', 'placa']
};
Thanks in advance!
You should not use generateRows. generateRows introduced here, just return a dummy array data.
Just follow the example to implement your component.
If you want to use all features, and pass to this.state.row the schema and rows. Just do this:
this.state = {
row: {
rows: yourRows,
schema: yourSchema
},
searchColumn: 'all',
query: {}, // search query
sortingColumns: null,
columns: this.getColumns(),
pagination: {
page: 1,
perPage: 5
}
};
Related
I have a grid store with something like this.
var gridStore = Ext.create('Ext.data.Store',{
proxy : {
type : 'ajax',
actionMethods : {
read : 'POST'
},
url : 'getECIAgentWrapperJobs.do',
reader : {
type : 'json',
rootProperty : 'rows',
totalProperty : 'results'
}
},
pageSize : 3,
autoLoad : {start: 0, limit: 3}
});
Clearly it makes an AJAX request to the url.
The JSON response that I am getting for this store looks something like this :
{
"results":2,
"rows":[
{
"pkTable1":1,
"name":"Rick",
"eciAgentJob":{
"pkTable2":11,
"name":"Play Local Ar",
},
}
],
"msg":null,
"success":true,
}
Now this is how my grid looks :
var mappedEciAgentJobsGrids = Ext.create('Ext.grid.Panel',{
store : gridStore,
columns : [
{
dataIndex : 'pkTable1',
header : 'Pk of table 1'
},
{
dataIndex : 'name',
header : 'Name'
},
{
dataIndex : 'eciAgentJob.pkTable2',
header : 'Pk of Table 2'
}
]
});
Now in my UI the first 2 columns(with dataIndex: pkTable2 and name respectively) load fine. But for the 3rd one it does not.
I know it is because I have used dataIndex as 'eciAgentJob.pkTable2'. But then what is that way to load data in columns when we get response like the way I got(where eciAgentJob is a object inside the original JSON).
Please help.
Edit : I dont want to use a renderer due to some other use case reasons.
Define a new field in your model and map with the required field. In convert function pick any value from the record.
Ext.define('User', {
extend: 'Ext.data.Model',
fields: [
{ name: 'name', type: 'string ' },
{
name: 'columnName',
convert: function (value, record) {
return "return what ever you want"
}
}
]
});
I have a kendo grid which is filled with some JSON data,
in the filter window in the grid, you can select a condition Type and then fill the condition value text box and then filter the grid based on your selection.
now I have a column that is filled with just four or five different value.
I want to make the condition value field of the filter section to become a drop-down list and instead of writing those values to select them, I want to choose them from the list. ( I mean in the filter section of the grid column, not in the column itself.)
I read an article which was like what I wanted, but it had added those values in the code,
I should notify you that those fields are not the same each time, so I can't write those value in the filter by hard coding.
even something like this one is very similar to what I wanted ( Filter Condition Created For 'City' Field ), but it's using a different source for getting the condition drop-down values, not grid column itself.
in addition, I can't use JSON data, I must use the information from the kendo grid.
thanks in advance.
I found the solution to my problem at last...
after binding the grid to the data source, by setting a loop on the data source of the grid, I take data of one column of the grid and push it to an array, then I set the filter on that column to the array.
<script type="text/javascript">
var arrayName = [];
$(function () {
var productsDataSource = new kendo.data.DataSource({
transport: {
read: {
url: "api/products",
dataType: "json",
contentType: 'application/json; charset=utf-8',
type: 'GET'
},
parameterMap: function (options) {
return kendo.stringify(options);
}
},
schema: {
data: "Data",
total: "Total",
model: {
fields: {
"Id": { type: "number" },
"Name": { type: "string" },
"IsAvailable": { type: "boolean" },
"Price": { type: "number" }
}
}
},
error: function (e) {
alert(e.errorThrown);
},
sort: { field: "Id", dir: "desc" },
serverPaging: true,
serverFiltering: true,
serverSorting: true
});
productsDataSource.read();
$("#report-grid").kendoGrid({
dataSource: productsDataSource,
dataBound:
function (e) {
var data = $("#report-grid").data("kendoGrid").dataSource._data;
for (i = 0; i < data.length; i++) {
arrayName.push(data[i].Name);
}
},
autoBind: false,
scrollable: false,
pageable: true,
sortable: true,
filterable: { extra: false },
reorderable: true,
columnMenu: true,
columns: [
{ field: "Id", title: "No", width: "130px" },
{ field: "Name", title: "ProductName", filterable: { ui: SystemFilter } },
{
field: "IsAvailable", title: "Available",
template: '<input type="checkbox" #= IsAvailable ? checked="checked" : "" # disabled="disabled" ></input>'
},
{ field: "Price", title: "Price", format: "{0:c}" }
]
});
function SystemFilter(element) {
element.kendoDropDownList({
dataSource: arrayName,
optionLabel: "--Select Name--"
})
};
});
One way that I like to do this is to create a list of my values and add that list to ViewData, which then gets passed to the View.
public IEnumerable<ModelName> GetTypes()
{
//Get data from the table you store your values in.
return dbContext.TypesTable.OrderBy(f => f.Name);
}
public ActionResult YourView()
{
IEnumerable<ModelName> types = GetTypes();
ViewData["MyTypes"] = types;
return View();
}
Then in your grid add a ForeignKey column and set it to look at the ViewData you set earlier.
#(Html.Kendo().Grid<ViewModelName>()
.Name("GridName")
.Columns(columns =>
{
columns.ForeignKey(c => c.RecipientType, (System.Collections.IEnumerable)ViewData["MyTypes"], "TypeId", "Name");
})
)
This column will now display the Name of your value for the current records. Then when you go to edit or add a record, this field will display as a dropdown with all of the possible values.
I have JSON with structure like this:
"id":1,
"user_role":"ADMIN",
"state":"ACTIVE",
"address":{
"street":"test 59",
"city":"City test",
"post_number":"25050"
},
How I should to pass values of address.street into column using setting in fields and model?
Many thanks for any advice.
If you want to show all values in a single column do what #RobinGiltner suggests.
If you want to show each member of address in a different column you can do:
var grid = $("#grid").kendoGrid({
dataSource: data,
editable: true,
columns : [
{ field: "id", title: "#" },
{ field: "user_role", title: "Role" },
{ field: "address.street", title: "Street" },
{ field: "address.city", title: "City" },
{ field: "address.post_number", title: "Post#" }
]
}).data("kendoGrid");
i.e.: use address.street as name of the field. This would allow you even to edit the field as in the example: http://jsfiddle.net/OnaBai/L6LwW/
#OnaBai Good and intuitive answer. Sadly Kendo doesn't always work to well with nested properties this way. For example formating doesn't work. Here is an example using data source shema to access nested properties. This way you can use formatting but you have to specify a schema model.
var grid = $("#grid").kendoGrid({
dataSource: {
data: data,
schema: {
model: {
id: "id",
fields: {
id: { type: "number" },
user_role: { type: "string" },
address_street: { from: "address.street" },
address_city: { from: "address.city" },
address_post_number: {
type: "number",
from: "address.post_number"
}
}
}
}
},
columns: [{
field: "id",
title: "#"
}, {
field: "user_role",
title: "Role"
}, {
field: "address_street",
title: "Street"
}, {
field: "address_city",
title: "City"
}, {
field: "address_post_number",
title: "Post#",
format: "{0:0#######}"
}]
}).data("kendoGrid");
Jsfiddle: http://jsfiddle.net/wtj6mtz2
See also this Telerik example for accessing nested properties.
You could use a template on the grid column definition to display whichever pieces of the address you wanted.
{ field: 'address', title: 'Address', template: '#= address.street# #= address.city#, #= address.post_number# ' },
See documentation for kendo column template. http://docs.telerik.com/kendo-ui/api/web/grid#configuration-columns.template
See sample at http://jsbin.com/gizab/1/edit
i have a json in the following format:
{
"collection": [
{
"id": 4,
"tickets": {
"collection": [
{
"inner_id": 8,
},
{
"inner_id": 10,
}
],
"count": 2,
"type": "collection"
},
},
{
"id": 5,
"tickets": {
"collection": [
{
"inner_id": 1,
},
{
"inner_id": 2,
}
],
"count": 2,
"type": "collection"
},
},
]
}
For this particular JSON i created the models as:
Ext.define("myProject.model.ABC", {
extend: "Ext.data.Model",
config: {
idProperty: "id",
fields:[
{name: "id", type: "int" },
],
hasMany: [
{
model: "myProject.model.XYZ",
name: "tickets",
associationKey: "tickets",
},
],
}
});
And second store as:
Ext.define("myProject.model.XYZ", {
extend: "Ext.data.Model",
config: {
// idProperty: "id",
fields:[
{name: "inner_id", type: "int" },
],
belongsTo: 'myProject.model.ABC'
}
});
But now i am confused. How do i populate the second store with a root property of collection again.
I know one way is to easily change the json so that there is no collection child inside tickets but i dont want to do that.
Any help would be appreciated. I have simplified the JSON for an easy example.
EDIT:
To be more clear, is there a way i can directly create a model which will read the Collection array inside the tickets object.
EDIT:
Adding the store which populates the model ABC for more understanding
Ext.define("myProject.store.ABCs", {
extend: "Ext.data.Store",
config: {
model: "myProject.model.ABC",
autoLoad: false,
proxy: {
type: "ajax",
url: '', //myURL
reader: {
type: "json",
rootProperty: "collection", // this is the first collection
},
},
}
});
This store loads the ABC model correctly but now i want to load the XYZ model which can load the inner array of collection
belongsTo should be define as follows :
Ext.define('Product', {
extend: 'Ext.data.Model',
fields: [
{ name: 'id', type: 'int' },
{ name: 'category_id', type: 'int' },
{ name: 'name', type: 'string' }
],
associations: [
{ type: 'belongsTo', model: 'Category' }
]
Have you read the doc? They specified the root property.
The name of the property which contains the data items corresponding to the Model(s) for which this Reader is configured. For JSON reader it's a property name (or a dot-separated list of property names if the root is nested). For XML reader it's a CSS selector. For Array reader the root is not applicable since the data is assumed to be a single-level array of arrays.
By default the natural root of the data will be used: the root JSON array, the root XML element, or the array.
The data packet value for this property should be an empty array to clear the data or show no data.
Sometimes the JSON structure is even more complicated. Document databases like CouchDB often provide metadata around each record inside a nested structure like this:
{
"total": 122,
"offset": 0,
"users": [
{
"id": "ed-spencer-1",
"value": 1,
"user": {
"id": 1,
"name": "Ed Spencer",
"email": "ed#sencha.com"
}
}
]
}
In the case above the record data is nested an additional level inside the "users" array as each "user" item has additional metadata surrounding it ('id' and 'value' in this case). To parse data out of each "user" item in the JSON above we need to specify the record configuration like this:
reader: {
type : 'json',
root : 'users',
record: 'user'
}
root as a Function
reader: {
type : 'json',
root : function (obj) {
// I can't reproduce your problem
// so you should check in your console collection.id is right
return obj.collection.id
}
}
// Or, we can use dot notation
reader: {
type : 'json',
root : collection[0].tickets.collection
}
There are two ways to solve this problem. After researching extensively, i found two solutions...
SOLUTION 1:
Instead of making a second model, just create one model and create an array field with type as "auto"
Ext.define("myProject.model.ABC", {
extend: "Ext.data.Model",
config: {
idProperty: "id",
fields:[
{name: "id", type: "int" },
{ name: "tickets", convert: function(value, record) {
if(value.collection instanceof Array) {
return value.collection;
} else {
return [value.collection]; // Convert to an Array
}
return value.collection;
}
}
],
}
});
Now you can refer to an array of tickets from records by:
record.get('tickets')
SOLUTION 2:
Create three model instead of two.
Model 1:
hasOne Association with Tickets
Model 2:
hasMany association with Collection
Model 3:
has all the fields of the innermost array
I can give an example if its not clear enough
Ext.define('Olvldefnition', {
extend: 'Ext.data.Model',
fields: [
{
name : 'defKey'
},
{
name : 'defStructKey',
type : 'int'
},
{
name : 'defLevelNo',
type : 'int'
}, {
name : 'defLevelDiscP',
type : 'string'
}, {
name : 'defLevelDiscS',
type : 'string'
}, {
name : 'defSeqNo',
type : 'int'
}
]
});
var storeDef = Ext.create('Ext.data.Store', {
id: 'storeDef',
model: 'Olvldefnition',
proxy: {
type: 'jsonp',
api : {
read : 'definition/view.action'
},
reader: {
type: 'json',
root: 'data',
idProperty: 'defKey',
successProperty : 'success',
messageProperty : 'message'
}
}
});
This is my code it gets a JSON data like as follows.
{
"total":3,
"data":[
{"modifiers":{"status":"A","effstartdate":"2012-04-02 00:00:00.0","effenddate":"2012-04-26 00:00:00.0","updateUser":"ARCSADMIN","updateDate":"2012-04-16 16:04:29.162","remarks":null,"entryDate":"2012-04-07 19:34:28.923","entryUser":"ARCSADMIN"},
"defKey":105,
"defSeqNo":2,
"defStructKey":73,
"defLevelNo":1,
"defLevelDiscP":"Branch",
"defLevelDiscS":"Branch",
"olvstructure":{"modifiers":{"status":"A","effstartdate":"2012-04-06 00:00:00.0","effenddate":"2012-04-27 00:00:00.0","updateUser":"ARCSADMIN","updateDate":"2012-04-06 20:03:43.817","remarks":"Remark","entryDate":"2012-04-06 20:03:37.252","entryUser":"ARCSADMIN"},"olsKey":73,"olsSeqNo":1,"olsLevel":3,"olsSeperator":"-"}},{"modifiers":{"status":"A","effstartdate":"2012-04-02 00:00:00.0","effenddate":"2012-05-23 00:00:00.0","updateUser":"ARCSADMIN","updateDate":"2012-04-30 12:22:12.899","remarks":null,"entryDate":"2012-04-07 19:33:58.405","entryUser":"ARCSADMIN"},"defKey":104,"defSeqNo":1,"defStructKey":73,"defLevelNo":2,"defLevelDiscP":"Dept1","defLevelDiscS":"Dept1","olvstructure":{"modifiers":{"status":"A","effstartdate":"2012-04-06 00:00:00.0","effenddate":"2012-04-27 00:00:00.0","updateUser":"ARCSADMIN","updateDate":"2012-04-06 20:03:43.817","remarks":"Remark","entryDate":"2012-04-06 20:03:37.252","entryUser":"ARCSADMIN"},"olsKey":73,"olsSeqNo":1,"olsLevel":3,"olsSeperator":"-"}},{"modifiers":{"status":"I","effstartdate":null,"effenddate":null,"updateUser":null,"updateDate":null,"remarks":null,"entryDate":"2012-04-19 13:52:04.676","entryUser":"ARCSADMIN"},"defKey":118,"defSeqNo":3,"defStructKey":73,"defLevelNo":3,"defLevelDiscP":"sdasda","defLevelDiscS":"dsd","olvstructure":{"modifiers":{"status":"A","effstartdate":"2012-04-06 00:00:00.0","effenddate":"2012-04-27 00:00:00.0","updateUser":"ARCSADMIN","updateDate":"2012-04-06 20:03:43.817","remarks":"Remark","entryDate":"2012-04-06 20:03:37.252","entryUser":"ARCSADMIN"},"olsKey":73,"olsSeqNo":1,"olsLevel":3,"olsSeperator":"-"}}],"message":"view","success":true}
but it shows an error like this
SCRIPT1004: Expected ';'
view.action?_dc=1337079455042&page=1&start=0&limit=25&callback=Ext.data.JsonP.callback1, line 1 character 9
maybe problem is proxy type: 'jsonp'?
because in your example I only see json not jsonp and your api url is on same server so why not use json instead of jsonp?
Example:
var storeDef = Ext.create('Ext.data.Store', {
id: 'storeDef',
model: 'Olvldefnition',
proxy: {
type: 'ajax',
api : {
read : 'definition/view.action'
},
reader: {
type: 'json',
root: 'data',
idProperty: 'defKey',
successProperty : 'success',
messageProperty : 'message'
}
}
});
I think you've got simple syntax error somewhere. It has nothing to do with parsing JSON data.