Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix menu mutli active item #1438

Merged
merged 7 commits into from
Jun 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion components/menu/PropsType.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ export interface MenuProps {
defaultValue?: Array<string>;
value?: Array<string>;
onChange?: Function;
level?: number;
level?: 1 | 2;
height?: number;
}
75 changes: 28 additions & 47 deletions components/menu/SubMenu.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,35 @@ import classNames from 'classnames';
import List from '../list/index.web';
import Radio from '../radio/Radio.web';

export default class SubMenu extends React.Component<any, any> {
constructor(props) {
super(props);
this.state = {
selItem: props.selItem,
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.subMenuData !== this.props.subMenuData) {
this.setState({
selItem: nextProps.selItem,
});
export default function SubMenu(props) {
const onClick = (dataItem) => {
if (props.onSel) {
props.onSel(dataItem);
}
}
onClick = (dataItem) => {
this.setState({
selItem: [dataItem],
});
if (this.props.onSel) {
this.props.onSel(dataItem);
}
}
render() {
const { subMenuPrefixCls, radioPrefixCls, subMenuData } = this.props;
const { selItem } = this.state;
};

const selected = dataItem => selItem.length > 0 && selItem[0].value === dataItem.value;
const { subMenuPrefixCls, radioPrefixCls, subMenuData, showSelect, selItem } = props;
const selected = dataItem => (showSelect && (selItem.length > 0 && selItem[0].value === dataItem.value));

return (
<List style={{ paddingTop: 0 }} className={subMenuPrefixCls}>
{subMenuData.map((dataItem, idx) => (
<List.Item
className={classNames({
[`${radioPrefixCls}-item`]: true,
[`${subMenuPrefixCls}-item-selected`]: selected(dataItem),
[`${subMenuPrefixCls}-item-disabled`]: dataItem.disabled,
})}
key={idx}
extra={<Radio
checked={selected(dataItem)}
disabled={dataItem.disabled}
onChange={() => this.onClick(dataItem)}
/>}
>
{dataItem.label}
</List.Item>
))}
</List>
);
}
return(
<List style={{ paddingTop: 0 }} className={subMenuPrefixCls}>
{subMenuData.map((dataItem, idx) => (
<List.Item
className={classNames({
[`${radioPrefixCls}-item`]: true,
[`${subMenuPrefixCls}-item-selected`]: selected(dataItem),
[`${subMenuPrefixCls}-item-disabled`]: dataItem.disabled,
})}
key={idx}
extra={<Radio
checked={selected(dataItem)}
disabled={dataItem.disabled}
onChange={() => onClick(dataItem)}
/>}
>
{dataItem.label}
</List.Item>
))}
</List>
);
}
10 changes: 5 additions & 5 deletions components/menu/__tests__/__snapshots__/index.test.web.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
exports[`Menu level 1 renders correctly 1`] = `
<div
class="am-menu"
style="height:0px;overflow-y:scroll;"
style="height:0px;"
>
<div
class="am-flexbox am-flexbox-align-top"
Expand All @@ -12,7 +12,7 @@ exports[`Menu level 1 renders correctly 1`] = `
aria-hidden="false"
class="am-flexbox-item"
role="tabpanel"
style="height:0px;overflow-y:scroll;"
style="height:0px;"
>
<div
class="am-list am-sub-menu"
Expand Down Expand Up @@ -103,14 +103,14 @@ exports[`Menu level 1 renders correctly 1`] = `
exports[`Menu renders correctly 1`] = `
<div
class="am-menu"
style="height:0px;overflow-y:scroll;"
style="height:0px;"
>
<div
class="am-flexbox am-flexbox-align-top"
>
<div
class="am-flexbox-item"
style="height:0px;overflow-y:scroll;"
style="height:0px;"
>
<div
class="am-list"
Expand Down Expand Up @@ -164,7 +164,7 @@ exports[`Menu renders correctly 1`] = `
aria-hidden="false"
class="am-flexbox-item"
role="tabpanel"
style="height:0px;overflow-y:scroll;"
style="height:0px;"
>
<div
class="am-list am-sub-menu"
Expand Down
52 changes: 31 additions & 21 deletions components/menu/demo/basic.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,64 +12,71 @@ import { Menu, ActivityIndicator, NavBar } from 'antd-mobile';
const data = [
{
value: '1',
label: 'All Categories',
isLeaf: true,
}, {
value: '2',
label: 'Food',
children: [
{
label: 'All Foods',
value: '22',
value: '1',
disabled: false,
},
{
label: 'Chinese Food',
value: '21',
value: '2',
}, {
label: 'Hot Pot',
value: '23',
value: '3',
}, {
label: 'Buffet',
value: '24',
value: '4',
}, {
label: 'Fast Food',
value: '25',
value: '5',
}, {
label: 'Snack',
value: '26',
value: '6',
}, {
label: 'Bread',
value: '27',
value: '7',
}, {
label: 'Fruit',
value: '28',
value: '8',
}, {
label: 'Noodle',
value: '29',
value: '9',
}, {
label: 'Leisure Food',
value: '210',
value: '10',
}],
}, {
value: '3',
value: '2',
label: 'Supermarket',
children: [
{
label: 'All Supermarkets',
value: '31',
value: '1',
}, {
label: 'Supermarket',
value: '32',
value: '2',
disabled: true,
}, {
label: 'C-Store',
value: '33',
value: '3',
}, {
label: 'Personal Care',
value: '34',
value: '4',
}],
},
{
value: '3',
label: 'Extra',
isLeaf: true,
children: [
{
label: 'you can not see',
value: '1',
},
],
},
];

class MenuExample extends React.Component {
Expand Down Expand Up @@ -117,7 +124,7 @@ class MenuExample extends React.Component {
<Menu
className="foo-menu"
data={initData}
value={['2', '22']}
value={['1', '3']}
onChange={this.onChange}
height={document.documentElement.clientHeight * 0.6}
/>
Expand Down Expand Up @@ -151,9 +158,12 @@ ReactDOM.render(<MenuExample />, mountNode);

```css
.foo-menu {
position: relative;
z-index: 1000 !important;
}
.top-nav-bar {
position: relative;
z-index: 1000 !important;
background-color: #008AE6;
color: #FFF;
}
Expand All @@ -163,10 +173,10 @@ ReactDOM.render(<MenuExample />, mountNode);
.menu-active:after {
content: ' ';
position: absolute;
top: 0;
width: 100%;
height: 100%;
background-color: #000;
opacity: 0.4;
z-index: 1;
}
```
51 changes: 38 additions & 13 deletions components/menu/index.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,56 +21,80 @@ export default class Menu extends React.Component<MenuProps, any> {
super(props);
this.state = {
firstLevelSelectValue: this.getNewFsv(props),
value: props.value,
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.value !== this.props.value) {
this.setState({
firstLevelSelectValue: this.getNewFsv(nextProps),
value: nextProps.value,
});
}
}

getNewFsv(props) {
const { value, data } = props;
return value && value.length ? value[0] : !data[0].isLeaf ? data[0].value : '';
let firstValue = '';
if (value && value.length) { // if has init path, chose init first value
firstValue = value[0];
} else if (!data[0].isLeaf) { // chose the first menu item if it's not leaf.
firstValue = data[0].value;
}

return firstValue;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getNewFsv的写法也改写下吧,这个写法很难阅读。


onClickFirstLevelItem = (dataItem) => {
const { onChange } = this.props;
this.setState({
firstLevelSelectValue: dataItem.value,
});
if (dataItem.isLeaf && this.props.onChange) {
this.props.onChange([dataItem.value]);
if (dataItem.isLeaf && onChange) {
onChange([dataItem.value]);
}
}

onClickSubMenuItem = (dataItem) => {
const { level, onChange } = this.props;
const value = (level === 2) ? [this.state.firstLevelSelectValue, dataItem.value] : [dataItem.value];
this.setState({ value });
setTimeout(() => {
if (onChange) {
onChange(level === 2 ? [this.state.firstLevelSelectValue, dataItem.value] : [dataItem.value]);
onChange(value);
}
}, 300);
}

render() {
const { className, style, height, data = [], prefixCls, value, level } = this.props;
const { firstLevelSelectValue } = this.state;
const { className, style, height, data = [], prefixCls, level } = this.props;
const { firstLevelSelectValue, value } = this.state;
let subMenuData = data; // menu only has one level as init

if (level === 2) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

重新梳理了一下逻辑,加入了isLeaf === true 就不显示children 的判断

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isLeaf的使用场景是干啥?demo里的isLeaf用来显示全部类型?也不太对啊

要问下这个组件最初的开发者

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个跟@pingan1927 沟通过。
isLeaf 表明它是叶子节点,无法展开二级节点,在文档中说,isLeaf的优先级大于children。之前代码中没有这个判断。
demo中叶子节点显示全部类型,是有些令人困惑,我去修正一下demo。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

文档和 demo 有可以完善的地方就直接改掉

let parent = data;
if (firstLevelSelectValue && firstLevelSelectValue !== '') {
parent = data.filter(dataItem => dataItem.value === firstLevelSelectValue);
}

let subMenuData = data[0].children || [];
if (level !== 2) {
subMenuData = data;
} else if (firstLevelSelectValue) {
subMenuData = data.filter(dataItem => dataItem.value === firstLevelSelectValue)[0].children || [];
if (parent[0] && parent[0].children && parent[0].isLeaf !== true ) {
subMenuData = parent[0].children;
} else {
subMenuData = [];
}
}

const subValue = value && value.length && value[value.length - 1];
const subValue = value && (value.length > 0) && value[value.length - 1];
const parentValue = (value && (value.length > 1)) ? value[0] : null;
const subSelInitItem = subMenuData.filter(dataItem => dataItem.value === subValue);

let showSelect = true;
if (level === 2 && parentValue !== firstLevelSelectValue) {
showSelect = false;
}

const heightStyle = {
height: `${Math.round(height || document.documentElement.clientHeight / 2)}px`,
overflowY: 'scroll',
};

return (
Expand Down Expand Up @@ -106,6 +130,7 @@ export default class Menu extends React.Component<MenuProps, any> {
subMenuData={subMenuData}
selItem={subSelInitItem}
onSel={this.onClickSubMenuItem}
showSelect={showSelect}
/>
</Flex.Item>
</Flex>
Expand Down
2 changes: 1 addition & 1 deletion components/menu/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ subtitle: 菜单
----|-----|------|------
| data | 数据(isLeaf 设置后 children 无效) | `Array<{label, value, disabled?, children<data>?, isLeaf?}>` | [] |
| level | 菜单级数,可选1/2 | number | 2 |
| value | 初始值,一级和二级筛选数据的`value`组成的数组 | Array | [] |
| value | 初始值,一级和二级筛选数据的`value`组成的数组 | Array | |
| onChange | 选择后的回调函数 | (item: Object): void | |
| height | 筛选组件的高度 | number | `document.documentElement.clientHeight / 2` |
5 changes: 5 additions & 0 deletions components/menu/style/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
.@{flexPrefixCls}-item {
margin-left: 0;
-webkit-overflow-scrolling: touch;
overflow-y: scroll;

.@{listPrefixCls} {
padding: 0;
Expand Down Expand Up @@ -97,6 +98,10 @@
&:only-child {
.@{listPrefixCls} {
.@{listPrefixCls}-item {
.@{listPrefixCls}-line {
.hairline-bottom(@border-color-base);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

单级情况下,每个ListItem的下边框缺失

}

&:last-child {
.hairline-bottom(@border-color-base);

Expand Down