I am using a Kendo grid with grouping that displays some strange behavior if the grid is re-populated.
Steps to produce odd behavior:
On button click grid is created with data source but not data
One or more ajax calls are made and results are added to the grid
Data is rendered to the grid as expected
Click search button again and grid is populated as expected
Drag a column into the grouping bar
After step five, the grid is grouped with the original search data.
Click the group button to sort and the updated search is displayed.
Here is the code that adds rows to the grid:
var grid = $('#grid');
var dataSource = grid.data().kendoGrid.dataSource;
if (data.length > 0) {
$.each(data, function (i, v) {
dataSource.add(v);
});
}
I have tried several things to clear out the data source, including variations on the following:
$("#grid").data("kendoGrid").dataSource.data([ ]);
The old search data is retained somewhere and is not displayed until I starting grouping.
The resolution is clearing data from the grid itself and not the data source.
Calling the destroy method cleaned out all JQuery data attributes and I was able to repopulate the grid with the odd behavior.
var grid = $('#report').data('kendoGrid');
if (grid) {
grid.destroy();
}
Related
I'm building an Addon used with Google Sheets which has a root homepage and 3 sub-Cards.
Card 1 generates folders and files and documents for orders based on sheet data which have an associated order number (list of whole integers).
Card 2 includes a Dropdown menu which is populated on Card creation from values (order numbers) from a column on a tab on the spreadsheet which is itself updated via function calls when any docs/orders are generated (using Card 1).
What I'm trying to do is update the values containing the order numbers on the Dropdown menu on Card 2 when new documents are created using Card 1. I'm successfully updating the spreadsheet tab with the new order numbers when docs are generated but I cannot get the Addon dropdown to update (properly - see below) with the new order numbers.
As I understand it, Cards cannot be refreshed, only replaced entirely, which should be fine but I cannot get it to work. I've seen this question but it doesn't seem to completely replace/refresh Card 2 with the new dropdown data.
I build the Addon with this:
function startAddon(e) {
return [createGenerateDocsCard(), createManageOrdersCard(), createResetSheetCard()];
}
The relevant Card which includes the Dropdown menu:
function createManageOrdersCard() {
//Get list of Order Numbers from sheet
let orderList = ss.getRange("C2!A1:A1000").getDisplayValues().filter(String);
//Generate dropdown using order numbers from sheet
let orderDropdown = generateDropdown("Order", "CHOOSE EXISTING ORDER TO LOAD:", previousSelected, orderList);
let manageOrdersCard = CardService
.newCardBuilder()
.setHeader(
CardService.newCardHeader()
.setTitle('📖 MANAGE ORDERS')
.setSubtitle('Switch between existing Order sheets')
)
.addSection(
CardService.newCardSection()
.addWidget(
//Insert generated dropdown
orderDropdown
.setOnChangeAction(CardService.newAction().setFunctionName("handleOrderDropdown"))
)
.addWidget(CardService.newTextButton()
.setText("SYNC ORDER NUMBERS")
.setTextButtonStyle(CardService.TextButtonStyle.FILLED)
.setOnClickAction(CardService.newAction().setFunctionName('syncOrderNumbersButton'))
)
)
return manageOrdersCard.build();
}
The function which generates the Dropdown:
function generateDropdown(fieldName, fieldTitle, previousSelected, items) {
var selectionInput = CardService.newSelectionInput().setTitle(fieldTitle)
.setFieldName(fieldName)
.setType(CardService.SelectionInputType.DROPDOWN);
items.forEach((item, index) => {
selectionInput.addItem(item[0], item[0], item[0] == previousSelected);
Logger.log(previousSelected);
})
return selectionInput;
}
And the code I'm using to attempt to fully replace the Card with a new one including updated Dropdown entries:
function syncOrderNumbersButton(e) {
syncOrderNumbers();
//replace the current outdated card with the newly created card.
return CardService.newNavigation().updateCard(createManageOrdersCard());
}
At the moment, I'm testing using a button to initiate inserting an updated list of orders into the spreadsheet using syncOrderNumbers() (which works) and then (attempting to) re-create Card 2 which should then have the new Dropdown entries. Ultimately this process will happen automatically without a button click when new order files are created.
What's happening though is that Card 2 appears to update and the new order number does show in the Dropdown, but when I navigate (using back button at top of Addon) to the root card (Addon homepage) and then navigate again to Card 2, the Dropdown no longer has the order number in it which previously showed.
When createManageOrdersCard() is run, the generateDropdown() function is within it, so I don't understand why a refreshed list for the Dropdown isn't being created/displayed and why it seems to revert to using the list from when the Addon first loaded?
Is it possible to do a full refresh of Card 2 so that even if navigated away and back again, the Dropdown it contains will represent a fully updated list of values taken from the spreadsheet?
Would really appreciate any help figuring this out.
The goal is to store the selected text into PropertiesService for later insertion into a Google Doc. Kind of like cut and paste so that the user can collapse and expand elements.
The code is
ui = DocumentApp.getUi();
var selection = DocumentApp.getActiveDocument().getSelection();
ui.alert(JSON.stringify(selection))
The alert contents is
[{}]
I understand that selection returns a Range. So I tried to store individual elements:
if (selection) {
var elements = selection.getRangeElements();
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
ui.alert(JSON.stringify(element.getElement()))
}
}
The alert contents for individual elements is always
[{}]
where there is one {} for every element in the list.
The functions I plan to use to store and retrieve follow:
function save_value(elements) {
PropertiesService.getScriptProperties().setProperty('selection', JSON.stringify(elements));
}
function get_value() {
return JSON.parse(PropertiesService.getScriptProperties().getProperty('selection'));
}
I realize there is a workaround here by storing the element values.
element.getElement().asText().getText();
This comes with downsides.
Code complexity when elements are partially selected. If the selection is partially selecting an element, it creates complexity in the code. The code would have to leverage isPartial(), getStartOffset() and getEndOffsetInclusive().
Code complexity in multiple elements. Instead of one swift store, I have to iterate and chain each store, or have multiple stores, or something else.
Unsure about this one but code complexity in distinct elements. Based on the element, the value method varies. For example, storing an image vs text.
Note, I also realized that not all elements can be inserted, and am experimenting to see if there is a workaround by using elements.
In the code snapshot below in app.component.html, I display clickable rows in a table in Lines 39 to 58. Once the user clicks a row, I display other relevant rows in a table named suraTable as shown in Lines 63 to 77. Namely, when the user clicks on a row, the function onSelectAya(aya, suraTable) in app.component.ts is called. That function loads the necessary rows and the table is displayed.
What I am stuck with is this. Suppose suraTable ends up with 100 rows. The current behaviour is that rows 1, 2, 3... are displayed of course. I need to be able to show the table at Row 50 say (information carried in the parameter aya on Line 91). How do I scroll to that position? I tried the scrollTop way but when checking the values before and after the setting of suraTable.scrollTop, the value is always 0 (0 pixels that is). Line 100 shows that when console.log(suraTable) is reached, expected output is generated in the browser, which means that I am getting hold of the element correctly to start with.
So, how do I scroll to a specific row in a table, or to an item in a list (I could convert the whole structure to a list if easier) from within the app.component.ts component? Thank you.
<mat-row id="{{task.taskId}}"
*matRowDef='let task; columns: columnsReadyTask;let i = index;'></mat-row>
if working with datasources, you will need some delay after getting element on the page with id...
setTimeout(() => {
const selectedRow = document.getElementById(taskId);
if(selectedRow) {
selectedRow.scrollIntoView({block: 'center'});
}
}, 500);
This may not work on old browsers.
If this is simply a scrolling thing, you could add specific id to your rows so you can know theyr number, and then do
var elmnt = document.getElementById("rowNumber"+rowNumber);
elmnt.scrollIntoView();
If when the scrolling is taking part your element is not rendered on DOM, try adding a callback for when that rendering is finished. If that is not possible, maybe a setTimeout can do.
I am using flex TabNavigator to display few datagrids. Each datagrid have same structure but populated with different dataProvider. Currently I am using following method to check which datagrid or an element from a tab was clicked.
if(TabNavigator.selectedIndex == 0){
}else if(TabNavigator.selectedIndex == 1){
}
...
else if(TabNavigator.selectedIndex == 4){
}
My question is is there an efficient way to check this? Is there anyway I can organize similar structure in to one property?
Thank you.
Add all your data providers into an array in the same sequence as the items in the tab navigator. Then simply do:
dataGrid.dataProvider = dataProviderArray[tabNavigator.selectedIndex];
Here 'dataProviderArray' is the array of all the data providers for the data grid.
Also, since you mentioned that the data grid has the same structure for all the tabs, I am assuming you are using one Data Grid and not multiple. If not, I would recommend you keep one data grid only and change its data provider when the tabs change.
Hope this solves your question.
I am new to working on flex. I looked at several stackoverflow questions but they didnt seem to answer my question.
I am using Advanced data grid column to display my data in a table. I know that columns can be sorted using the controls on the table being displayed.
But is there a way to sort data based on a single column when the data gets displayed.
I used sortDescending ="true" attribute but no change in the data.
Any help is much appreciated
Try to dispatch event
var adgEvent:AdvancedDataGridEvent =
new AdvancedDataGridEvent(AdvancedDataGridEvent.SORT, false, true);
adgEvent.columnIndex = columnIndex;
adgEvent.dataField = dataField;
adgEvent.triggerEvent = triggerEvent;
adgEvent.multiColumnSort = false;
on your AdvancedDataGrid to sort some column