소개 | OverView (React)

FlexGrid는 빠르고 유연하며 자바스크립트 DataGrid와 친숙합니다. 핵심 그리드 모듈은 일반적인 기능이 모두 포함되어 있습니다. 더 나아가 확장 기능과 그리드 사용자 정의가 가능한 유연한 API도 포함되어 있습니다.

이 샘플은 정렬, 그룹화, 검색, Excel과 유사한 필터링, DataMaps, 사용자 정의 CellTemplates, 스파크라인, 리치 편집, Excel/PDF 내보내기, 유효성검사, DetailRows와 같은 FlexGrid의 많은 기능을 보여 줍니다.

데이터 항목 수를 변경하여 대규모 데이터 집합을 사용하더라고 그리드가 어떻게 빠르게 유지되는지 알아봅시다. FlexGrid는 행과 열을 자동으로 가상화하여 높은 수준의 성능을 달성하였습니다.

이 데모는 React를 기반으로합니다.

import 'bootstrap.css'; import '@mescius/wijmo.styles/wijmo.css'; import ReactDOM from 'react-dom/client'; import React, { useEffect, useRef, useState } from 'react'; import useEvent from 'react-use-event-hook'; import '@mescius/wijmo.touch'; import * as wjCore from '@mescius/wijmo'; import { InputDate, InputTime } from '@mescius/wijmo.input'; import { CellMaker, SparklineMarkers } from '@mescius/wijmo.grid.cellmaker'; import { DataMap } from '@mescius/wijmo.grid'; import { FlexGrid, FlexGridColumn, FlexGridCellTemplate } from '@mescius/wijmo.react.grid'; import { FlexGridFilter } from '@mescius/wijmo.react.grid.filter'; import { FlexGridSearch } from '@mescius/wijmo.react.grid.search'; import { GroupPanel as FlexGridGroupPanel } from '@mescius/wijmo.react.grid.grouppanel'; import './app.css'; import { DataService, Country, KeyValue } from './data'; import { ExportService } from './export'; const dataService = new DataService(); const exportService = new ExportService(); const buildDataMap = (items) => { const map = []; for (let i = 0; i < items.length; i++) { map.push({ key: i, value: items[i] }); } return new DataMap(map, 'key', 'value'); }; function App() { const [count, setCount] = useState(0); const [itemsCount, setItemsCount] = useState(500); const [isExcelPreparing, setIsExcelPreparing] = useState(false); const [isExcelExporting, setIsExcelExporting] = useState(false); const [excelProgress, setExcelProgress] = useState(0); const flex = useRef(null); const theGrid = useRef(null); const theSearch = useRef(null); const lastId = useRef(itemsCount); const productMap = useRef(buildDataMap(dataService.getProducts())); const countryMap = useRef(new DataMap(dataService.getCountries(), 'id', 'name')); const colorMap = useRef(buildDataMap(dataService.getColors())); const dateEditor = useRef(new InputDate(document.createElement('div'), { format: 'MM/dd/yyyy', isRequired: false })); const timeEditor = useRef(new InputTime(document.createElement('div'), { format: 'HH:mm', isRequired: false })); const historyCellTemplate = useRef(CellMaker.makeSparkline({ markers: SparklineMarkers.High | SparklineMarkers.Low, maxPoints: 25, label: 'price history', })); const ratingCellTemplate = useRef(CellMaker.makeRating({ range: [1, 5], label: 'rating' })); const forceUpdate = () => setCount(count + 1); useEffect(() => { exportService.cancelExcelExport(); // connect search box and grid theSearch.current.control.grid = theGrid.current.control; }, []); const countryCellTemplate = useEvent((ctx) => { const country = countryMap.current.getDataItem(ctx.item.countryId) || Country.NotFound; return (<React.Fragment> <span className={`flag-icon flag-icon-${country.flag}`}/> {' '}{country.name}{' '} </React.Fragment>); }); const colorCellTemplate = useEvent((ctx) => { const color = (colorMap.current.getDataItem(ctx.item.colorId) || KeyValue.NotFound).value; return (<React.Fragment> <span className="color-tile" style={{ background: color }}/> {' '}{color}{' '} </React.Fragment>); }); const changeCellTemplate = useEvent((ctx) => { const change = ctx.item.change; let cssClass = ''; let displayValue = ''; if (wjCore.isNumber(change)) { if (change > 0) { cssClass = 'change-up'; } else if (change < 0) { cssClass = 'change-down'; } displayValue = wjCore.Globalize.formatNumber(change, 'c'); } else if (!wjCore.isUndefined(change) && change !== null) { displayValue = wjCore.changeType(change, wjCore.DataType.String); } return (<span className={cssClass}> {displayValue} </span>); }); const gridInitialized = useEvent((ctl) => { ctl.itemsSource = createItemsSource(itemsCount); flex.current = ctl; forceUpdate(); }); const itemsCountChanged = (e) => { const itemsCount = parseInt(e.target.value); setItemsCount(itemsCount); flex.current.itemsSource.collectionChanged.removeAllHandlers(); lastId.current = itemsCount; flex.current.itemsSource = createItemsSource(itemsCount); }; const exportToExcel = () => { const preparing = isExcelPreparing; const exporting = isExcelExporting; const resetState = () => { setIsExcelPreparing(false); setIsExcelExporting(false); setExcelProgress(0); }; if (!preparing && !exporting) { setIsExcelPreparing(true); exportService.startExcelExport(flex.current, () => { console.log('Export to Excel completed'); resetState(); }, (err) => { console.error(`Export to Excel failed: ${err}`); resetState(); }, (prg) => { setIsExcelPreparing(false); setIsExcelExporting(false); setExcelProgress(prg); }); console.log('Export to Excel started'); } else { exportService.cancelExcelExport(() => { console.log('Export to Excel canceled'); resetState(); }); } }; const exportToPdf = () => { exportService.exportToPdf(flex.current, { countryMap: countryMap.current, colorMap: colorMap.current, historyCellTemplate: historyCellTemplate.current, }); }; const createItemsSource = (counter) => { const data = dataService.getData(counter || 10); const view = new wjCore.CollectionView(data, { getError: (item, prop) => { const displayName = flex.current.columns.getColumn(prop).header; return dataService.validate(item, prop, displayName); } }); view.collectionChanged.addHandler((s, e) => { // initializes new added item with a history data if (e.action === wjCore.NotifyCollectionChangedAction.Add) { e.item.history = dataService.getHistoryData(); e.item.id = lastId.current; lastId.current++; } }); return view; }; return (<div className="container-fluid"> <div className="row"> <div className="toolbar-item col-sm-3 col-md-5"> <FlexGridSearch ref={theSearch} placeholder="Search" cssMatch=""/> </div> <div className="toolbar-item col-sm-3 col-md-3"> <div className="input-group"> <span className="input-group-addon">Items:</span> <select className="form-control" value={itemsCount} onChange={itemsCountChanged}> <option value="5">5</option> <option value="50">50</option> <option value="500">500</option> <option value="5000">5,000</option> <option value="50000">50,000</option> <option value="100000">100,000</option> </select> </div> </div> <div className="toolbar-item col-sm-3 col-md-2"> <button className="btn btn-default btn-block" disabled={isExcelPreparing} onClick={exportToExcel}> {isExcelExporting ? `Cancel (${excelProgress}% done)` : 'Export To Excel'} </button> </div> <div className="toolbar-item col-sm-3 col-md-2"> <button className="btn btn-default btn-block" onClick={exportToPdf}>Export To PDF</button> </div> </div> <FlexGridGroupPanel grid={flex.current} placeholder={"Drag columns here to create groups"}/> <FlexGrid ref={theGrid} autoGenerateColumns={false} allowAddNew allowDelete allowPinning="SingleColumn" newRowAtTop showMarquee selectionMode="MultiRange" validateEdits={false} initialized={gridInitialized}> <FlexGridFilter /> <FlexGridColumn header="ID" binding="id" width={70} isReadOnly={true}/> <FlexGridColumn header="Date" binding="date" format="MMM d yyyy" isRequired={false} width={130} editor={dateEditor.current}/> <FlexGridColumn header="Country" binding="countryId" dataMap={countryMap.current} width={145}> <FlexGridCellTemplate cellType="Cell" template={countryCellTemplate}/> </FlexGridColumn> <FlexGridColumn header="Price" binding="price" format="c" isRequired={false} width={100}/> <FlexGridColumn header="History" binding="history" align="center" width={180} allowSorting={false} cellTemplate={historyCellTemplate.current}/> <FlexGridColumn header="Change" binding="change" align="right" width={115}> <FlexGridCellTemplate cellType="Cell" template={changeCellTemplate}/> </FlexGridColumn> <FlexGridColumn header="Rating" binding="rating" align="center" width={180} cssClass="cell-rating" cellTemplate={ratingCellTemplate.current}/> <FlexGridColumn header="Time" binding="time" format="HH:mm" isRequired={false} width={95} editor={timeEditor.current}> </FlexGridColumn> <FlexGridColumn header="Color" binding="colorId" dataMap={colorMap.current} width={145}> <FlexGridCellTemplate cellType="Cell" template={colorCellTemplate}/> </FlexGridColumn> <FlexGridColumn header="Product" binding="productId" dataMap={productMap.current} width={145}/> <FlexGridColumn header="Discount" binding="discount" format="p0" width={130}/> <FlexGridColumn header="Active" binding="active" width={100}/> </FlexGrid> </div>); } const container = document.getElementById('app'); if (container) { const root = ReactDOM.createRoot(container); root.render(<App />); }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>MESCIUS Wijmo Wijmo FlexGrid Overview</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.40/system.src.js" integrity="sha512-G6mEj6h18+m3MvzdviSDfPle/TfH0//cXcB33AKlNR/Rha0yQsKefDZKRTkIZos97HEGq2JMV1RT5ybMoQ3WsQ==" crossorigin="anonymous"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div id="app"></div> </body> </html>
@import url('https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/3.1.0/css/flag-icon.css'); body { font-size: 1.5em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI Light", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; } .toolbar-item { margin-bottom: 6px; } .wj-flexgridsearch { width: 100%; } .wj-flexgrid { height: 330px; } .wj-flexgrid .wj-cell { padding: 7px; border: none; } .wj-cell.wj-state-invalid:not(.wj-header)::after { top: -14px; border: 14px solid transparent; border-right-color: red; } .flag-icon { box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.4); } .color-tile { display: inline-block; position: relative; width: 1em; height: 1em; border-radius: 50%; box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.4); vertical-align: middle; } .change-up { color: darkgreen; } .change-up:after { content: '\25b2'; margin-left: 0.5em; } .change-down { color: darkred; } .change-down:after { content: '\25bc'; margin-left: 0.5em; } .cell-rating { font-size: 12px; } .wj-flexgrid .wj-detail { padding: 4px 16px; } .wj-detail h3 { margin: 10px 0; }
import * as wjcCore from '@mescius/wijmo'; import { RequiredValidator, MinNumberValidator, MinDateValidator, MaxNumberValidator, MaxDateValidator } from './validation'; export class KeyValue { } KeyValue.NotFound = { key: -1, value: '' }; export class Country { } Country.NotFound = { id: -1, name: '', flag: '' }; export class DataService { constructor() { this._products = ['Widget', 'Gadget', 'Doohickey']; this._colors = ['Black', 'White', 'Red', 'Green', 'Blue']; this._countries = [ { id: 0, name: 'US', flag: 'us' }, { id: 1, name: 'Germany', flag: 'de' }, { id: 2, name: 'UK', flag: 'gb' }, { id: 3, name: 'Japan', flag: 'jp' }, { id: 4, name: 'Italy', flag: 'it' }, { id: 5, name: 'Greece', flag: 'gr' } ]; this._validationConfig = { 'date': [ new RequiredValidator(), new MinDateValidator(new Date('2000-01-01T00:00:00')), new MaxDateValidator(new Date('2100-01-01T00:00:00')) ], 'time': [ new RequiredValidator(), new MinDateValidator(new Date('2000-01-01T00:00:00')), new MaxDateValidator(new Date('2100-01-01T00:00:00')) ], 'productId': [ new RequiredValidator(), new MinNumberValidator(0, `{0} can't be less than {1} (${this._products[0]})`), new MaxNumberValidator(this._products.length - 1, `{0} can't be greater than {1} (${this._products[this._products.length - 1]})`) ], 'countryId': [ new RequiredValidator(), new MinNumberValidator(0, `{0} can't be less than {1} (${this._countries[0].name})`), new MaxNumberValidator(this._countries.length - 1, `{0} can't be greater than {1} (${this._countries[this._countries.length - 1].name})`) ], 'colorId': [ new RequiredValidator(), new MinNumberValidator(0, `{0} can't be less than {1} (${this._colors[0]})`), new MaxNumberValidator(this._colors.length - 1, `{0} can't be greater than {1} (${this._colors[this._colors.length - 1]})`) ], 'price': [ new RequiredValidator(), new MinNumberValidator(0, `Price can't be a negative value`) ] }; } getCountries() { return this._countries; } getProducts() { return this._products; } getColors() { return this._colors; } getHistoryData() { return this._getRandomArray(25, 100); } getData(count) { const data = []; const dt = new Date(); const year = dt.getFullYear(); const itemsCount = Math.max(count, 5); // add items for (let i = 0; i < itemsCount; i++) { const item = this._getItem(i, year); data.push(item); } // set invalid data to demonstrate errors visualization data[1].price = -2000; data[2].date = new Date('1970-01-01T00:00:00'); data[4].time = undefined; data[4].price = -1000; return data; } validate(item, prop, displayName) { const validators = this._validationConfig[prop]; if (wjcCore.isUndefined(validators)) { return ''; } const value = item[prop]; for (let i = 0; i < validators.length; i++) { const validationError = validators[i].validate(displayName, value); if (!wjcCore.isNullOrWhiteSpace(validationError)) { return validationError; } } } _getItem(i, year) { const date = new Date(year, i % 12, 25, i % 24, i % 60, i % 60); const countryIndex = this._getRandomIndex(this._countries); const productIndex = this._getRandomIndex(this._products); const colorIndex = this._getRandomIndex(this._colors); const item = { id: i, date: date, time: new Date(date.getTime() + Math.random() * 30 * (24 * 60 * 60 * 1000)), countryId: this._countries[countryIndex].id, productId: productIndex, colorId: colorIndex, price: wjcCore.toFixed(Math.random() * 10000 + 5000, 2, true), change: wjcCore.toFixed(Math.random() * 1000 - 500, 2, true), history: this.getHistoryData(), discount: wjcCore.toFixed(Math.random() / 4, 2, true), rating: this._getRating(), active: i % 4 == 0, size: Math.floor(100 + Math.random() * 900), weight: Math.floor(100 + Math.random() * 900), quantity: Math.floor(Math.random() * 10), description: "Across all our software products and services, our focus is on helping our customers achieve their goals. Our key principles – thoroughly understanding our customers' business objectives, maintaining a strong emphasis on quality, and adhering to the highest ethical standards – serve as the foundation for everything we do." }; return item; } _getRating() { return Math.ceil(Math.random() * 5); } _getRandomIndex(arr) { return Math.floor(Math.random() * arr.length); } _getRandomArray(len, maxValue) { const arr = []; for (let i = 0; i < len; i++) { arr.push(Math.floor(Math.random() * maxValue)); } return arr; } }
import * as wjcCore from '@mescius/wijmo'; import * as wjcGrid from '@mescius/wijmo.grid'; import * as wjcGridPdf from '@mescius/wijmo.grid.pdf'; import * as wjcGridXlsx from '@mescius/wijmo.grid.xlsx'; import * as wjcPdf from '@mescius/wijmo.pdf'; import * as wjcXlsx from '@mescius/wijmo.xlsx'; import { KeyValue, Country } from './data'; const ExcelExportDocName = 'FlexGrid.xlsx'; const PdfExportDocName = 'FlexGrid.pdf'; const FakeColumn = new wjcGrid.Column(); const FakeRow = new wjcGrid.Row(); class Fonts { } Fonts.ZapfDingbatsSm = new wjcPdf.PdfFont('zapfdingbats', 8, 'normal', 'normal'); Fonts.ZapfDingbatsLg = new wjcPdf.PdfFont('zapfdingbats', 16, 'normal', 'normal'); export class IExcelExportContext { } export class ExportService { startExcelExport(flex, successCallback, errorCallback, progressCallback) { wjcGridXlsx.FlexGridXlsxConverter.saveAsync(flex, { includeColumnHeaders: true, includeStyles: false, formatItem: this._formatExcelItem }, ExcelExportDocName, successCallback, errorCallback, progressCallback, true); } cancelExcelExport(doneCollback) { wjcGridXlsx.FlexGridXlsxConverter.cancelAsync(doneCollback); } exportToPdf(flex, options) { wjcGridPdf.FlexGridPdfConverter.export(flex, PdfExportDocName, { maxPages: 100, exportMode: wjcGridPdf.ExportMode.All, scaleMode: wjcGridPdf.ScaleMode.ActualSize, documentOptions: { pageSettings: { layout: wjcPdf.PdfPageOrientation.Landscape }, header: { declarative: { text: '\t&[Page]\\&[Pages]' } }, footer: { declarative: { text: '\t&[Page]\\&[Pages]' } } }, styles: { cellStyle: { backgroundColor: '#ffffff', borderColor: '#c6c6c6' }, altCellStyle: { backgroundColor: '#f9f9f9' }, groupCellStyle: { backgroundColor: '#dddddd' }, headerCellStyle: { backgroundColor: '#eaeaea' }, // Highlight Invalid Cells errorCellStyle: { backgroundColor: 'rgba(255, 0, 0, 0.3)' } }, customCellContent: false, formatItem: (e) => this._formatPdfItem(e, options) }); } _formatExcelItem(e) { const panel = e.panel; if (panel.cellType !== wjcGrid.CellType.Cell) { return; } // highlight invalid cells if (panel.grid._getError(panel, e.row, e.col)) { const fill = new wjcXlsx.WorkbookFill(); fill.color = '#ff0000'; e.xlsxCell.style.fill = fill; } } _resetExcelContext(ctx) { ctx.exporting = false; ctx.progress = 0; ctx.preparing = false; } _formatPdfItem(e, options) { const panel = e.panel; if (panel.cellType !== wjcGrid.CellType.Cell) { return; } switch (panel.columns[e.col].binding) { case 'countryId': this._formatPdfCountryCell(e, options.countryMap); break; case 'colorId': this._formatPdfColorCell(e, options.colorMap); break; case 'change': this._formatPdfChangeCell(e); break; case 'history': /*** Version #1: get grid cell produced before by a cell template ***/ // const cell = e.getFormattedCell(); // this._formatPdfHistoryCell(e, cell); /*** Version #2: create fake cell from a cell template ***/ const history = e.panel.getCellData(e.row, e.col, false); const cell = this._createCellFromCellTemplate(options.historyCellTemplate, history); this._formatPdfHistoryCell(e, cell); break; case 'rating': this._formatPdfRatingCell(e); break; } } _formatPdfCountryCell(e, countryMap) { e.drawBackground(e.style.backgroundColor); // check whether country exists const countryName = e.data; if (this._isCountryExist(countryName, countryMap)) { // bound rectangle of cell's content area const contentRect = e.contentRect; // draw flag image const image = e.canvas.openImage(`resources/${countryName.toLowerCase()}.png`); const imageTop = contentRect.top + (contentRect.height - image.height) / 2; e.canvas.drawImage(image, contentRect.left, imageTop); // draw country name e.canvas.drawText(countryName, contentRect.left + image.width + 3, e.textTop); } // cancel standard cell content drawing e.cancel = true; } _formatPdfColorCell(e, colorMap) { e.drawBackground(e.style.backgroundColor); // check whether color exists const colorName = e.data; if (this._isColorExist(colorName, colorMap)) { // bound rectangle of cell's content area const contentRect = e.contentRect; // draw color indicator const imageHeight = Math.min(10, contentRect.height); const imageWidth = 1.33 * imageHeight; const imageTop = contentRect.top + (contentRect.height - imageHeight) / 2; e.canvas.paths .rect(contentRect.left, imageTop, imageWidth, imageHeight) .fillAndStroke(wjcCore.Color.fromString(colorName), wjcCore.Color.fromString('gray')); // draw color name e.canvas.drawText(colorName, contentRect.left + imageWidth + 3, e.textTop); } // cancel standard cell content drawing e.cancel = true; } _formatPdfChangeCell(e) { e.drawBackground(e.style.backgroundColor); // get change value and text const cellData = e.panel.getCellData(e.row, e.col, false); let change = 0; let changeText = ''; if (wjcCore.isNumber(cellData)) { change = cellData; changeText = wjcCore.Globalize.formatNumber(change, 'c'); } else if (!wjcCore.isUndefined(cellData) && cellData !== null) { changeText = wjcCore.changeType(cellData, wjcCore.DataType.String); } // determine whether change is positive or negative let changeIndicator = ''; let changeColor = e.style.color; if (change > 0) { changeIndicator = '\x73'; // ▲ changeColor = 'darkgreen'; } else if (change < 0) { changeIndicator = '\x74'; // ▼ changeColor = 'darkred'; } // draw change indicator let indent = 10; e.canvas.drawText(changeIndicator, e.contentRect.right - indent, e.contentRect.top + indent, { brush: changeColor, font: Fonts.ZapfDingbatsSm }); // draw change text indent += 3; e.canvas.drawText(changeText, e.contentRect.left, e.textTop, { brush: changeColor, align: wjcPdf.PdfTextHorizontalAlign.Right, width: e.contentRect.width - indent }); // cancel standard cell content drawing e.cancel = true; } _formatPdfHistoryCell(e, cell) { e.drawBackground(e.style.backgroundColor); // draw history svg const svgUrl = this._getHistorySvgDataUrlFromCell(cell, e.clientRect.width, e.clientRect.height); if (svgUrl) { let cr = e.contentRect; e.canvas.drawSvg(svgUrl, cr.left + 2, cr.top + 2, { width: cr.width - 4, height: cr.height - 4 }); } // cancel standard cell content drawing e.cancel = true; } _getHistorySvgDataUrlFromCell(cell, width, height) { let dataUrl = null; // extract SVG from provided cell const svg = cell.getElementsByTagName('svg')[0]; if (svg) { const clone = svg.cloneNode(true); clone.setAttribute('version', '1.1'); clone.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'http://www.w3.org/2000/svg'); clone.style.overflow = 'visible'; clone.style.stroke = '#376092'; clone.style.fill = '#376092'; const s = document.createElement('style'); s.setAttribute('type', 'text/css'); s.innerHTML = `<![CDATA[ line { stroke-width: 2; } circle { stroke-width: 0; stroke-opacity: 0; } .wj-marker { fill: #d00000; opacity: 1; } ]]>`; const defs = document.createElement('defs'); defs.appendChild(s); clone.insertBefore(defs, clone.firstChild); const outer = document.createElement('div'); outer.appendChild(clone); dataUrl = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(outer.innerHTML))); } return dataUrl; } _formatPdfRatingCell(e) { e.drawBackground(e.style.backgroundColor); // check whether rating is defined let rating = wjcCore.changeType(e.data, wjcCore.DataType.Number); if (wjcCore.isInt(rating)) { const ratingIndicator = '\x48'; // ★ const ratingNormalColor = wjcCore.Color.fromRgba(255, 165, 0, 1); // orange const ratingLightColor = wjcCore.Color.fromRgba(255, 165, 0, 0.2); // draw rating indicators const indent = 16; const count = 5; const width = count * indent; const y = e.clientRect.top + indent; let x = e.contentRect.left + (e.contentRect.width - width) / 2; rating = wjcCore.clamp(rating, 1, count); for (let i = 0; i < count; i++) { e.canvas.drawText(ratingIndicator, x, y, { brush: (i < rating) ? ratingNormalColor : ratingLightColor, font: Fonts.ZapfDingbatsLg, height: e.clientRect.height }); x += indent; } } // cancel standard cell content drawing e.cancel = true; } _isCountryExist(countryName, countryMap) { const countryId = countryMap.getKeyValue(countryName); if (wjcCore.isUndefined(countryId) || countryId === null) { return false; } if (countryId === Country.NotFound.id) { return false; } return true; } _isColorExist(colorName, colorMap) { const colorId = colorMap.getKeyValue(colorName); if (wjcCore.isUndefined(colorId) || colorId === null) { return false; } if (colorId === KeyValue.NotFound.key) { return false; } return true; } _createCellFromCellTemplate(cellTemplate, data) { const cell = document.createElement('div'); cellTemplate({ col: FakeColumn, row: FakeRow, value: data, item: null, text: null }, cell); return cell; } }
import * as wjcCore from '@mescius/wijmo'; export class RequiredValidator { validate(name, value) { const message = name + ' is required'; if (wjcCore.isUndefined(value)) { return message; } const str = wjcCore.changeType(value, wjcCore.DataType.String); if (wjcCore.isNullOrWhiteSpace(str)) { return message; } return ''; } } export class MinValueValidator { constructor(minValue, message = '{0} can\'t be less than {1}', format = null) { this.minValue = minValue; this.message = message; this.format = format; } validate(name, value) { if (value < this.minValue) { return wjcCore.format(this.message, { 0: name, 1: this._formatValue(this.minValue) }); } return ''; } } export class MaxValueValidator { constructor(maxValue, message = '{0} can\'t be greater than {1}', format = null) { this.maxValue = maxValue; this.message = message; this.format = format; } validate(name, value) { if (value > this.maxValue) { return wjcCore.format(this.message, { 0: name, 1: this._formatValue(this.maxValue) }); } return ''; } } export class MinNumberValidator extends MinValueValidator { constructor(minValue, message = '{0} can\'t be less than {1}', format = 'n') { super(minValue, message, format); } _formatValue(value) { return wjcCore.Globalize.formatNumber(value, this.format); } } export class MaxNumberValidator extends MaxValueValidator { constructor(maxValue, message = '{0} can\'t be greater than {1}', format = 'n') { super(maxValue, message, format); } _formatValue(value) { return wjcCore.Globalize.formatNumber(value, this.format); } } export class MinDateValidator extends MinValueValidator { constructor(minValue, message = '{0} can\'t be less than {1}', format = 'MM/dd/yyyy') { super(minValue, message, format); } _formatValue(value) { return wjcCore.Globalize.formatDate(value, this.format); } } export class MaxDateValidator extends MaxValueValidator { constructor(maxValue, message = '{0} can\'t be greater than {1}', format = 'MM/dd/yyyy') { super(maxValue, message, format); } _formatValue(value) { return wjcCore.Globalize.formatDate(value, this.format); } }
(function (global) { System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true, react: true }, meta: { '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { 'jszip': 'npm:jszip/dist/jszip.js', '@mescius/wijmo': 'npm:@mescius/wijmo/index.js', '@mescius/wijmo.input': 'npm:@mescius/wijmo.input/index.js', '@mescius/wijmo.styles': 'npm:@mescius/wijmo.styles', '@mescius/wijmo.cultures': 'npm:@mescius/wijmo.cultures', '@mescius/wijmo.chart': 'npm:@mescius/wijmo.chart/index.js', '@mescius/wijmo.chart.analytics': 'npm:@mescius/wijmo.chart.analytics/index.js', '@mescius/wijmo.chart.animation': 'npm:@mescius/wijmo.chart.animation/index.js', '@mescius/wijmo.chart.annotation': 'npm:@mescius/wijmo.chart.annotation/index.js', '@mescius/wijmo.chart.finance': 'npm:@mescius/wijmo.chart.finance/index.js', '@mescius/wijmo.chart.finance.analytics': 'npm:@mescius/wijmo.chart.finance.analytics/index.js', '@mescius/wijmo.chart.hierarchical': 'npm:@mescius/wijmo.chart.hierarchical/index.js', '@mescius/wijmo.chart.interaction': 'npm:@mescius/wijmo.chart.interaction/index.js', '@mescius/wijmo.chart.radar': 'npm:@mescius/wijmo.chart.radar/index.js', '@mescius/wijmo.chart.render': 'npm:@mescius/wijmo.chart.render/index.js', '@mescius/wijmo.chart.webgl': 'npm:@mescius/wijmo.chart.webgl/index.js', '@mescius/wijmo.chart.map': 'npm:@mescius/wijmo.chart.map/index.js', '@mescius/wijmo.gauge': 'npm:@mescius/wijmo.gauge/index.js', '@mescius/wijmo.grid': 'npm:@mescius/wijmo.grid/index.js', '@mescius/wijmo.grid.detail': 'npm:@mescius/wijmo.grid.detail/index.js', '@mescius/wijmo.grid.filter': 'npm:@mescius/wijmo.grid.filter/index.js', '@mescius/wijmo.grid.search': 'npm:@mescius/wijmo.grid.search/index.js', '@mescius/wijmo.grid.grouppanel': 'npm:@mescius/wijmo.grid.grouppanel/index.js', '@mescius/wijmo.grid.multirow': 'npm:@mescius/wijmo.grid.multirow/index.js', '@mescius/wijmo.grid.transposed': 'npm:@mescius/wijmo.grid.transposed/index.js', '@mescius/wijmo.grid.transposedmultirow': 'npm:@mescius/wijmo.grid.transposedmultirow/index.js', '@mescius/wijmo.grid.pdf': 'npm:@mescius/wijmo.grid.pdf/index.js', '@mescius/wijmo.grid.sheet': 'npm:@mescius/wijmo.grid.sheet/index.js', '@mescius/wijmo.grid.xlsx': 'npm:@mescius/wijmo.grid.xlsx/index.js', '@mescius/wijmo.grid.selector': 'npm:@mescius/wijmo.grid.selector/index.js', '@mescius/wijmo.grid.cellmaker': 'npm:@mescius/wijmo.grid.cellmaker/index.js', '@mescius/wijmo.grid.immutable': 'npm:@mescius/wijmo.grid.immutable/index.js', '@mescius/wijmo.touch': 'npm:@mescius/wijmo.touch/index.js', '@mescius/wijmo.cloud': 'npm:@mescius/wijmo.cloud/index.js', '@mescius/wijmo.nav': 'npm:@mescius/wijmo.nav/index.js', '@mescius/wijmo.odata': 'npm:@mescius/wijmo.odata/index.js', '@mescius/wijmo.olap': 'npm:@mescius/wijmo.olap/index.js', '@mescius/wijmo.rest': 'npm:@mescius/wijmo.rest/index.js', '@mescius/wijmo.pdf': 'npm:@mescius/wijmo.pdf/index.js', '@mescius/wijmo.pdf.security': 'npm:@mescius/wijmo.pdf.security/index.js', '@mescius/wijmo.viewer': 'npm:@mescius/wijmo.viewer/index.js', '@mescius/wijmo.xlsx': 'npm:@mescius/wijmo.xlsx/index.js', '@mescius/wijmo.undo': 'npm:@mescius/wijmo.undo/index.js', '@mescius/wijmo.interop.grid': 'npm:@mescius/wijmo.interop.grid/index.js', '@mescius/wijmo.barcode': 'npm:@mescius/wijmo.barcode/index.js', '@mescius/wijmo.barcode.common': 'npm:@mescius/wijmo.barcode.common/index.js', '@mescius/wijmo.barcode.composite': 'npm:@mescius/wijmo.barcode.composite/index.js', '@mescius/wijmo.barcode.specialized': 'npm:@mescius/wijmo.barcode.specialized/index.js', "@mescius/wijmo.react.chart.analytics": "npm:@mescius/wijmo.react.chart.analytics/index.js", "@mescius/wijmo.react.chart.animation": "npm:@mescius/wijmo.react.chart.animation/index.js", "@mescius/wijmo.react.chart.annotation": "npm:@mescius/wijmo.react.chart.annotation/index.js", "@mescius/wijmo.react.chart.finance.analytics": "npm:@mescius/wijmo.react.chart.finance.analytics/index.js", "@mescius/wijmo.react.chart.finance": "npm:@mescius/wijmo.react.chart.finance/index.js", "@mescius/wijmo.react.chart.hierarchical": "npm:@mescius/wijmo.react.chart.hierarchical/index.js", "@mescius/wijmo.react.chart.interaction": "npm:@mescius/wijmo.react.chart.interaction/index.js", "@mescius/wijmo.react.chart.radar": "npm:@mescius/wijmo.react.chart.radar/index.js", "@mescius/wijmo.react.chart": "npm:@mescius/wijmo.react.chart/index.js", "@mescius/wijmo.react.core": "npm:@mescius/wijmo.react.core/index.js", '@mescius/wijmo.react.chart.map': 'npm:@mescius/wijmo.react.chart.map/index.js', "@mescius/wijmo.react.gauge": "npm:@mescius/wijmo.react.gauge/index.js", "@mescius/wijmo.react.grid.detail": "npm:@mescius/wijmo.react.grid.detail/index.js", "@mescius/wijmo.react.grid.filter": "npm:@mescius/wijmo.react.grid.filter/index.js", "@mescius/wijmo.react.grid.grouppanel": "npm:@mescius/wijmo.react.grid.grouppanel/index.js", '@mescius/wijmo.react.grid.search': 'npm:@mescius/wijmo.react.grid.search/index.js', "@mescius/wijmo.react.grid.multirow": "npm:@mescius/wijmo.react.grid.multirow/index.js", "@mescius/wijmo.react.grid.sheet": "npm:@mescius/wijmo.react.grid.sheet/index.js", '@mescius/wijmo.react.grid.transposed': 'npm:@mescius/wijmo.react.grid.transposed/index.js', '@mescius/wijmo.react.grid.transposedmultirow': 'npm:@mescius/wijmo.react.grid.transposedmultirow/index.js', '@mescius/wijmo.react.grid.immutable': 'npm:@mescius/wijmo.react.grid.immutable/index.js', "@mescius/wijmo.react.grid": "npm:@mescius/wijmo.react.grid/index.js", "@mescius/wijmo.react.input": "npm:@mescius/wijmo.react.input/index.js", "@mescius/wijmo.react.olap": "npm:@mescius/wijmo.react.olap/index.js", "@mescius/wijmo.react.viewer": "npm:@mescius/wijmo.react.viewer/index.js", "@mescius/wijmo.react.nav": "npm:@mescius/wijmo.react.nav/index.js", "@mescius/wijmo.react.base": "npm:@mescius/wijmo.react.base/index.js", '@mescius/wijmo.react.barcode.common': 'npm:@mescius/wijmo.react.barcode.common/index.js', '@mescius/wijmo.react.barcode.composite': 'npm:@mescius/wijmo.react.barcode.composite/index.js', '@mescius/wijmo.react.barcode.specialized': 'npm:@mescius/wijmo.react.barcode.specialized/index.js', 'jszip': 'npm:jszip/dist/jszip.js', 'react': 'npm:react/umd/react.production.min.js', 'react-dom': 'npm:react-dom/umd/react-dom.production.min.js', 'react-dom/client': 'npm:react-dom/umd/react-dom.production.min.js', 'redux': 'npm:redux/dist/redux.min.js', 'react-redux': 'npm:react-redux/dist/react-redux.min.js', 'bootstrap.css': 'npm:bootstrap/dist/css/bootstrap.min.css', 'css': 'npm:systemjs-plugin-css/css.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', 'systemjs-babel-build':'npm:systemjs-plugin-babel/systemjs-babel-browser.js', "react-use-event-hook": "npm:react-use-event-hook/dist/esm/useEvent.js", }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'jsx' }, "node_modules": { defaultExtension: 'js' }, } }); })(this);