import * as React from 'react'; import { FormControl, FormGroup, InputGroup, Sizes } from 'react-bootstrap'; import { findDOMNode } from 'react-dom'; import { Icon } from 'react-fa'; import { Observable } from 'rxjs'; import { BaseView, BaseViewProps } from '../../React'; import { BindableInput, BindableProps } from '../BindableInput/BindableInput'; import { CommandButton } from '../CommandButton/CommandButton'; import { ContentTooltip, TooltipPlacement, } from '../ContentTooltip/ContentTooltip'; import { InlineEditViewModel } from './InlineEditViewModel'; export interface InlineEditProps extends BindableProps { controlId?: string; inputType?: string; placeholder?: string; keyboard?: boolean; clickToEdit?: boolean; bsSize?: Sizes; template?: (value: any, view: InlineEditView) => any; editTemplate?: (value: any, view: InlineEditView) => any; errorContent?: | any | (( viewModel: Readonly>, view: InlineEditView, ) => any); errorPlacement?: TooltipPlacement; } export interface InlineEditViewProps extends BaseViewProps>, InlineEditProps {} export class InlineEditView extends BaseView< InlineEditViewProps, InlineEditViewModel<{}> > { public static displayName = 'InlineEditView'; static defaultProps: Partial = { inputType: 'text', placeholder: 'Enter New Value...', template: (x: any, view: InlineEditView) => x.toString(), editTemplate: (x: any, view: InlineEditView) => ( ), errorContent: (
Sorry, your change was not saved.
Please try again.
), errorPlacement: 'right', }; private handleKeyDown(e: React.KeyboardEvent) { switch (e.keyCode) { case 13: // ENTER key this.viewModel.save.execute(null); break; case 27: // ESC key this.viewModel.cancel.execute(null); break; default: break; } } private focusAndSelectControlText( instance: React.ReactInstance | null | undefined, ) { this.wxr.focusElement(instance, (x: HTMLInputElement) => { if (x.select instanceof Function) { x.select(); } }); } updateOn(viewModel: Readonly>) { return [ viewModel.isEditing.changed, viewModel.hasSavingError.changed, viewModel.save.canExecuteObservable, ]; } render() { return this.wxr.renderConditional( this.viewModel.isEditing, () => this.renderEditor(), () => this.renderValue(), ); } private renderErrorTooltip() { return (
{this.wxr.renderConditional( this.props.errorContent instanceof Function, () => { return this.props.errorContent(this.viewModel, this); }, () => this.props.errorContent, )}
); } private renderEditor() { const { className, props, rest } = this.restProps(x => { const { controlId, inputType, placeholder, converter, valueProperty, onChangeProperty, valueGetter, valueSetter, keyboard, clickToEdit, template, editTemplate, errorContent, errorPlacement, } = x; return { controlId, inputType, placeholder, converter, valueProperty, onChangeProperty, valueGetter, valueSetter, keyboard, clickToEdit, template, editTemplate, errorContent, errorPlacement, }; }); return ( {this.wxr.renderConditional(this.viewModel.hasSavingError, () => ( ))} {this.renderBindableInput()} ); } private renderBindableInput() { const { props } = this.restProps(x => { const { converter, valueProperty, onChangeProperty, valueGetter, valueSetter, } = x; return { converter, valueProperty, onChangeProperty, valueGetter, valueSetter, }; }); const onKeyDown = this.props.keyboard === true ? (e: React.KeyboardEvent) => this.handleKeyDown(e) : undefined; return ( {React.cloneElement( this.props.editTemplate!(this.viewModel.editValue.value, this), { // ref: (x: Element | null) => this.focusAndSelectControlText(x), ref: x => this.focusAndSelectControlText(x), } as { ref: React.Ref }, )} ); } private renderValue() { const { className, props, rest } = this.restProps(x => { const { controlId, inputType, placeholder, converter, valueProperty, onChangeProperty, valueGetter, valueSetter, keyboard, clickToEdit, template, editTemplate, errorContent, errorPlacement, } = x; return { controlId, inputType, placeholder, converter, valueProperty, onChangeProperty, valueGetter, valueSetter, keyboard, clickToEdit, template, editTemplate, errorContent, errorPlacement, }; }); const displayContent = ( {this.props.template!(this.viewModel.value.value, this)} ); return this.wxr.renderConditional( props.clickToEdit === true, () => ( {displayContent} ), () => displayContent, ); } }