If I have a Kendo grid, I can use format="{0:c}" on a kendo grid column to display a number in currency format. However, as I am editing this column inline and the grid column is in focus, the currency format is no longer displaying correctly, instead, while in focus, it behaves as just a simple numeric input where any number or amount of decimals is accepted. Once I blur from that input, the currency format correctly displays again.
I was wondering if there was a way to maintain the currency format while the focus is on the input when inline editing.
In my example (which I took from kendo's docs and simplified),I click on an item in the price column that is $22.00, I can add $22.985094385043950439 into the input while editing. As I blur, this becomes $22.99, but I do not want to allow the user more than 2 decimal places (USD) even if they are editing and the focus is on the column.
In addition, this will have to be globalized so it will have to behave this way for the local currency, not just USD. I've tried using formatNumber() from '@telerik/kendo-intl' in both the edit handler and the valueChange event handler but did not get the desired effect.
How can I maintain the currency format even when I am editing the column?
import { Observable } from 'rxjs/Observable';
import { Component, OnInit, Inject } from '@angular/core';
import { Validators, FormBuilder, FormGroup } from '@angular/forms';
import { GridDataResult } from '@progress/kendo-angular-grid';
import { State, process } from '@progress/kendo-data-query';
import { Product } from './model';
import { EditService } from './edit.service';
import { map } from 'rxjs/operators/map';
@Component({
selector: 'my-app',
template: `
<kendo-grid #grid
[data]="view | async"
[pageable]="true" [sortable]="true"
(dataStateChange)="onStateChange($event)"
(cellClick)="cellClickHandler($event)"
(cellClose)="cellCloseHandler($event)"
(cancel)="cancelHandler($event)"
(save)="saveHandler($event)"
>
<ng-template kendoGridToolbarTemplate>
<button kendoGridAddCommand>Add new</button>
<button class='k-button' [disabled]="!editService.hasChanges()" (click)="saveChanges(grid);">Save Changes</button>
<button class='k-button' [disabled]="!editService.hasChanges()" (click)="cancelChanges(grid);">Cancel Changes</button>
</ng-template>
<kendo-grid-column field="ProductName" title="Product Name"></kendo-grid-column>
<kendo-grid-column field="UnitPrice" format="{0:c}" editor="numeric" title="Price"></kendo-grid-column>
</kendo-grid>
`
})
export class AppComponent implements OnInit {
public view: Observable<GridDataResult>;
public gridState: State = {
sort: [],
skip: 0,
take: 10
};
public changes: any = {};
constructor(private formBuilder: FormBuilder, public editService: EditService) {
}
public ngOnInit(): void {
this.view = this.editService.pipe(map(data => process(data, this.gridState)));
this.editService.read();
}
public onStateChange(state: State) {
this.gridState = state;
this.editService.read();
}
public cellClickHandler({ sender, rowIndex, columnIndex, dataItem, isEdited }) {
if (!isEdited) {
sender.editCell(rowIndex, columnIndex, this.createFormGroup(dataItem));
}
}
public cellCloseHandler(args: any) {
const { formGroup, dataItem } = args;
if (!formGroup.valid) {
// prevent closing the edited cell if there are invalid values.
args.preventDefault();
} else if (formGroup.dirty) {
this.editService.assignValues(dataItem, formGroup.value);
this.editService.update(dataItem);
}
}
public addHandler({ sender }) {
sender.addRow(this.createFormGroup(new Product()));
}
public cancelHandler({ sender, rowIndex }) {
sender.closeRow(rowIndex);
}
public saveHandler({ sender, formGroup, rowIndex }) {
if (formGroup.valid) {
this.editService.create(formGroup.value);
sender.closeRow(rowIndex);
}
}
public removeHandler({ sender, dataItem }) {
this.editService.remove(dataItem);
sender.cancelCell();
}
public saveChanges(grid: any): void {
grid.closeCell();
grid.cancelCell();
this.editService.saveChanges();
}
public cancelChanges(grid: any): void {
grid.cancelCell();
this.editService.cancelChanges();
}
public createFormGroup(dataItem: any): FormGroup {
return this.formBuilder.group({
'ProductID': dataItem.ProductID,
'ProductName': [dataItem.ProductName, Validators.required],
'UnitPrice': dataItem.UnitPrice,
'UnitsInStock': [dataItem.UnitsInStock, Validators.compose([Validators.required, Validators.pattern('^[0-9]{1,3}')])],
'Discontinued': dataItem.Discontinued
});
}
}