From 07fc248626e55dd0df212467d18d517b3747feca Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Thu, 7 May 2020 16:07:49 +0200 Subject: [PATCH] Field/panel options - do not trigger change events onChange, but onBlur or enter key press (#24388) * Field options - do not trigger change events onChange, but onBlur or enter key press * Review changes * fix ts --- .../src/components/OptionsUI/number.tsx | 37 +++++++++--- .../src/components/OptionsUI/string.tsx | 27 +++++++-- .../ValueMappingsEditor/MappingRow.tsx | 57 ++++++++++++++----- 3 files changed, 95 insertions(+), 26 deletions(-) diff --git a/packages/grafana-ui/src/components/OptionsUI/number.tsx b/packages/grafana-ui/src/components/OptionsUI/number.tsx index 572599ddc8f..8c1e91c7688 100644 --- a/packages/grafana-ui/src/components/OptionsUI/number.tsx +++ b/packages/grafana-ui/src/components/OptionsUI/number.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useCallback } from 'react'; import { FieldConfigEditorProps, toIntegerOrUndefined, @@ -13,19 +13,42 @@ export const NumberValueEditor: React.FC { const { settings } = item; + + const onValueChange = useCallback( + (e: React.SyntheticEvent) => { + if (e.hasOwnProperty('key')) { + // handling keyboard event + const evt = e as React.KeyboardEvent; + if (evt.key === 'Enter') { + onChange( + settings?.integer + ? toIntegerOrUndefined(evt.currentTarget.value) + : toFloatOrUndefined(evt.currentTarget.value) + ); + } + } else { + // handling form event + const evt = e as React.FormEvent; + onChange( + settings?.integer + ? toIntegerOrUndefined(evt.currentTarget.value) + : toFloatOrUndefined(evt.currentTarget.value) + ); + } + }, + [onChange] + ); + return ( { - onChange( - settings?.integer ? toIntegerOrUndefined(e.currentTarget.value) : toFloatOrUndefined(e.currentTarget.value) - ); - }} + onBlur={onValueChange} + onKeyDown={onValueChange} /> ); }; diff --git a/packages/grafana-ui/src/components/OptionsUI/string.tsx b/packages/grafana-ui/src/components/OptionsUI/string.tsx index 9f5fe2f3f5c..c5ddcc3028d 100644 --- a/packages/grafana-ui/src/components/OptionsUI/string.tsx +++ b/packages/grafana-ui/src/components/OptionsUI/string.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useCallback } from 'react'; import { FieldConfigEditorProps, StringFieldConfigSettings } from '@grafana/data'; import { Input } from '../Input/Input'; import { TextArea } from '../TextArea/TextArea'; @@ -9,14 +9,31 @@ export const StringValueEditor: React.FC { const Component = item.settings?.useTextarea ? TextArea : Input; + + const onValueChange = useCallback( + (e: React.SyntheticEvent) => { + if (e.hasOwnProperty('key')) { + // handling keyboard event + const evt = e as React.KeyboardEvent; + if (evt.key === 'Enter' && !item.settings?.useTextarea) { + onChange(evt.currentTarget.value.trim() === '' ? undefined : evt.currentTarget.value); + } + } else { + // handling form event + const evt = e as React.FormEvent; + onChange(evt.currentTarget.value.trim() === '' ? undefined : evt.currentTarget.value); + } + }, + [onChange] + ); + return ( ) => - onChange(e.currentTarget.value.trim() === '' ? undefined : e.currentTarget.value) - } + onBlur={onValueChange} + onKeyDown={onValueChange} /> ); }; diff --git a/packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx b/packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx index ddd402fe29d..473c16f746e 100644 --- a/packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx +++ b/packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx @@ -1,4 +1,4 @@ -import React, { ChangeEvent } from 'react'; +import React from 'react'; import { HorizontalGroup } from '../Layout/Layout'; import { IconButton, Label, RadioButtonGroup } from '../index'; import { Field } from '../Forms/Field'; @@ -19,41 +19,61 @@ const MAPPING_OPTIONS: Array> = [ export const MappingRow: React.FC = ({ valueMapping, updateValueMapping, removeValueMapping }) => { const { type } = valueMapping; - const onMappingValueChange = (event: ChangeEvent) => { - updateValueMapping({ ...valueMapping, value: event.target.value }); + const onMappingValueChange = (value: string) => { + updateValueMapping({ ...valueMapping, value: value }); }; - const onMappingFromChange = (event: ChangeEvent) => { - updateValueMapping({ ...valueMapping, from: event.target.value }); + const onMappingFromChange = (value: string) => { + updateValueMapping({ ...valueMapping, from: value }); }; - const onMappingToChange = (event: ChangeEvent) => { - updateValueMapping({ ...valueMapping, to: event.target.value }); + const onMappingToChange = (value: string) => { + updateValueMapping({ ...valueMapping, to: value }); }; - const onMappingTextChange = (event: ChangeEvent) => { - updateValueMapping({ ...valueMapping, text: event.target.value }); + const onMappingTextChange = (value: string) => { + updateValueMapping({ ...valueMapping, text: value }); }; const onMappingTypeChange = (mappingType: MappingType) => { updateValueMapping({ ...valueMapping, type: mappingType }); }; + const onKeyDown = (handler: (value: string) => void) => (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + handler(e.currentTarget.value); + } + }; + const renderRow = () => { if (type === MappingType.RangeToText) { return ( <> - + onMappingFromChange(e.currentTarget.value)} + onKeyDown={onKeyDown(onMappingFromChange)} + /> - + onMappingToChange(e.currentTarget.value)} + onKeyDown={onKeyDown(onMappingToChange)} + /> - + onMappingTextChange(e.currentTarget.value)} + onKeyDown={onKeyDown(onMappingTextChange)} + /> ); @@ -62,11 +82,20 @@ export const MappingRow: React.FC = ({ valueMapping, updateValueMapping, return ( <> - + onMappingValueChange(e.currentTarget.value)} + onKeyDown={onKeyDown(onMappingValueChange)} + /> - + onMappingTextChange(e.currentTarget.value)} + onKeyDown={onKeyDown(onMappingTextChange)} + /> );