I need get all data from one column of a kendo grid, I've searched a lot but didn't found something useful. I create a kendo grid based on a JSON coming from API API/LogService/ReadAllLog. I'm using AngularJS anyway.
My code:
$scope.gridColumns = [{
field: "SystemName",
editable: false,
title: _t("Title.SystemName"),
allownull: false,
width: 100
}, {
field: "FormName",
editable: false,
title: _t("CommonTitle.SystemFeatureForm"),
allownull: false,
width: 100
}]
and then I fill it like this:
$scope.gridConfig = {
autoBind: true,
inlineOperationalUrl: {
read: {
url: webAccess + "api/LogService/ReadAllLog",
}
}
};
and this is my grid in my view (note: pn-gridview is a custom directive created from angular grid view with some changes):
<pn-gridview id="SystemsGrid"
config="gridConfig"
columns="gridColumns"
</pn-gridview>
Collect all values on one column with a simple helper function:
function getColumnValues(selector, columnName) {
//Init
var columnData = [];
var data = $(selector).data("kendoGrid").dataSource._data;
//collect each valueof given columnName
for (i = 0; i < data.length; i++) {
if (typeof data[i][columnName] !== "undefined") {
columnData.push(data[i][columnName]);
}
}
//return column data as array
return columnData;
}
> DEMO FIDDLE
In your case you need to call this helper function like:
var myColumnData = getColumnValues('#SystemsGrid', 'SystemName');
You can access a specific row data with:
var myRowData = $("#SystemsGrid").data().kendoGrid.dataSource.at(index);
Related
As title, yesterday I learn how to retrieve the All-suggestion-accepted content of a document with API in this post, and I refer to the other post and know how to retrieve the insertion and deletion of the suggestion. Also, with the method above, I can retrieve the start-index(The position where insertion or deletion starts in a document) and end-index(The position where insertion or deletion ends in a document) of the insertion and deletion.
So, can I make changes, such as underlining the insertion or deletion parts, to the All-suggestion-accepted content referring to the indexes as positions? Is there going to be an error if I do this?
This is the array Google Doc API returned to me, and its format is
[suggestedDeletionIds,"delete",content,startIndex,endIndex]
This is the insertion and the deletion I made to the document, and I want to underline the deletion and insertion part within the All-suggestion-accepted content of a document based on the index.
Below is the snippet and the result of the snippet, last two figures are the start and the end index of the insertion or deletion.
function get_all_insertion_deletion() {
var documentId = "MYDOCUMENTID";
var doc = Docs.Documents.get(documentId);
remove_all(documentId);
doc.body.content.forEach(function (content){
if (content.paragraph) {
var elements = content.paragraph.elements;
elements.forEach(function (element){
if(element.textRun.suggestedDeletionIds)
{
var d_length= element.endIndex-element.startIndex;
var d= [element.textRun.suggestedDeletionIds,"delete",element.textRun.content,element.startIndex,element.endIndex];
Logger.log(d);
deletion++;
}
if(element.textRun.suggestedInsertionIds)
{
var i_length= element.endIndex-element.startIndex;
var i= [element.textRun.suggestedInsertionIds,"insert",element.textRun.content,element.startIndex,element.endIndex];
Logger.log(i);
insertion++; } }); }
});
}
I believe your goal is as follows.
You want to add the underline to "delete" and "insert" parts of your script in Google Document.
In order to achieve your goal, when your script is modified it becomes as follows.
Modified script:
function get_all_insertion_deletion() {
var documentId = "MYDOCUMENTID";
var doc = Docs.Documents.get(documentId);
var requests = [];
doc.body.content.forEach(function (content) {
if (content.paragraph) {
var elements = content.paragraph.elements;
elements.forEach(function (element) {
if (element.textRun.suggestedDeletionIds) {
// var d_length = element.endIndex - element.startIndex; // This is not used.
var d = [element.textRun.suggestedDeletionIds, "delete", element.textRun.content, element.startIndex, element.endIndex];
Logger.log(d);
requests.push({ updateTextStyle: { range: { startIndex: element.startIndex, endIndex: element.endIndex }, textStyle: { underline: true }, fields: "underline" } });
// deletion++; // This is not used.
}
if (element.textRun.suggestedInsertionIds) {
// var i_length = element.endIndex - element.startIndex; // This is not used.
var i = [element.textRun.suggestedInsertionIds, "insert", element.textRun.content, element.startIndex, element.endIndex];
requests.push({ updateTextStyle: { range: { startIndex: element.startIndex, endIndex: element.endIndex }, textStyle: { underline: true }, fields: "underline" } });
Logger.log(i);
// insertion++; // This is not used.
}
});
}
});
Docs.Documents.batchUpdate({requests}, documentId);
}
or, I thought that you can also the following modified script.
function get_all_insertion_deletion() {
var documentId = "MYDOCUMENTID";
var doc = Docs.Documents.get(documentId);
var requests = doc.body.content.flatMap(content => {
if (content.paragraph) {
var elements = content.paragraph.elements;
return elements.flatMap(element => element.textRun.suggestedDeletionIds || element.textRun.suggestedInsertionIds ? { updateTextStyle: { range: { startIndex: element.startIndex, endIndex: element.endIndex }, textStyle: { underline: true }, fields: "underline" } } : []);
}
return [];
});
Docs.Documents.batchUpdate({requests}, documentId);
}
Reference:
UpdateTextStyleRequest
I have the following scenario:
A user can visit a site with a DataTable in two ways:
Normal, no filter set, you'll see every entry.
User should see only entries with predefined filters
I've accomplished so far to set the filter's value as well as the column's search value by setting them in the initComplete-method, but the DataTable doesn't updates after setting the filters, which is mysterious to me since the DataTable knows after pressing F5 the set filter value...
So my question is: How do I get the desired result of setting default filter values, and tell the DataTable to update, after it finished it's initialization?
My DataTable-Initialization looks like this:
$('#table-data').DataTable({
processing: true,
serverSide: true,
language: dataTablesGerman,
initComplete: function () {
this.api().columns().every(initColumnFilter);
const json = JSON.parse($('[name="table_settings"]').val());
const dt = this.api();
dt.columns().every(function (idx) {
const column = this;
if (json[idx] !== null) {
const $current = $('input:not(.datetimerange), select', this.footer());
const value = json[idx].search;
$current.val(value);
column.search(value).draw();
}
});
}
});
The settings are looking like this (these settings are from the PHP Response, which are stored on a hidden field, the $('[name="table_settings"]').val() line):
const settings = [
null,
null,
null,
null,
null,
null,
null,
{ search: 1 } // this will be set to a select box
];
After some other experiments we could get it work with drawing the column again with a delay of 1ms. This made the DataTable apply the filter.
So the code now looks like this:
$('#table-data').DataTable({
processing: true,
serverSide: true,
language: dataTablesGerman,
initComplete: function () {
this.api().columns().every(initColumnFilter);
const json = JSON.parse($('[name="table_settings"]').val());
const dt = this.api();
if (json !== null && json.length > 0) {
dt.columns().every(function (idx) {
const column = this;
if (json[idx] !== null) {
const $current = $('input:not(.datetimerange), select', this.footer());
const value = json[idx].search;
$current.val(value);
column.search(value).draw();
window.setTimeout(function () {
column.draw();
}, 1);
}
});
}
}
});
I'm using handsontable js plugin. I want to use getCellMeta function in afterChange hook but not working.
I when use function out afterChange hook, function is working. But not working in afterChange hook.
var container = document.getElementById('t1'),
options = document.querySelectorAll('.options input'),
table,
hot;
hot = new Handsontable(container, {
autoWrapRow: true,
startRows: 81,
startCols: 206,
autoColumnSize : true,
stretchH: 'all',
afterChange : function(change,source) {
if (source === 'loadData') {
return;
}
var test = this.getCellMeta(change[0],change[1]); // not working, not return "id" meta
console.log(test);
}
});
$.ajax({
url: 'path',
type: 'GET',
dataType: 'json',
success: function (res) {
var data = [], row, pc = 0;
for (var i = 0, ilen = hot.countRows(); i < ilen; i++)
{
row = [];
for (var ii = 0; ii<hot.countCols(); ii++)
{
hot.setCellMeta(i,ii,'id',res[pc].id);
row[ii] = res[pc].price;
if(pc < (res.length-1)) {
pc++;
}
}
data[i] = row;
}
hot.loadData(data);
}
});
var test = this.getCellMeta(0,0); // is working, return "id" meta
console.log(test);
Output console log i tried out afterChange;
Output console log use in afterChange;
How to get cell meta after change?
Thanks.
You're almost there, there's just a small mistake in your callback: the doc for afterChange specifies that first argument (changes) of the callback is:
a 2D array containing information about each of the edited cells
[[row, prop, oldVal, newVal], ...].
So, 2 important details:
To get the "meta" of row/col of affected cell (assuming there is just one), you need to call hot.getCellMeta(change[0][0],change[0][1]) for example
On hot and not this because the afterChange callback function is invoked from a different context (ie on a different object), so this is not the right target for the call, see How does the "this" keyword work?
Example that reads the whole array of changes:
var hot = new Handsontable(container, {
/* rest of init... */
afterChange : function(changes,source) {
console.log("Changes:", changes, source);
if (changes) {
changes.forEach(function(change) {
var test = hot.getCellMeta(change[0],change[1]);
console.log(test.id, test); // 'id' is the property you've added earlier with setMeta
});
}
}
});
See demo fiddle, open JS console, make any change(s) in the table.
I want to copy the value from issues in one project to issues in another that depend on it.
That is what I have:
var entities = require('#jetbrains/youtrack-scripting-api/entities');
var workflow = require('#jetbrains/youtrack-scripting-api/workflow');
exports.rule = entities.Issue.onChange({
// TODO: give the rule a human-readable title
title: 'Date-propagation',
guard: function(ctx) {
var links = ctx.issue.links['depends on'];
return ctx.issue.isChanged("Date") || !links.added.isEmpty() || !links.removed.isEmpty();
},
action: function(ctx) {
var issue = ctx.issue;
var links = issue.links['depends on'];
function updateIssue(normalIssue){
normalIssue.fields.DueDate = issue.fields.Date.value;
}
function checkList(list){
if(list.isNotEmpty())list.forEach(function(normalIssue){updateIssue(normalIssue);}) ;
}
//checkList(links.removed);
checkList(links);
// TODO: specify what to do when a change is applied to an issue
},
requirements: {
Date: {
type: entities.Field.dateType,
},
Depend: {
type: entities.IssueLinkPrototype,
outward: 'is required for',
inward: "depends on"
}
}
});
The problem is in this line:
normalIssue.fields.DueDate = issue.fields.Date;
How should it be done?
Most probably, you do not have a 'DueDate' field on your instance (as the default field is called 'Due Date'). If so, your code line should look like this:
normalIssue.fields['Due Date'] = issue.fields.Date;
I have a grid Panel in my code as:
Ext.create('Ext.grid.Panel', {
id : 'frPanel-' + interfaceId,
store : frStore,
columns : [
{
text : 'Sequence',
dataIndex : 'ruleId',
menuDisabled : true
},
{
text : 'Source',
dataIndex : 'source',
renderer : function(value, metaData) {
var newValue = convertObjValue(value);
if (newValue.match(/[-]+/i)) {
metaData.tdAttr = 'data-qtip="'
+ networkStore(value) + '"';
}
return newValue;
}
},
// paging bar at the bottom
dockedItems : [ {
xtype : 'pagingtoolbar',
store : frStore, // same store GridPanel is using
dock : 'bottom',
displayInfo : true
} ],
height : 300,
width : '100%',
forceFit : true,
renderTo : 'frContainer-' + interfaceId
});
And these are the helper function i have:
// To get the value after 2nd colon for object and object-group
function convertObjValue(value) {
var result;
var exp = /.*?:.*?:(.*)/i;
var newValue = value;
if ((result = exp.exec(value)) != null) {
if (result.index === exp.lastIndex) {
exp.lastIndex++;
}
newValue = result[1];
}
return newValue;
}
The store:
function networkStore(value) {
//var store = Ext.create('Ext.data.Store', {
var store = new Ext.data.Store({
model : 'networkModel',
autoLoad : {
timeout : 60000
},
proxy : {
type : 'ajax',
url : networkObjsURL + "&" + Ext.urlEncode({
'peId' : value
}),
reader : {
type : 'json',
idProperty : 'objValue'
},
}
});
var hoverOutput = "";
if(store.data.length > 0){
store.data.items.forEach(function(item) {
hoverOutput += item.data.objectValue + "</br>";
});
}
console.log(hoverOutput);
return hoverOutput;
and last but not the least is the model:
Ext.define('networkModel', {
extend : 'Ext.data.Model',
fields : [ {
name : 'objectValue'
} ]
});
Now comes the issue. The problem is when i dont place the breakpoint in the browser in store, the values wont show up in qtip. Im guessing thats because of the grid panel not waiting for the response back from the store after ajax response. Can someone help me figure out a workaround for this situation?
Thanks in advance
Have you tried setting
autoLoad:false
and then something like :
store.load({
callback: function(records, operation, success) {
if (success == true) {
//do your stuff
var hoverOutput = "";
if(store.data.length > 0){
store.data.items.forEach(function(item) {
hoverOutput += item.data.objectValue + "</br>";
});
}
console.log(hoverOutput);
return hoverOutput;
} else {
// the store didn't load, deal with it
}
}
// scope: this,
});
Since your breakpoint allows you to see your data, im thinking you are right in assuming it's a delay issue. Since Ext is asynchronous, it wont wait for the ajax call to be finished before continuing it's processing. A callback will help you manage this as it will be called when ajax returns.
I'm still also fairly new to Ext but at least that's my understanding. Hope it helps, or at least points you in the right way.
Edit because i reminded that sometimes having a return inside the success will make it hard to debug, etc. So you could also try changing your success to call another function and have that function do the processing, just keep the scope in mind.
I asked in comment which version ExtJS you're using but I didn't get response so I assume that you are using ExtJS 5.
Control Flow in your code is strange for me.
Why do you create store in render function indirectly (directly in networkStore) multiple times?
Nevertheless, store is fetching data asynchronous, so you have to wait/callback result (or use Future/Promise API for example). In addition, you should have any necessary data for the grid in frStore store (which you pass to the grid). You can also take advantage of data association in your model or you can create new field in model with convert function and use value of the association/field in render function.
Let me show you one of the approach how to do that (a simple one).
ExtJS doesn't like modifying records inside render function so we prepare a model which has a necessary qtip value.
I assume that you can load data of networkStore earlier (autoload: true) but this is for simplicity and you can change it later, for example using remoteFilter and callbacks.
You don't show definition of frStore and underlying model so I will use FrStore and FrModel as class names.
Ext.define('FrModel', {
extend: 'Ext.data.Model',
// ...
fields: [
// source field
// ...
/** qtip value **/
{
name: 'qtip',
type: 'string',
convert: function (value, record) {
var result = '';
// below code is from your render function with modifications
if (record.get('rendered_source').match(/[-]+/i)) {
result = 'data-qtip="'
+ networkStore(record.get('source')) + '"';
}
return result;
},
depends: ['source', 'rendered_source']
},
/** rendered source **/
{
name: 'rendered_source',
type: 'string',
convert: function (value, record) {
var newValue = convertObjValue(record.get('source'));
return newValue;
},
depends: ['source']
}
]
// ...
}
After that change render function is simple:
// ...
{
text : 'Source',
dataIndex : 'rendered_source', // this will allow users to sort & filter this field by the values which are displayed
renderer : function(value, metaData, record) {
metaData.tdAttr = 'data-qtip="'
+ record.get('qtip') + '"';
}
return value;
}
},
// ...
You can need also a NetworkStore which you could place in seperate file: (I prefer proxy/schema in model but I've used your code)
Ext.create('Ext.data.Store', { // using Ext.create is better
model : 'networkModel',
storeId: 'networkStore', // registering store in Ext.data.StoreManager in order to get later this store by Ext.getStore(<store_id>)
autoLoad : true,
proxy : {
type : 'ajax',
url : networkObjsURL, // we load all records but I mentioned earlier that you can change this
reader : {
type : 'json',
idProperty : 'objValue'
},
}
});
I added peId field in netowrkModel because we want to query store later.
Ext.define('networkModel', {
extend : 'Ext.data.Model',
fields : [
{
name: 'objectValue'
},
{
name: 'peId',
type: 'int'
}
]
});
The last part is the networkStore function:
function networkStore(value) {
var store = Ext.getStore('networkStore');
var records = store.query('peId', value, false, true, true);
var hoverOutput = "";
if (records.length > 0) {
records.each(function(item) {
hoverOutput += item.get('objectValue') + "</br>";
});
}
console.log(hoverOutput);
return hoverOutput;
}
PS. I do not test above code.
However, IMO correct solution uses associations. I recommend you read this doc.
You should get to know concepts like schema, proxy, association and others.
When you join FrModel with NetworkModel by peId then you won't need NetworkStore and you build qtip in convert function based on that association.