Skip to content

Commit

Permalink
Select: add value-key
Browse files Browse the repository at this point in the history
  • Loading branch information
Leopoldthecoder committed Jul 18, 2017
1 parent 84c81ff commit 39e3f4c
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 27 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ examples/pages/zh-CN
fe.element/element-ui
.npmrc
coverage
waiter.config.js
5 changes: 5 additions & 0 deletions examples/docs/en-US/select.md
Original file line number Diff line number Diff line change
Expand Up @@ -637,11 +637,16 @@ Create and select new items that are not included in select options
```
:::

:::tip
If the binding value of Select is an object, make sure to assign `value-key` as its unique identity key name.
:::

### Select Attributes
| Attribute | Description | Type | Accepted Values | Default |
|---------- |-------------- |---------- |-------------------------------- |-------- |
| multiple | whether multiple-select is activated | boolean || false |
| disabled | whether Select is disabled | boolean || false |
| value-key | unique identity key name for value, required when value is an object | string || value |
| size | size of Input | string | large/small/mini ||
| clearable | whether single select can be cleared | boolean || false |
| multiple-limit | maximum number of options user can select when `multiple` is `true`. No limit when set to 0 | number || 0 |
Expand Down
5 changes: 5 additions & 0 deletions examples/docs/zh-CN/select.md
Original file line number Diff line number Diff line change
Expand Up @@ -632,11 +632,16 @@
```
:::

:::tip
如果 Select 的绑定值为对象类型,请务必指定 `value-key` 作为它的唯一性标识。
:::

### Select Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---------- |-------------- |---------- |-------------------------------- |-------- |
| multiple | 是否多选 | boolean || false |
| disabled | 是否禁用 | boolean || false |
| value-key | 作为 value 唯一标识的键名,绑定值为对象类型时必填 | string || value |
| size | 输入框尺寸 | string | large/small/mini ||
| clearable | 单选时是否可以清空选项 | boolean || false |
| multiple-limit | 多选时用户最多可以选择的项目数,为 0 则不限制 | number || 0 |
Expand Down
32 changes: 29 additions & 3 deletions packages/select/src/option.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

<script type="text/babel">
import Emitter from 'element-ui/src/mixins/emitter';
import { getValueByPath } from 'element-ui/src/utils/util';
export default {
mixins: [Emitter],
Expand Down Expand Up @@ -47,8 +48,13 @@
},
computed: {
isObject() {
const type = typeof this.value;
return type !== 'string' && type !== 'number';
},
currentLabel() {
return this.label || ((typeof this.value === 'string' || typeof this.value === 'number') ? this.value : '');
return this.label || (this.isObject ? '' : this.value);
},
currentValue() {
Expand All @@ -65,9 +71,9 @@
itemSelected() {
if (!this.parent.multiple) {
return this.value === this.parent.value;
return this.isEqual(this.value, this.parent.value);
} else {
return this.parent.value.indexOf(this.value) > -1;
return this.contains(this.parent.value, this.value);
}
},
Expand All @@ -92,6 +98,26 @@
},
methods: {
isEqual(a, b) {
if (!this.isObject) {
return a === b;
} else {
const valueKey = this.parent.valueKey;
return getValueByPath(a, valueKey) === getValueByPath(b, valueKey);
}
},
contains(arr = [], target) {
if (!this.isObject) {
return arr.indexOf(target) > -1;
} else {
const valueKey = this.parent.valueKey;
return arr.some(item => {
return getValueByPath(item, valueKey) === getValueByPath(target, valueKey);
});
}
},
handleGroupDisabled(val) {
this.groupDisabled = val;
},
Expand Down
49 changes: 44 additions & 5 deletions packages/select/src/select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<transition-group @after-leave="resetInputHeight">
<el-tag
v-for="item in selected"
:key="item.value"
:key="getValueKey(item)"
closable
:hit="item.hitState"
type="primary"
Expand Down Expand Up @@ -103,6 +103,8 @@
import { addClass, removeClass, hasClass } from 'element-ui/src/utils/dom';
import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event';
import { t } from 'element-ui/src/locale';
import { getValueByPath } from 'element-ui/src/utils/util';
const sizeMap = {
'large': 42,
'small': 30,
Expand Down Expand Up @@ -192,7 +194,11 @@
return t('el.select.placeholder');
}
},
defaultFirstOption: Boolean
defaultFirstOption: Boolean,
valueKey: {
type: String,
default: 'value'
}
},
data() {
Expand Down Expand Up @@ -380,15 +386,20 @@
getOption(value) {
let option;
const type = typeof value;
const isObject = type !== 'string' && type !== 'number';
for (let i = this.cachedOptions.length - 1; i >= 0; i--) {
const cachedOption = this.cachedOptions[i];
if (cachedOption.value === value) {
const isEqual = isObject
? getValueByPath(cachedOption.value, this.valueKey) === getValueByPath(value, this.valueKey)
: cachedOption.value === value;
if (isEqual) {
option = cachedOption;
break;
}
}
if (option) return option;
const label = typeof value === 'string' || typeof value === 'number'
const label = !isObject
? value : '';
let newOption = {
value: value,
Expand Down Expand Up @@ -518,7 +529,7 @@
handleOptionSelect(option) {
if (this.multiple) {
const value = this.value.slice();
const optionIndex = value.indexOf(option.value);
const optionIndex = this.getValueIndex(value, option.value);
if (optionIndex > -1) {
value.splice(optionIndex, 1);
} else if (this.multipleLimit <= 0 || value.length < this.multipleLimit) {
Expand All @@ -536,6 +547,25 @@
}
},
getValueIndex(arr = [], value) {
const type = typeof value;
const isObject = type !== 'string' && type !== 'number';
if (!isObject) {
return arr.indexOf(value);
} else {
const valueKey = this.valueKey;
let index = -1;
arr.some((item, i) => {
if (getValueByPath(item, valueKey) === getValueByPath(value, valueKey)) {
index = i;
return true;
}
return false;
});
return index;
}
},
toggleMenu() {
if (this.filterable && this.query === '' && this.visible) {
return;
Expand Down Expand Up @@ -660,6 +690,15 @@
}
}
}
},
getValueKey(item) {
const type = typeof item.value;
if (type === 'number' || type === 'string') {
return item.value;
} else {
return getValueByPath(item.value, this.valueKey);
}
}
},
Expand Down
2 changes: 1 addition & 1 deletion packages/table/src/table-column.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import ElCheckbox from 'element-ui/packages/checkbox';
import ElTag from 'element-ui/packages/tag';
import objectAssign from 'element-ui/src/utils/merge';
import { getValueByPath } from './util';
import { getValueByPath } from 'element-ui/src/utils/util';

let columnIdSeed = 1;

Expand Down
20 changes: 2 additions & 18 deletions packages/table/src/util.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { getValueByPath } from 'element-ui/src/utils/util';

export const getCell = function(event) {
let cell = event.target;

Expand All @@ -11,24 +13,6 @@ export const getCell = function(event) {
return null;
};

export const getValueByPath = function(object, prop) {
prop = prop || '';
const paths = prop.split('.');
let current = object;
let result = null;
for (let i = 0, j = paths.length; i < j; i++) {
const path = paths[i];
if (!current) break;

if (i === j - 1) {
result = current[path];
break;
}
current = current[path];
}
return result;
};

const isObject = function(obj) {
return obj !== null && typeof obj === 'object';
};
Expand Down
18 changes: 18 additions & 0 deletions src/utils/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,21 @@ export function toObject(arr) {
}
return res;
};

export const getValueByPath = function(object, prop) {
prop = prop || '';
const paths = prop.split('.');
let current = object;
let result = null;
for (let i = 0, j = paths.length; i < j; i++) {
const path = paths[i];
if (!current) break;

if (i === j - 1) {
result = current[path];
break;
}
current = current[path];
}
return result;
};

0 comments on commit 39e3f4c

Please sign in to comment.