Browse Source
* Extract SelectionRadio, SelectionCheckbox, SelectionCheckboxAll * Add some testspull/3804/merge
Wei Zhu
8 years ago
committed by
偏右
6 changed files with 474 additions and 111 deletions
@ -0,0 +1,81 @@ |
|||
import React from 'react'; |
|||
import Checkbox from '../checkbox'; |
|||
import Radio from '../radio'; |
|||
import { Store } from './createStore'; |
|||
|
|||
export interface SelectionBoxProps { |
|||
store: Store; |
|||
type: string; |
|||
defaultSelection: string[]; |
|||
rowIndex: string; |
|||
disabled?: boolean; |
|||
onChange: (e) => void; |
|||
} |
|||
|
|||
export default class SelectionBox extends React.Component<SelectionBoxProps, any> { |
|||
unsubscribe: () => void; |
|||
|
|||
constructor(props) { |
|||
super(props); |
|||
|
|||
this.state = { |
|||
checked: this.getCheckState(props), |
|||
}; |
|||
} |
|||
|
|||
componentDidMount() { |
|||
this.subscribe(); |
|||
} |
|||
|
|||
componentWillUnmount() { |
|||
if (this.unsubscribe) { |
|||
this.unsubscribe(); |
|||
} |
|||
} |
|||
|
|||
subscribe() { |
|||
const { store } = this.props; |
|||
this.unsubscribe = store.subscribe(() => { |
|||
const checked = this.getCheckState(this.props); |
|||
if (checked !== this.state.checked) { |
|||
this.setState({ checked }); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
getCheckState(props) { |
|||
const { store, defaultSelection, rowIndex } = props; |
|||
let checked = false; |
|||
if (store.getState().selectionDirty) { |
|||
checked = store.getState().selectedRowKeys.indexOf(rowIndex) >= 0; |
|||
} else { |
|||
checked = (store.getState().selectedRowKeys.indexOf(rowIndex) >= 0 || |
|||
defaultSelection.indexOf(rowIndex) >= 0); |
|||
} |
|||
return checked; |
|||
} |
|||
|
|||
render() { |
|||
const { type, rowIndex, disabled, onChange } = this.props; |
|||
const { checked } = this.state; |
|||
|
|||
if (type === 'radio') { |
|||
return ( |
|||
<Radio |
|||
disabled={disabled} |
|||
onChange={onChange} |
|||
value={rowIndex} |
|||
checked={checked} |
|||
/> |
|||
); |
|||
} |
|||
|
|||
return ( |
|||
<Checkbox |
|||
checked={checked} |
|||
disabled={disabled} |
|||
onChange={onChange} |
|||
/> |
|||
); |
|||
} |
|||
} |
@ -0,0 +1,114 @@ |
|||
import React from 'react'; |
|||
import Checkbox from '../checkbox'; |
|||
import { Store } from './createStore'; |
|||
|
|||
export interface SelectionCheckboxAllProps { |
|||
store: Store; |
|||
disabled: boolean; |
|||
getCheckboxPropsByItem: (item) => any; |
|||
getRecordKey: (record, index?) => string; |
|||
data: any[]; |
|||
onChange: (e) => void; |
|||
} |
|||
|
|||
export default class SelectionCheckboxAll extends React.Component<SelectionCheckboxAllProps, any> { |
|||
unsubscribe: () => void; |
|||
|
|||
constructor(props) { |
|||
super(props); |
|||
|
|||
this.state = { |
|||
checked: this.getCheckState(), |
|||
indeterminate: this.getIndeterminateState(), |
|||
}; |
|||
} |
|||
|
|||
componentDidMount() { |
|||
this.subscribe(); |
|||
} |
|||
|
|||
componentWillUnmount() { |
|||
if (this.unsubscribe) { |
|||
this.unsubscribe(); |
|||
} |
|||
} |
|||
|
|||
subscribe() { |
|||
const { store } = this.props; |
|||
this.unsubscribe = store.subscribe(() => { |
|||
const checked = this.getCheckState(); |
|||
const indeterminate = this.getIndeterminateState(); |
|||
if (checked !== this.state.checked) { |
|||
this.setState({ checked }); |
|||
} |
|||
if (indeterminate !== this.state.indeterminate) { |
|||
this.setState({ indeterminate }); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
checkSelection(data, type, byDefaultChecked) { |
|||
const { store, getCheckboxPropsByItem, getRecordKey } = this.props; |
|||
// type should be 'every' | 'some'
|
|||
if (type === 'every' || type === 'some') { |
|||
return ( |
|||
byDefaultChecked |
|||
? data[type](item => getCheckboxPropsByItem(item).defaultChecked) |
|||
: data[type]((item, i) => |
|||
store.getState().selectedRowKeys.indexOf(getRecordKey(item, i)) >= 0) |
|||
); |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
getCheckState() { |
|||
const { store, data } = this.props; |
|||
let checked; |
|||
if (!data.length) { |
|||
checked = false; |
|||
} else { |
|||
checked = store.getState().selectionDirty |
|||
? this.checkSelection(data, 'every', false) |
|||
: ( |
|||
this.checkSelection(data, 'every', false) || |
|||
this.checkSelection(data, 'every', true) |
|||
); |
|||
|
|||
} |
|||
return checked; |
|||
} |
|||
|
|||
getIndeterminateState() { |
|||
const { store, data } = this.props; |
|||
let indeterminate; |
|||
if (!data.length) { |
|||
indeterminate = false; |
|||
} else { |
|||
indeterminate = store.getState().selectionDirty |
|||
? ( |
|||
this.checkSelection(data, 'some', false) && |
|||
!this.checkSelection(data, 'every', false) |
|||
) |
|||
: ((this.checkSelection(data, 'some', false) && |
|||
!this.checkSelection(data, 'every', false)) || |
|||
(this.checkSelection(data, 'some', true) && |
|||
!this.checkSelection(data, 'every', true)) |
|||
); |
|||
} |
|||
return indeterminate; |
|||
} |
|||
|
|||
render() { |
|||
const { disabled, onChange } = this.props; |
|||
const { checked, indeterminate } = this.state; |
|||
|
|||
return ( |
|||
<Checkbox |
|||
checked={checked} |
|||
indeterminate={indeterminate} |
|||
disabled={disabled} |
|||
onChange={onChange} |
|||
/> |
|||
); |
|||
} |
|||
} |
@ -0,0 +1,38 @@ |
|||
import assign from 'object-assign'; |
|||
|
|||
export interface Store { |
|||
setState: (Object) => void; |
|||
getState: () => any; |
|||
subscribe: (listener: () => void) => () => void; |
|||
} |
|||
|
|||
export default function createStore(initialState): Store { |
|||
let state = initialState; |
|||
const listeners: any[] = []; |
|||
|
|||
function setState(partial) { |
|||
state = assign({}, state, partial); |
|||
for (let i = 0; i < listeners.length; i++) { |
|||
listeners[i](); |
|||
} |
|||
} |
|||
|
|||
function getState() { |
|||
return state; |
|||
} |
|||
|
|||
function subscribe(listener) { |
|||
listeners.push(listener); |
|||
|
|||
return function unsubscribe() { |
|||
const index = listeners.indexOf(listener); |
|||
listeners.splice(index, 1); |
|||
}; |
|||
} |
|||
|
|||
return { |
|||
setState, |
|||
getState, |
|||
subscribe, |
|||
}; |
|||
} |
@ -0,0 +1,87 @@ |
|||
import React from 'react'; |
|||
import createStore from '../../components/table/createStore'; |
|||
import SelectionBox from '../../components/table/SelectionBox'; |
|||
import TestUtils from 'react-addons-test-utils'; |
|||
|
|||
describe('SelectionBox', () => { |
|||
it('unchecked by selectedRowKeys ', () => { |
|||
const store = createStore({ |
|||
selectedRowKeys: [], |
|||
selectionDirty: false, |
|||
}); |
|||
|
|||
const instance = TestUtils.renderIntoDocument( |
|||
<SelectionBox |
|||
store={store} |
|||
rowIndex="1" |
|||
disabled={false} |
|||
onChange={() => {}} |
|||
defaultSelection={[]} |
|||
/> |
|||
); |
|||
|
|||
expect(instance.state).toEqual({ checked: false }); |
|||
}); |
|||
|
|||
it('checked by selectedRowKeys ', () => { |
|||
const store = createStore({ |
|||
selectedRowKeys: ['1'], |
|||
selectionDirty: false, |
|||
}); |
|||
|
|||
const instance = TestUtils.renderIntoDocument( |
|||
<SelectionBox |
|||
store={store} |
|||
rowIndex="1" |
|||
disabled={false} |
|||
onChange={() => {}} |
|||
defaultSelection={[]} |
|||
/> |
|||
); |
|||
|
|||
expect(instance.state).toEqual({ checked: true }); |
|||
}); |
|||
|
|||
it('checked by defaultSelection', () => { |
|||
const store = createStore({ |
|||
selectedRowKeys: [], |
|||
selectionDirty: false, |
|||
}); |
|||
|
|||
const instance = TestUtils.renderIntoDocument( |
|||
<SelectionBox |
|||
store={store} |
|||
rowIndex="1" |
|||
disabled={false} |
|||
onChange={() => {}} |
|||
defaultSelection={['1']} |
|||
/> |
|||
); |
|||
|
|||
expect(instance.state).toEqual({ checked: true }); |
|||
}); |
|||
|
|||
it('checked when store change', () => { |
|||
const store = createStore({ |
|||
selectedRowKeys: [], |
|||
selectionDirty: false, |
|||
}); |
|||
|
|||
const instance = TestUtils.renderIntoDocument( |
|||
<SelectionBox |
|||
store={store} |
|||
rowIndex="1" |
|||
disabled={false} |
|||
onChange={() => {}} |
|||
defaultSelection={[]} |
|||
/> |
|||
); |
|||
|
|||
store.setState({ |
|||
selectedRowKeys: ['1'], |
|||
selectionDirty: true, |
|||
}); |
|||
|
|||
expect(instance.state).toEqual({ checked: true }); |
|||
}); |
|||
}) |
@ -0,0 +1,91 @@ |
|||
import React from 'react'; |
|||
import createStore from '../../components/table/createStore'; |
|||
import Table from '../../components/table'; |
|||
import TestUtils from 'react-addons-test-utils'; |
|||
|
|||
describe('Table', () => { |
|||
describe('row selection', () => { |
|||
it('allow select by checkbox', () => { |
|||
const columns = [{ |
|||
title: 'Name', |
|||
dataIndex: 'name', |
|||
}]; |
|||
|
|||
const data = [{ |
|||
name: 'Jack', |
|||
}, { |
|||
name: 'Lucy', |
|||
}]; |
|||
|
|||
const instance = TestUtils.renderIntoDocument( |
|||
<Table |
|||
columns={columns} |
|||
dataSource={data} |
|||
rowSelection={{}} |
|||
/> |
|||
); |
|||
|
|||
const checkboxes = TestUtils.scryRenderedDOMComponentsWithTag(instance, 'input'); |
|||
const checkboxAll = checkboxes[0]; |
|||
|
|||
checkboxAll.checked = true; |
|||
TestUtils.Simulate.change(checkboxAll); |
|||
|
|||
expect(instance.store.getState()).toEqual({ |
|||
selectedRowKeys: [0, 1], |
|||
selectionDirty: true, |
|||
}); |
|||
|
|||
checkboxes[1].checked = false; |
|||
TestUtils.Simulate.change(checkboxes[1]); |
|||
|
|||
expect(instance.store.getState()).toEqual({ |
|||
selectedRowKeys: [1], |
|||
selectionDirty: true, |
|||
}); |
|||
|
|||
checkboxes[1].checked = true; |
|||
TestUtils.Simulate.change(checkboxes[1]); |
|||
|
|||
expect(instance.store.getState()).toEqual({ |
|||
selectedRowKeys: [1, 0], |
|||
selectionDirty: true, |
|||
}); |
|||
}); |
|||
|
|||
it('pass getCheckboxProps to checkbox', () => { |
|||
const columns = [{ |
|||
title: 'Name', |
|||
dataIndex: 'name', |
|||
}]; |
|||
|
|||
const data = [{ |
|||
id: 0, |
|||
name: 'Jack', |
|||
}, { |
|||
id: 1, |
|||
name: 'Lucy', |
|||
}]; |
|||
|
|||
const rowSelection = { |
|||
getCheckboxProps: record => ({ |
|||
disabled: record.name === 'Lucy', |
|||
}), |
|||
}; |
|||
|
|||
const instance = TestUtils.renderIntoDocument( |
|||
<Table |
|||
columns={columns} |
|||
dataSource={data} |
|||
rowSelection={rowSelection} |
|||
rowKey="id" |
|||
/> |
|||
); |
|||
|
|||
const checkboxes = TestUtils.scryRenderedDOMComponentsWithTag(instance, 'input'); |
|||
|
|||
expect(checkboxes[1].disabled).toBe(false); |
|||
expect(checkboxes[2].disabled).toBe(true); |
|||
}); |
|||
}); |
|||
}) |
Loading…
Reference in new issue