How to grid updated and refresh data with KendoUI for Angular2? - kendo-ui-angular2

I am using the Kendo UI grid to edit records.
I have a load data function:
private loadData(): void {
this.gridView = {
data: this.data.slice(this.skip, this.skip + this.pageSize),
total: this.data.length
};
}
and I have a service that updates the data and stores it in this.data content:
this.dataservice.update().then(res => this.loadData());
However, the UI does not update. How should I update the grid UI?

If the grid is not updated, I suppose that changes in the loadData() method are not detected.
A simple test in a plunker shows that such simplified approach works just fine:
Plunker Demo
As a side note, if you are not seeing changes in the a specific row template, then this is a known issue logged here:
Kendo Grid for Angular 2 Issue

Related

How to show an image in the mobile application

I have a request to add the image from a stock item to the picking screen in the mobile app in Acumatica. I took a look at the Mobile Framework documentation but, there doesn't appear to be a way to show an image in the mobile app. Has anybody tried something like this?
TIA!
I don't think there is a control for ImageURL in the mobile app as of now.
However, as long as your screen holds a Header record with Files(attachments) you could still see the attachments(images) in the mobile application.
For this you can take as an example and guidance the EP301020 - Expense Receipt screen:
add screen EP301020 {
openAs = Form
add container "ClaimDetails" {
formActionsToExpand = 1
add layout "ReceiptNumberHeader" {
displayName = "ReceiptNumberHeader"
layout = "HeaderFirstAttachment"
add field "ReceiptNumber" {
forceIsDisabled = True
}
add field "Status" {
forceIsDisabled = True
}
}
add field "DetailsExpenseDetails#Description"
.....................
attachments {
imageAdjustmentPreset = Receipt
}
}
...............
}
See more details about the layout "HeaderFirstAttachment" here:
https://help.acumatica.com/(W(1))/Help?ScreenId=ShowWiki&pageid=bd31e3a8-538f-47d5-84ff-251ca3d03c43

kendo ui angular grid - how to leave row when user hits enter key instead of clicking off of row

Ive got a working grid, using in-line editing thanks to this example
https://www.telerik.com/kendo-angular-ui/components/grid/editing/editing-row-click/
What I need to do now, is force the saving upon a user hitting the enter key, instead of clicking away onto another row or away from the current row. I suppose I could add a "save" button in the header?
You could probably use cellClose event in your html (cellClose)="cellCloseHandler($event)" - API Documentation
You could then write your own code (in typescript) in cellCloseHandler() to modify and save the updated items accordingly.
From Kendo UI for Angular Documentation:
In-Cell Editing
You could capture the Enter key hits and force executing cellCloseHandler() like that:
#HostListener('keydown', ['$event'])
public keydown(event: any): void {
console.log("keydown event", event);
if (event.keyCode === 13) {
this.cellCloseHandler();
}
}
Similar to Giannis answer but with small modifications:
Add keydown event to kendo-grid tag.
Call grid.closeCell() instead of calling the closeHander directly.
Template
<kendo-grid #grid
[data]="data$ | async"
(cellClose)="cellCloseHandler($event)"
(keydown)="onKeydown(grid, $event)"
>
Class
onKeydown(grid: GridComponent, e: KeyboardEvent) {
if (e.key === 'Enter') {
grid.closeCell();
}
}
cellCloseHandler(args: CellCloseEvent) {
const { formGroup, dataItem } = args;
// save to backend etc
}
Calling grid.closeCell(); will make the grid to call cellCloseHandler
You dont have to implement a HostListener for Keydown by yourself. If you set the input navigable to true, the cellClose event will get triggered when pressing Enter while editing a cell or row. This way you get the data of the row in your cellCloseHandler aswell for saving it.
<kendo-grid [navigable]="true" (cellClose)="cellCloseHandler($event)"></kendo-grid>

How can you control visibility of datasource in Cesiumjs?

I want to display multiple datasources in a cesiumjs viewer but need to allow the user to select which ones they want to see at any given time. For example, if I load a kml and a czml file, how do I hide one and show the other? I can't find the cesiumjs way to do this with its API.
Update Feb 2016: A show flag has been proposed and may be added to a future version of Cesium.
Original answer:
Currently there is no show flag on the dataSource, however it is easy to add and remove the dataSource from the list of available dataSources, and this is used to get the show/hide functionality.
Here's a working demo: Load the Cesium Sandcastle Hello World example, and paste the following code into the left side, then hit Run (F8). It should display a checkbox in the upper-left with show/hide functionality.
var viewer = new Cesium.Viewer('cesiumContainer');
// Create a typical CzmlDataSource.
var dataSource1 = new Cesium.CzmlDataSource();
dataSource1.load('../../SampleData/simple.czml');
// Add a checkbox at the top.
document.getElementById('toolbar').innerHTML =
'<label><input type="checkbox" id="showCheckbox" /> Show CZML</label>';
var checkbox = document.getElementById('showCheckbox');
checkbox.addEventListener('change', function() {
// Checkbox state changed.
if (checkbox.checked) {
// Show if not shown.
if (!viewer.dataSources.contains(dataSource1)) {
viewer.dataSources.add(dataSource1);
}
} else {
// Hide if currently shown.
if (viewer.dataSources.contains(dataSource1)) {
viewer.dataSources.remove(dataSource1);
}
}
}, false);
This code could be improved, for example it could be a "lazy load" where the dataSource.load does not get called until the first time it's shown. Also if a dataSource has been hidden a while, you have to consider at what point should you be saving memory by destroying the dataSource rather than continuing to hold onto it (triggering a new lazy load if it is later shown again).
as of now, show is a property of the data source, you can control it by accessing the property in dot or bracket notation:
https://cesiumjs.org/Cesium/Build/Documentation/CzmlDataSource.html#show
const src = new Cesium.CzmlDataSource();
src.show = false;

Backbone.relational, real-time and handling large data

I'm building a real-time feed application using Backbone.js, node.js and socket.io.
My Feed is a collection of Update models. Displaying these, overriding Backbone.sync for integration with socket.io works fine.
The complication comes in that each Update has a set of comments associated with it. When I show each Update in the Feed view, I want to show a summary of the associated comments (number of comments and a single 'most poular' comment), and also have the ability to click through to a different view to display each Update on its own with a paginated list of comments with further data.
I'm using backbone-relational to model the relationship between the Update model and Comment model, as follows:
Feed (collection) -> Update (model) -(has many)-> Comment (model)
I've been following this backbone-relational tutorial, but it seems to assume that I'd want to have all related data in memory at once in my Feed view, which I don't as there are potentially thousands of comments updating in real-time:
http://antoviaque.org/docs/tutorials/backbone-relational-tutorial/
My questions are:
How can I bring in summary data for comments to each Update in my Feed view without loading all comment data, and also maintain the ability to show paginated full data in my Update view?
I'm using backbone.layoutmanager for rendering my views. How best should I break my views up to accomplish the above?
For Q1:
I'm assuming you're using something like ioSync to use socket.io in Backbone.sync instead of REST API, or a similar solution.
Include metadata (such as # of comments) as an attribute on Update. If your Update object is heavy weight in itself, you could update the count using ioBind and custom server-side socket.io events instead of sending the whole object every time.
Include an attribute topComment as an additional one-to-one relation in Update. When initially loading Update from the server, include topComment in the response, but not the other comments.
Lazy-load the rest of the comments using custom socket.io events. You will likely want a server-side handler that takes as parameters updateId, startIndex, maxComments, which returns a list of comments for the given Update starting at the given index. If the result is sent to the client as JSON, then it's easy to do something like this on the client:
// Assume `model` is an instance of `Update`.
socket.emit('get_comments_page', {
updateId: model.get('id'),
startIndex: 1,
maxComments: 10
}, function(err, data) {
if (err) {
alert('Unable to fetch comments: ', err);
} else {
model.get('messages').reset(data)
}
});
Avoid sending ID for all comments when fetching Update then trying to use fetchRelated to resolve them. I learned this one the hard way :O/
You could also store the comments collection directly on the view without associating it as relationship of Update
For Q2:
I don't have any experience with layoutmanager as I use Backbone.Marionette for managing my views. Marionette has an async extension (disclaimer: I'm a co-maintainer). I encourage to see how Marionette.async does the delayed rendering, waiting for the data to arrive from the server.
The main idea is to use jquery's Deferred objects that resolve when the data comes back from the server. Extending the above example with deferred:
var MyView = Backbone.View.extend({
// ... normal stuff that views need ...
initialize: function() {
var deferred = $.Deferred();
// Assume `model` is an instance of `Update`.
var that = this;
socket.emit('get_comments_page', {
updateId: that.model.get('id'),
startIndex: that.options.pageNumber,
maxComments: 10
}, function(err, data) {
if (err) {
alert('Unable to fetch comments: ', err);
} else {
that.model.get('messages').reset(data)
}
deferred.resolve();
});
this.promise = deferred.promise();
},
render: function() {
var that = this;
this.promise.done(function() {
// Do your normal rendering code here, for instance:
$(that.el).html(that.template(that.model.toJSON()));
});
return this;
}
});
Note: the code snippets above are not tested as is.

Telerik MVC Grid submitChanges with no grid changes

I'm using Telerik's MVC grid, and I would like to submit batch edit mode changes with some out of grid values. According to this telerik forum I can call the grid's submitChanges function and supply non-grid values inside the OnSubmitChanges event. This function only gets called if the grid has changes. There can be a case when values are changed outside of the grid but grid values are not saved. Is it possible to force the submission so that non-grid values can be submitted?
Good thing Telerik MVC Extensions are open source. I figured out the answer the following way:
function SaveCriteriaChanges() {
var grid = $("#MyGridId").data("tGrid");
//don't submit if grid fails validation
if (!grid.validate())
return false;
if (grid.hasChanges()) {
grid.submitChanges();
} else { //no grid changes to process so force submission
var additionalValues = {};
if(!$.telerik.trigger(grid.element, 'submitChanges', { values: additionalValues })) {
grid.sendValues($.extend({}, additionalValues), 'updateUrl', 'submitChanges');
}
}
return true;
}

Resources