Skip to content

Commit

Permalink
Renovation: Move viewModel to class with component declaration (#12188)
Browse files Browse the repository at this point in the history
* Move viewModel to class

* Update generator version

* fix review remarks

* fix regression
  • Loading branch information
roman-simionov authored Mar 4, 2020
1 parent 7c5b50c commit b53bed5
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 144 deletions.
105 changes: 47 additions & 58 deletions js/renovation/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,80 +46,53 @@ const getAriaLabel = (text, icon) => {
return label ? { label } : {};
};

export const viewModelFunction = (model: Button):ButtonViewModel => {
const props = model.props;
return {
...props,
aria: getAriaLabel(model.props.text, model.props.icon),
contentRef: model.contentRef,
cssClasses: getCssClasses(props),
elementAttr: { ...props.elementAttr, role: 'button' },
iconSource: (props.icon || props.type === 'back') ? (props.icon || 'back') : '',
onActive: model.onActive,
onInactive: model.onInactive,
onWidgetClick: model.onWidgetClick,
onWidgetKeyPress: model.onWidgetKeyPress,
submitInputRef: model.submitInputRef,
};
};

declare type ButtonViewModel = {
contentRef: any;
cssClasses: string;
iconSource: string;
onActive: (e: Event) => any;
onInactive: (e: Event) => any;
onWidgetClick: (e: Event) => any;
onWidgetKeyPress: (e: Event, options:any) => void;
submitInputRef: any;
} & ButtonInput;

export const viewFunction = (viewModel: ButtonViewModel) => {
const renderText = !viewModel.contentRender && viewModel.text;
const isIconLeft = viewModel.iconPosition === 'left';
const leftIcon = !viewModel.contentRender && isIconLeft;
const rightIcon = !viewModel.contentRender && !isIconLeft;
const icon = !viewModel.contentRender && viewModel.iconSource
&& <Icon source={viewModel.iconSource} position={viewModel.iconPosition}/>;
export const viewFunction = (viewModel: Button) => {
const { contentRender, text, iconPosition, icon } = viewModel.props;
const renderText = !contentRender && text;
const isIconLeft = iconPosition === 'left';
const leftIcon = !contentRender && isIconLeft;
const rightIcon = !contentRender && !isIconLeft;
const iconComponent = !contentRender && viewModel.iconSource
&& <Icon source={viewModel.iconSource} position={iconPosition}/>;

return <Widget
accessKey={viewModel.accessKey}
activeStateEnabled={viewModel.activeStateEnabled}
accessKey={viewModel.props.accessKey}
activeStateEnabled={viewModel.props.activeStateEnabled}
aria={viewModel.aria}
className={viewModel.cssClasses}
disabled={viewModel.disabled}
disabled={viewModel.props.disabled}
elementAttr={viewModel.elementAttr}
focusStateEnabled={viewModel.focusStateEnabled}
height={viewModel.height}
hint={viewModel.hint}
hoverStateEnabled={viewModel.hoverStateEnabled}
focusStateEnabled={viewModel.props.focusStateEnabled}
height={viewModel.props.height}
hint={viewModel.props.hint}
hoverStateEnabled={viewModel.props.hoverStateEnabled}
onActive={viewModel.onActive}
onContentReady={viewModel.onContentReady}
onContentReady={viewModel.props.onContentReady}
onClick={viewModel.onWidgetClick}
onInactive={viewModel.onInactive}
onKeyPress={viewModel.onWidgetKeyPress}
rtlEnabled={viewModel.rtlEnabled}
tabIndex={viewModel.tabIndex}
visible={viewModel.visible}
width={viewModel.width}
rtlEnabled={viewModel.props.rtlEnabled}
tabIndex={viewModel.props.tabIndex}
visible={viewModel.props.visible}
width={viewModel.props.width}
>
<div className="dx-button-content" ref={viewModel.contentRef}>
{viewModel.contentRender &&
<viewModel.contentRender
<div className="dx-button-content" ref={viewModel.contentRef as any}>
{contentRender &&
<viewModel.props.contentRender
model={{
icon: viewModel.icon,
text: viewModel.text,
icon,
text,
}}
parentRef={viewModel.contentRef}
/>
}
{leftIcon && icon}
{leftIcon && iconComponent}
{renderText &&
<span className="dx-button-text">{viewModel.text}</span>
<span className="dx-button-text">{text}</span>
}
{rightIcon && icon}
{viewModel.useSubmitBehavior &&
<input ref={viewModel.submitInputRef} type="submit" tabIndex={-1} className="dx-button-submit-input"/>
{rightIcon && iconComponent}
{viewModel.props.useSubmitBehavior &&
<input ref={viewModel.submitInputRef as any} type="submit" tabIndex={-1} className="dx-button-submit-input"/>
}
</div>
</Widget>;
Expand Down Expand Up @@ -159,7 +132,6 @@ const defaultOptionRules = createDefaultOptionRules<ButtonInput>([
@Component({
defaultOptionsRules: defaultOptionRules,
view: viewFunction,
viewModel: viewModelFunction,
})

export default class Button extends JSXComponent<ButtonInput> {
Expand Down Expand Up @@ -207,4 +179,21 @@ export default class Button extends JSXComponent<ButtonInput> {

return () => click.off(this.submitInputRef, { namespace });
}

get aria() {
return getAriaLabel(this.props.text, this.props.icon);
}

get cssClasses():string {
return getCssClasses(this.props);
}

get elementAttr() {
return { ...this.props.elementAttr, role: 'button' };
}

get iconSource(): string {
const { icon, type } = this.props;
return (icon || type === 'back') ? (icon || 'back') : '';
}
}
29 changes: 7 additions & 22 deletions js/renovation/icon.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,7 @@
import { getImageSourceType } from '../core/utils/icon';
import { Component, ComponentBindings, JSXComponent, OneWay, Fragment } from 'devextreme-generator/component_declaration/common';

type IconViewModel = {
cssClass: string;
props: IconInput;
sourceType: string;
};

export const viewModelFunction = (model: Icon): IconViewModel => {
return {
cssClass: model.props.position !== 'left' ? 'dx-icon-right' : '',
props: model.props,
sourceType: getImageSourceType(model.props.source),
};
};

export const viewFunction = ({ sourceType, cssClass, props: { source } }: IconViewModel) => {
export const viewFunction = ({ sourceType, cssClass, props: { source } }: Icon) => {
return (<Fragment>
{sourceType === 'dxIcon' && <i className={`dx-icon dx-icon-${source} ${cssClass}`}/>}
{sourceType === 'fontIcon' && <i className={`dx-icon ${source} ${cssClass}`}/>}
Expand All @@ -34,14 +20,13 @@ export class IconInput {
@Component({
components: [],
view: viewFunction,
viewModel: viewModelFunction,
})
export default class Icon extends JSXComponent<IconInput> {
// get sourceType() {
// return getImageSourceType(this.props.source);
// }
get sourceType() {
return getImageSourceType(this.props.source);
}

// get cssClass() {
// return this.props.position !== 'left' ? 'dx-icon-right' : '';
// }
get cssClass() {
return this.props.position !== 'left' ? 'dx-icon-right' : '';
}
}
118 changes: 55 additions & 63 deletions js/renovation/widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,72 +73,18 @@ const getCssClasses = (model: Partial<Widget> & Partial<WidgetInput>) => {
return className.join(' ');
};

export const viewModelFunction = ({
_active,
_focused,
_hovered,

props: {
accessKey,
aria,
children,
className,
disabled,
elementAttr,
focusStateEnabled,
height,
hint,
hoverStateEnabled,
rtlEnabled,
tabIndex,
visible,
width,
onContentReady,
onVisibilityChange,
},

widgetRef,
}: Widget) => {
const styles = getStyles({ width, height });
const attrsWithoutClass = getAttributes({
accessKey: focusStateEnabled && !disabled && accessKey,
elementAttr,
});
const arias = getAria({ ...aria, disabled, hidden: !visible });
const cssClasses = getCssClasses({
_active, _focused, _hovered, className,
disabled, elementAttr, focusStateEnabled, hoverStateEnabled,
onVisibilityChange, rtlEnabled, visible,
});

return {
attributes: { ...attrsWithoutClass, ...arias },
children,
cssClasses,
disabled,
focusStateEnabled,
hoverStateEnabled,
onContentReady,
styles,
tabIndex: focusStateEnabled && !disabled && tabIndex,
title: hint,
visible,
widgetRef,
};
};

export const viewFunction = (viewModel: any) => {
export const viewFunction = (viewModel: Widget) => {
return (
<div
ref={viewModel.widgetRef}
ref={viewModel.widgetRef as any}
{...viewModel.attributes}
className={viewModel.cssClasses}
tabIndex={viewModel.tabIndex}
title={viewModel.title}
title={viewModel.props.hint}
style={viewModel.styles}
hidden={!viewModel.visible}
hidden={!viewModel.props.visible}
>
{viewModel.children}
{viewModel.props.children}
</div>
);
};
Expand Down Expand Up @@ -180,7 +126,6 @@ export class WidgetInput {
components: [],
name: 'Widget',
view: viewFunction,
viewModel: viewModelFunction,
})

export default class Widget extends JSXComponent<WidgetInput> {
Expand Down Expand Up @@ -259,9 +204,7 @@ export default class Widget extends JSXComponent<WidgetInput> {

@Effect()
contentReadyEffect() {
const { onContentReady } = this.props;

onContentReady?.({});
this.props.onContentReady?.({});
}

@Effect()
Expand Down Expand Up @@ -351,4 +294,53 @@ export default class Widget extends JSXComponent<WidgetInput> {

return null;
}

get attributes() {
const {
aria,
visible,
focusStateEnabled,
disabled,
accessKey,
elementAttr,
} = this.props;

const attrsWithoutClass = getAttributes({
accessKey: focusStateEnabled && !disabled && accessKey,
elementAttr,
});
const arias = getAria({ ...aria, disabled, hidden: !visible });

return { ...attrsWithoutClass, ...arias };
}

get styles() {
const { width, height } = this.props;
return getStyles({ width, height });
}

get cssClasses() {
const {
className,
disabled,
elementAttr,
focusStateEnabled,
hoverStateEnabled,
onVisibilityChange,
rtlEnabled,
visible,
} = this.props;

return getCssClasses({
_active: this._active, _focused: this._focused, _hovered: this._hovered, className,
disabled, elementAttr, focusStateEnabled, hoverStateEnabled,
onVisibilityChange, rtlEnabled, visible,
});
}

get tabIndex() {
return this.props.focusStateEnabled &&
!this.props.disabled &&
this.props.tabIndex;
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"cldr-numbers-full": "latest",
"cldrjs": "^0.5.0",
"del": "^2.2.2",
"devextreme-generator": "^1.0.30",
"devextreme-generator": "^1.0.32",
"devextreme-internal-tools": "~1.2.24",
"enzyme": "^3.11.0",
"enzyme-adapter-preact-pure": "^2.2.0",
Expand Down

0 comments on commit b53bed5

Please sign in to comment.