Edición de cuadrícula React
La Ignite UI for React admite la edición de celdas y filas con actualizaciones por lotes. Tenga en cuenta que, por el momento, esto está limitado a columnas sin plantilla.
React Ejemplo de edición de cuadrícula
export class DataGridSharedData {
public static getEmployees(count?: number ): any [] {
if (count === undefined ) {
count = 250 ;
}
const employees: any [] = [];
let maleCount: number = 0 ;
let femaleCount: number = 0 ;
for (let i = 0 ; i < count; i++) {
const age: number = Math .round(this .getRandomNumber(20 , 40 ));
const gender: string = this .getRandomGender();
const firstName: string = this .getRandomNameFirst(gender);
const lastName: string = this .getRandomNameLast();
const street: string = this .getRandomStreet();
const country: string = this .getRandomItem(this .countries);
const city: string = this .getRandomCity(country);
const generation = Math .floor(age / 10 ) * 10 + "s" ;
const email: string = firstName.toLowerCase() + "@" + this .getRandomItem(this .emails);
const website: string = firstName.toLowerCase() + "-" + this .getRandomItem(this .websites);
let photoPath: any ;
if (gender === "male" ) {
maleCount++;
if (maleCount > 26 ) {
maleCount = 1 ;
}
photoPath = this .getPhotoMale(maleCount);
}
else {
femaleCount++;
if (femaleCount > 24 ) {
femaleCount = 1 ;
}
photoPath = this .getPhotoFemale(femaleCount);
}
let person: any = {};
person.Address = street + "," + city;
person.Age = age;
person.Birthday = this .getBirthday(age);
person.City = city;
person.Country = country;
person.CountryFlag = this .getCountryFlag(country);
person.Email = email;
person.FirstName = firstName;
person.Gender = this .getGenderPhoto(gender);
person.Generation = generation;
person.ID = this .pad(i + 1 , 5 );
person.LastName = lastName;
person.Name = firstName + " " + lastName;
person.Phone = this .getRandomPhone();
person.Photo = photoPath;
person.Street = street;
person.Salary = this .getRandomNumber(40 , 200 ) * 1000 ;
person.Sales = this .getRandomNumber(200 , 980 ) * 1000 ;
person.Website = website;
person.Productivity = this .getProductivity();
if (person.Salary < 50000 ) {
person.Income = "Low" ;
} else if (person.Salary < 100000 ) {
person.Income = "Average" ;
} else {
person.Income = "High" ;
}
employees.push(person);
}
return employees;
}
public static getProductivity(weekCount?: number ): any [] {
if (weekCount === undefined ) {
weekCount = 52 ;
}
const productivity: any [] = [];
for (let w = 0 ; w < weekCount; w++) {
const value = this .getRandomNumber(-50 , 50 );
productivity.push({Value : value, Week : w});
}
return productivity;
}
public static getSales(count?: number ): any [] {
if (count === undefined ) {
count = 250 ;
}
const names: string [] = [
"Intel CPU" , "AMD CPU" ,
"Intel Motherboard" , "AMD Motherboard" , "NVIDIA Motherboard" ,
"NVIDIA GPU" , "GIGABYTE GPU" , "Asus GPU" , "AMD GPU" , "MSI GPU" ,
"Corsair Memory" , "Patriot Memory" , "Skill Memory" ,
"Samsung HDD" , "WD HDD" , "Seagate HDD" , "Intel HDD" ,
"Samsung SSD" , "WD SSD" , "Seagate SSD" , "Intel SSD" ,
"Samsung Monitor" , "Asus Monitor" , "LG Monitor" , "HP Monitor" ];
const countries: string [] = ["USA" , "UK" , "France" , "Canada" , "Poland" , "Japan" , "Germany" ];
const status: string [] = ["Packing" , "Shipped" , "Delivered" ];
const sales: any [] = [];
for (let i = 0 ; i < count; i++) {
const price = this .getRandomNumber(100 , 900 );
const items = this .getRandomNumber(10 , 80 );
const value = price * items;
const margin = this .getRandomNumber(3 , 10 );
const profit = Math .round((price * margin / 100 ) * items);
const country = this .getRandomItem(countries);
sales.push({
BundlePrice : price,
ProductPrice : price,
Margin : margin,
OrderDate : this .getRandomDate(new Date (2012 , 0 , 1 ), new Date ()),
OrderItems : items,
OrderValue : value,
ProductID : 1001 + i,
ProductName : this .getRandomItem(names),
Profit : profit,
Countries : country,
CountryFlag : this .getCountryFlag(country),
Status : this .getRandomItem(status)
});
}
return sales;
}
public static getHouses(count?: number ): any [] {
if (count === undefined ) {
count = 250 ;
}
const houses: any [] = [];
const property: string [] = [ "Townhouse" , "Single" , "Condo" , "Villa" ];
const emails: string [] = [ "estates.com" , "remax.com" , "zillow.com" , "realtor.com" , "coldwell.com" ];
const countries: string [] = ["USA" , "UK" , "France" , "Canada" , "Poland" , "Japan" , "Germany" ];
for (let i = 0 ; i < count; i++) {
const year: number = this .getRandomNumber(1950 , 2015 );
const age: number = 2020 - year;
const gender: string = this .getRandomGender();
const firstName: string = this .getRandomNameFirst(gender);
const lastName: string = this .getRandomNameLast();
const initials = firstName.substr(0 , 1 ).toLowerCase();
const email: string = initials + lastName.toLowerCase() + "@" + this .getRandomItem(emails);
const street: string = this .getRandomStreet();
const country: string = this .getRandomItem(countries);
const city: string = this .getRandomCity(country);
houses.push({
Address : street + "," + city,
Age : age,
Agent : firstName + " " + lastName,
Area : this .getRandomNumber(50 , 300 ),
Baths : this .getRandomNumber(1 , 3 ),
Built : year,
City : city,
Country : country,
CountryFlag : this .getCountryFlag(country),
Email : email,
ID : this .pad(i + 1 , 5 ),
Phone : this .getRandomPhone(),
Price : this .getRandomNumber(210 , 900 ) * 1000 ,
Property : this .getRandomItem(property),
Rooms : this .getRandomNumber(2 , 5 ),
SaleDate : this .getRandomDate(new Date (2015 , 0 , 1 ), new Date ()),
Street : street,
});
}
return houses;
}
private static websites: string [] = [ ".com" , ".gov" , ".edu" , ".org" ];
private static emails: string [] = [ "gmail.com" , "yahoo.com" , "twitter.com" ];
private static genders: string [] = ["male" , "female" ];
private static maleNames: string [] = ["Kyle" , "Oscar" , "Ralph" , "Mike" , "Bill" , "Frank" , "Howard" , "Jack" , "Larry" , "Pete" , "Steve" , "Vince" , "Mark" , "Alex" , "Max" , "Brian" , "Chris" , "Andrew" , "Martin" , "Mike" , "Steve" , "Glenn" , "Bruce" ];
private static femaleNames: string [] = ["Gina" , "Irene" , "Katie" , "Brenda" , "Casey" , "Fiona" , "Holly" , "Kate" , "Liz" , "Pamela" , "Nelly" , "Marisa" , "Monica" , "Anna" , "Jessica" , "Sofia" , "Isabella" , "Margo" , "Jane" , "Audrey" , "Sally" , "Melanie" , "Greta" , "Aurora" , "Sally" ];
private static lastNames: string [] = ["Adams" , "Crowley" , "Ellis" , "Martinez" , "Irvine" , "Maxwell" , "Clark" , "Owens" , "Rooney" , "Lincoln" , "Thomas" , "Spacey" , "MOrgan" , "King" , "Newton" , "Fitzgerald" , "Holmes" , "Jefferson" , "Landry" , "Berry" , "Perez" , "Spencer" , "Starr" , "Carter" , "Edwards" , "Stark" , "Johnson" , "Fitz" , "Chief" , "Blanc" , "Perry" , "Stone" , "Williams" , "Lane" , "Jobs" , "Adams" , "Power" , "Tesla" ];
private static countries: string [] = ["USA" , "UK" , "France" , "Canada" , "Poland" ];
private static citiesUS: string [] = ["New York" , "Los Angeles" , "Miami" , "San Francisco" , "San Diego" , "Las Vegas" ];
private static citiesUK: string [] = ["London" , "Liverpool" , "Manchester" ];
private static citiesFR: string [] = ["Paris" , "Marseille" , "Lyon" ];
private static citiesCA: string [] = ["Toronto" , "Vancouver" , "Montreal" ];
private static citiesPL: string [] = ["Krakow" , "Warsaw" , "Wroclaw" , "Gdansk" ];
private static citiesJP: string [] = ["Tokyo" , "Osaka" , "Kyoto" , "Yokohama" ];
private static citiesGR: string [] = ["Berlin" , "Bonn" , "Cologne" , "Munich" , "Hamburg" ];
private static roadSuffixes: string [] = ["Road" , "Street" , "Way" ];
private static roadNames: string [] = ["Main" , "Garden" , "Broad" , "Oak" , "Cedar" , "Park" , "Pine" , "Elm" , "Market" , "Hill" ];
private static getRandomNumber(min: number , max : number ): number {
return Math .round(min + Math .random() * (max - min));
}
private static getRandomItem(array: any []): any {
const index = Math .round(this .getRandomNumber(0 , array.length - 1 ));
return array[index];
}
private static getRandomDate(start: Date , end : Date ): Date {
return new Date (start.getTime() + Math .random() * (end.getTime() - start.getTime()));
}
private static getRandomPhone(): string {
const phoneCode = this .getRandomNumber(100 , 900 );
const phoneNum1 = this .getRandomNumber(100 , 900 );
const phoneNum2 = this .getRandomNumber(1000 , 9000 );
const phone = phoneCode + "-" + phoneNum1 + "-" + phoneNum2;
return phone;
}
private static getRandomGender(): string {
return this .getRandomItem(this .genders);
}
private static getRandomNameLast(): string {
return this .getRandomItem(this .lastNames);
}
private static getRandomNameFirst(gender: string ): string {
if (gender === "male" ) {
return this .getRandomItem(this .maleNames);
}
else {
return this .getRandomItem(this .femaleNames);
}
}
private static getRandomCity(country: string ): string {
if (country === "Canada" ) {
return this .getRandomItem(this .citiesCA);
} else if (country === "France" ) {
return this .getRandomItem(this .citiesFR);
} else if (country === "Poland" ) {
return this .getRandomItem(this .citiesPL);
} else if (country === "USA" ) {
return this .getRandomItem(this .citiesUS);
} else if (country === "Japan" ) {
return this .getRandomItem(this .citiesJP);
} else if (country === "Germany" ) {
return this .getRandomItem(this .citiesGR);
} else {
return this .getRandomItem(this .citiesUK);
}
}
private static getRandomStreet(): string {
const num = Math .round(this .getRandomNumber(100 , 300 )).toString();
const road = this .getRandomItem(this .roadNames);
const suffix = this .getRandomItem(this .roadSuffixes);
return num + " " + road + " " + suffix;
}
private static getBirthday(age: number ): Date {
const today: Date = new Date ();
const year: number = today.getFullYear() - age;
const month: number = this .getRandomNumber(0 , 8 );
const day: number = this .getRandomNumber(10 , 27 );
return new Date (year, month, day);
}
private static getPhotoMale(id: number ): string {
return 'https://static.infragistics.com/xplatform/images/people//GUY' + this .pad(id, 2 ) + '.png' ;
}
private static getPhotoFemale(id: number ): string {
return 'https://static.infragistics.com/xplatform/images/people/GIRL' + this .pad(id, 2 ) + '.png' ;
}
private static getGenderPhoto(gender: string ): string {
return 'https://static.infragistics.com/xplatform/images/genders/' + gender + '.png' ;
}
private static getCountryFlag(country: string ): string {
return 'https://static.infragistics.com/xplatform/images/flags/' + country + '.png' ;
}
private static pad(num: number , size : number ): string {
let s = num + "" ;
while (s.length < size) {
s = "0" + s;
}
return s;
}
}
ts コピー import React from 'react' ;
import ReactDOM from 'react-dom/client' ;
import './index.css' ;
import { DataGridSharedData } from './DataGridSharedData' ;
import { IgrDataGrid } from "@infragistics/igniteui-react-grids" ;
import { IgrDataGridModule } from "@infragistics/igniteui-react-grids" ;
import { IgrTemplateColumn } from "@infragistics/igniteui-react-grids" ;
import { IgrTextColumn } from "@infragistics/igniteui-react-grids" ;
import { IgrNumericColumn } from "@infragistics/igniteui-react-grids" ;
import { IgrDateTimeColumn } from "@infragistics/igniteui-react-grids" ;
import { IgrImageColumn } from "@infragistics/igniteui-react-grids" ;
import { IgrGridColumnOptionsModule } from "@infragistics/igniteui-react-grids" ;
import { IgrTemplateCellUpdatingEventArgs } from "@infragistics/igniteui-react-grids" ;
import { IgrGridCellValueChangingEventArgs } from "@infragistics/igniteui-react-grids" ;
import { IgrGridRowEditEndedEventArgs } from "@infragistics/igniteui-react-grids" ;
import { EditModeType } from "@infragistics/igniteui-react-grids" ;
IgrDataGridModule.register();
IgrGridColumnOptionsModule.register();
export default class DataGridCellEditing extends React.Component <any, any> {
public data: any [];
public grid: IgrDataGrid;
public get canCommit(): boolean {
return this .grid && this .grid.canCommit;
}
public get canUndo(): boolean {
return this .grid && this .grid.canUndo;
}
public get canRedo(): boolean {
return this .grid && this .grid.canRedo;
}
public get editMode(): number {
if (this .grid) {
return this .grid.editMode;
}
return 1 ;
}
constructor (props: any ) {
super (props);
this .data = DataGridSharedData.getEmployees();
}
onGridRef = (grid: IgrDataGrid) => {
if (!grid) { return ; }
this .grid = grid;
}
public get excelEditMode(): number {
if (this .grid) {
return this .grid.editModeClickAction;
}
return 1 ;
}
public render (): JSX .Element {
return (
<div className ="container sample" >
<div className ="options horizontal" >
<button disabled ={!this.canCommit} onClick ={this.onCommitClick} > Commit</button >
<button disabled ={!this.canUndo} onClick ={this.onUndoClick} > Undo</button >
<button disabled ={!this.canRedo} onClick ={this.onRedoClick} > Redo</button >
<label >
Edit Mode:
<select value ={this.editMode} onChange ={this.onEditModeChange} >
<option value ="0" > None</option >
<option value ="1" > Cell</option >
<option value ="2" > CellBatch</option >
<option value ="3" > Row</option >
</select >
</label >
<label >
Excel Style Editing:
<select value ={this.excelEditMode} onChange ={this.onExcelEditModeChange} >
<option value ="1" > SingleClick</option >
<option value ="2" > DoubleClick</option >
</select >
</label >
</div >
<IgrDataGrid
ref ={this.onGridRef}
height ="calc(100% - 40px)"
width ="100%"
defaultColumnMinWidth ={120}
autoGenerateColumns ={false}
dataSource ={this.data}
activationMode ="Cell"
editModeClickAction ="SingleClick"
selectionMode ="SingleRow"
selectionBehavior ="ModifierBased"
isColumnOptionsEnabled ="true"
cellValueChanging ={this.onCellValueChanging}
rowEditEnded ={this.onRowEditEnded}
>
<IgrTextColumn field ="Name" width ="*> 150 "/>
<IgrTextColumn field=" Street" headerText=" Street" width=" *>160 " />
<IgrTextColumn field=" City" headerText=" City" width=" *>120 " />
<IgrNumericColumn field=" Salary" headerText=" Salary" width=" *>120 " positivePrefix=" $" showGroupingSeparator=" true " />
<IgrImageColumn field=" Photo" headerText=" Photo" contentOpacity=" 1 "
horizontalAlignment=" center" width=" *>110 "/>
<IgrDateTimeColumn field=" Birthday" headerText=" Date of Birth" width=" *>170 "/>
<IgrTemplateColumn isColumnOptionsEnabled=" false " field=" DeleteColumn" headerText=" Delete Row" width=" 80 " cellUpdating={this.onDeleteCellUpdating}/>
</IgrDataGrid>
</div>
);
}
onExcelEditModeChange = (event: any) => {
this.grid.editModeClickAction = parseInt(event.target.value);
this.setState({ });
}
//#region Input Control Handlers
onCommitClick = () => {
this.grid.commitEdits();
// request a new render so the undo/redo buttons update.
this.setState({ });
}
onUndoClick = () => {
this.grid.undo();
// request a new render so the undo/redo buttons update.
this.setState({ });
}
onRedoClick = () => {
this.grid.redo();
// request a new render so the undo/redo buttons update.
this.setState({ });
}
onEditModeChange = (event: any) => {
this.grid.cancelEdits();
this.grid.editMode = parseInt(event.target.value);
this.setState({ });
}
//#endregion
//#region Grid Handlers
onDeleteRowClick = (e: MouseEvent) => {
const button = e.srcElement as HTMLButtonElement;
const viewIndex = parseInt(button.id);
const rowItem = this.grid.actualDataSource.getItemAtIndex(viewIndex);
this.grid.removeItem(rowItem);
this.setState({ });
}
onCellValueChanging = (s: IgrDataGrid, e: IgrGridCellValueChangingEventArgs) => {
if(e.newValue === " ") {
s.setEditError(e.editID, " Error, cell is empty");
}
// request a new render so the undo/redo buttons update.
setTimeout(() => this.setState({ }));
}
onRowEditEnded = (s: IgrDataGrid, e: IgrGridRowEditEndedEventArgs) => {
this.setState({});
}
onDeleteCellUpdating = (s: IgrTemplateColumn, e: IgrTemplateCellUpdatingEventArgs) => {
const content = e.content as HTMLDivElement;
if (content.childElementCount === 0) {
const button = document.createElement(" button") as HTMLButtonElement;
button.innerText = " Delete";
button.addEventListener(" click", this.onDeleteRowClick);
content.appendChild(button);
}
const button = content.children[0] as HTMLButtonElement;
button.disabled = e.cellInfo.isDeleted;
button.id = e.cellInfo.dataRow.toString();
}
//#endregion
}
// rendering above class to the React DOM
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<DataGridCellEditing/>);
tsx コピー
¿Te gusta este ejemplo? Obtén acceso a nuestro kit de herramientas completo Ignite UI for React y comienza a crear tus propias aplicaciones en minutos. Descárgalo gratis.
Descripción general
La edición en la cuadrícula de datos React se configura mediante la opción editMode
de la cuadrícula React. Esta propiedad tiene tres opciones diferentes, que se enumeran a continuación:
None
: la edición no está habilitada.
Cell
: permita que las celdas ingresen al modo de edición y confirme el valor al salir del modo de edición.
CellBatch
: permite que las celdas entren en modo de edición, pero los cambios se almacenarán en caché más tarde hasta que se confirmen.
Row
: permite que las filas entren en modo de edición y confirmen el valor al salir.
Cuando se establece en CellBatch
, para confirmar los cambios debe realizar el método commitEdits
desde la cuadrícula. La cuadrícula pondrá en cursiva las celdas hasta que se confirmen, lo que proporciona control sobre cuándo enviar los cambios a la fuente de datos.
Además, el manejo de errores se puede realizar conectando el evento onCellValueChanging
e inspeccionando nuevos valores antes de confirmarlos. La cuadrícula expone un método setEditError
que puede generar un mensaje de error. Esto mantiene la celda en modo de edición hasta que se ingresa un valor válido. De lo contrario, se puede ejecutar el método rejectEdit
de la cuadrícula para revertir el valor no válido. Si no se encuentra ningún valor no válido, también puede confirmar los cambios llamando al método acceptEdit
de la cuadrícula.
Las confirmaciones se pueden aprobar o rechazar en el nivel de la grilla conectando onDataCommitting
a través de los métodos acceptCommit
o rejectCommit
pasando el argumento del evento commitID
como parámetro. Este evento también expone una colección changes
que almacena todas las modificaciones antes de confirmarse. Por ejemplo, puede verificar si una confirmación proviene de una operación de agregar, actualizar o eliminar a través de la propiedad TransactionType
expuesta en la colección changes
y realizar una acceptCommit
o rejectCommit
cuando sea necesario.
Edición de estilo de Excel
editOnKeyPress
le permite comenzar a editar instantáneamente al escribir de manera similar a como se comporta Excel. Además, puede configurar la propiedad editModeClickAction
en SingleClick
para permitir a los usuarios editar celdas rápidamente mientras navegan a otras celdas. De forma predeterminada, es necesario hacer doble clic para ingresar al modo de edición.
Fragmento de código
A continuación se muestra cómo configurar la edición en la cuadrícula de datos y la confirmación de los datos.
<IgrDataGrid
height ="100%"
width ="100%"
activationMode ="Cell"
editMode ="CellBatch" >
</IgrDataGrid >
<button onClick ={this.onCommitClick} > Commit Data</button >
tsx
import { IgrDataGrid } from 'igniteui-react-grids' ;
onCommitClick = () => {
this ._grid.commitEdits();
}
ts
Deshacer/Rehacer cambios por lotes
A continuación se muestra cómo revertir los cambios mientras la actualización por lotes está habilitada.
<IgrDataGrid
height ="100%"
width ="100%"
activationMode ="Cell"
editMode ="CellBatch" >
</IgrDataGrid >
<button disabled ={!this.canUndo} onClick ={this.onUndoClick} > Undo</button >
<button disabled ={!this.canRedo} onClick ={this.onRedoClick} > Redo</button >
tsx
import { IgrDataGrid } from 'igniteui-react-grids' ;
onUndoClick = () => {
this ._grid.undo();
this .setState({ });
}
onRedoClick = () => {
this ._grid.redo();
this .setState({ });
}
ts
Validación de errores e integridad del compromiso
A continuación se muestra cómo incorporar el error al verificar si las celdas están vacías al salir del modo de edición y se aceptan confirmaciones que provienen únicamente de celdas actualizadas.
<IgrDataGrid
height ="100%"
width ="100%"
dataSource ={this.data}
activationMode ="Cell"
cellValueChanging ={this.onCellValueChanging}
dataCommitting ={this.onDataCommitting} >
</IgrDataGrid >
tsx
import { IgrGridDataCommittingEventArgs } from 'igniteui-react-grids' ;
import { TransactionType } from 'igniteui-react-core'
onCellValueChanging = (s: IgrDataGrid, e: IgrGridCellValueChangingEventArgs ) => {
if (e.newValue === "" ) {
s.setEditError(e.editID, "Error, cell is empty" );
s.rejectEdit(e.editID);
}
else {
s.acceptEdit(e.editID);
}
}
onDataCommitting = (s: IgrDataGrid, e: IgrGridDataCommittingEventArgs ) => {
if (e.changes[0 ].transactionType === TransactionType.Update) {
s.acceptCommit(e.commitID);
}
else {
s.rejectCommit(e.commitID);
}
}
ts
Referencias de API