Skip to content

Commit 0743440

Browse files
authored
Merge pull request #317 from hansi90/select_option_group
Select field option group.
2 parents 417f14d + fec34f4 commit 0743440

File tree

2 files changed

+112
-26
lines changed

2 files changed

+112
-26
lines changed

src/fields/core/fieldSelect.vue

+71-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
<template lang="pug">
22
select.form-control(v-model="value", :disabled="disabled", :name="schema.inputName", :id="getFieldID(schema)")
33
option(v-if="!selectOptions.hideNoneSelectedText", :disabled="schema.required", :value="null", :selected="value == undefined") {{ selectOptions.noneSelectedText || "&lt;Nothing selected&gt;" }}
4-
option(v-for="item in items", :value="getItemValue(item)") {{ getItemName(item) }}
4+
5+
template(v-for="item in items")
6+
optgroup(v-if="item.group", :label="getGroupName(item)")
7+
option(v-if="item.ops", v-for="i in item.ops", :value="getItemValue(i)") {{ getItemName(i) }}
8+
9+
option(v-if="!item.group", :value="getItemValue(item)") {{ getItemName(item) }}
510
</template>
611

712
<script>
8-
import {isObject} from "lodash";
13+
import {isObject, find} from "lodash";
914
import abstractField from "../abstractField";
1015
1116
export default {
@@ -19,13 +24,74 @@
1924
items() {
2025
let values = this.schema.values;
2126
if (typeof(values) == "function") {
22-
return values.apply(this, [this.model, this.schema]);
27+
return this.groupValues(values.apply(this, [this.model, this.schema]));
2328
} else
24-
return values;
25-
}
29+
return this.groupValues(values);
30+
}
2631
},
2732
2833
methods: {
34+
35+
groupValues(values){
36+
let array = [];
37+
let arrayElement = {};
38+
39+
values.forEach((item) => {
40+
41+
arrayElement = null;
42+
43+
if(item.group && isObject(item)){
44+
// There is in a group.
45+
46+
// Find element with this group.
47+
arrayElement = find(array, i => i.group == item.group);
48+
49+
if(arrayElement){
50+
// There is such a group.
51+
52+
arrayElement.ops.push({
53+
id: item.id,
54+
name: item.name
55+
});
56+
}else{
57+
// There is not such a group.
58+
59+
// Initialising.
60+
arrayElement = {
61+
group:"",
62+
ops:[]
63+
};
64+
65+
// Set group.
66+
arrayElement.group = item.group;
67+
68+
// Set Group element.
69+
arrayElement.ops.push({
70+
id: item.id,
71+
name: item.name
72+
});
73+
74+
// Add array.
75+
array.push(arrayElement);
76+
}
77+
}else{
78+
// There is not in a group.
79+
array.push(item);
80+
}
81+
});
82+
83+
// With Groups.
84+
return array;
85+
},
86+
87+
getGroupName(item){
88+
if(item && item.group){
89+
return item.group;
90+
}
91+
92+
throw "Group name is missing! https://icebob.gitbooks.io/vueformgenerator/content/fields/select.html#select-field-with-object-items";
93+
},
94+
2995
getItemValue(item) {
3096
if (isObject(item)){
3197
if (typeof this.schema["selectOptions"] !== "undefined" && typeof this.schema["selectOptions"]["value"] !== "undefined") {

test/unit/specs/fields/fieldSelect.spec.js

+41-21
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ Vue.component("FieldSelect", FieldSelect);
99
let el, vm, field;
1010

1111
function createField(test, schema = {}, model = null, disabled = false, options) {
12-
[ el, vm, field ] = createVueField(test, "fieldSelect", schema, model, disabled, options);
12+
[el, vm, field] = createVueField(test, "fieldSelect", schema, model, disabled, options);
1313
}
1414

1515

16-
describe("fieldSelect.vue", function() {
16+
describe("fieldSelect.vue", function () {
1717

1818
describe("check template", () => {
1919
let schema = {
@@ -31,7 +31,7 @@ describe("fieldSelect.vue", function() {
3131
let model = { city: "Paris" };
3232
let input;
3333

34-
before( () => {
34+
before(() => {
3535
createField(this, schema, model, false);
3636
input = el.getElementsByTagName("select")[0];
3737
});
@@ -60,7 +60,7 @@ describe("fieldSelect.vue", function() {
6060
});
6161

6262
it("should contain the value", (done) => {
63-
vm.$nextTick( () => {
63+
vm.$nextTick(() => {
6464
expect(input.value).to.be.equal("Paris");
6565
done();
6666
});
@@ -69,16 +69,16 @@ describe("fieldSelect.vue", function() {
6969
describe("check optional attribute", () => {
7070
let attributes = ["disabled", "inputName"];
7171

72-
attributes.forEach(function(name) {
73-
it("should set " + name, function(done) {
72+
attributes.forEach(function (name) {
73+
it("should set " + name, function (done) {
7474
checkAttribute(name, vm, input, field, schema, done);
7575
});
7676
});
7777
});
7878

7979
it("input value should be the model value after changed", (done) => {
8080
model.city = "Rome";
81-
vm.$nextTick( () => {
81+
vm.$nextTick(() => {
8282
expect(input.value).to.be.equal("Rome");
8383
done();
8484
});
@@ -89,7 +89,7 @@ describe("fieldSelect.vue", function() {
8989
input.value = "London";
9090
trigger(input, "change");
9191

92-
vm.$nextTick( () => {
92+
vm.$nextTick(() => {
9393
expect(model.city).to.be.equal("London");
9494
done();
9595
});
@@ -98,7 +98,7 @@ describe("fieldSelect.vue", function() {
9898

9999
it("should contain a disabled <non selected> element if required", (done) => {
100100
schema.required = true;
101-
vm.$nextTick( () => {
101+
vm.$nextTick(() => {
102102
let options = input.querySelectorAll("option");
103103
expect(options[0].disabled).to.be.true;
104104
expect(options[0].textContent).to.be.equal("<Nothing selected>");
@@ -110,7 +110,7 @@ describe("fieldSelect.vue", function() {
110110
Vue.set(vm.schema, "selectOptions", {
111111
noneSelectedText: "Empty list"
112112
});
113-
vm.$nextTick( () => {
113+
vm.$nextTick(() => {
114114
let options = input.querySelectorAll("option");
115115
expect(options[0].disabled).to.be.true;
116116
expect(options[0].textContent).to.be.equal("Empty list");
@@ -126,7 +126,7 @@ describe("fieldSelect.vue", function() {
126126
noneSelectedText: "Empty list",
127127
hideNoneSelectedText: true
128128
});
129-
vm.$nextTick( () => {
129+
vm.$nextTick(() => {
130130
let options = input.querySelectorAll("option");
131131
expect(options[0].disabled).to.be.false;
132132
expect(options[0].textContent).to.not.be.equal("Empty list");
@@ -148,37 +148,57 @@ describe("fieldSelect.vue", function() {
148148
{ id: 1, name: "London" },
149149
{ id: 2, name: "Paris" },
150150
{ id: 3, name: "Rome" },
151-
{ id: 4, name: "Berlin" }
151+
{ id: 4, name: "Berlin" },
152+
{ id: 5, name: "Budapest", group: "HUN" },
153+
{ id: 6, name: "Paks", group: "HUN" },
152154
]
153155
};
154156
let model = { city: 2 };
155157
let input;
156158

157-
before( () => {
159+
before(() => {
158160
createField(this, schema, model, false);
159161
input = el.getElementsByTagName("select")[0];
160162
});
161163

162164
it("should contain option elements", () => {
163165
let options = input.querySelectorAll("option");
164-
expect(options.length).to.be.equal(4 + 1); // +1 for <non selected>
166+
expect(options.length).to.be.equal(6 + 1); // +1 for <non selected>
165167

166168
expect(options[2].value).to.be.equal("2");
167169
expect(options[2].textContent).to.be.equal("Paris");
168170
expect(options[2].selected).to.be.true;
169171
expect(options[1].selected).to.be.false;
170172
});
171173

174+
it("should contain optgroup elements", () => {
175+
let optgroups = input.querySelectorAll("optgroup");
176+
expect(optgroups.length).to.be.equal(1);
177+
expect(optgroups[0].label).to.be.equal("HUN");
178+
});
179+
180+
it("should contain option elements in optgroup", () => {
181+
let og = input.getElementsByTagName("optgroup")[0];
182+
let options = og.querySelectorAll("option");
183+
184+
expect(options.length).to.be.equal(2);
185+
expect(options[0].selected).to.be.false;
186+
expect(options[1].selected).to.be.false;
187+
188+
expect(options[1].textContent).to.be.equal("Paks");
189+
expect(options[1].value).to.be.equal("6");
190+
});
191+
172192
it("should contain the value", (done) => {
173-
vm.$nextTick( () => {
193+
vm.$nextTick(() => {
174194
expect(input.value).to.be.equal("2");
175195
done();
176196
});
177197
});
178198

179199
it("input value should be the model value after changed", (done) => {
180200
model.city = 3;
181-
vm.$nextTick( () => {
201+
vm.$nextTick(() => {
182202
expect(input.value).to.be.equal("3");
183203
done();
184204
});
@@ -189,7 +209,7 @@ describe("fieldSelect.vue", function() {
189209
input.value = "4";
190210
trigger(input, "change");
191211

192-
vm.$nextTick( () => {
212+
vm.$nextTick(() => {
193213
expect(model.city).to.be.equal(4);
194214
done();
195215
});
@@ -215,21 +235,21 @@ describe("fieldSelect.vue", function() {
215235
let model = { city: 2 };
216236
let input;
217237

218-
before( () => {
238+
before(() => {
219239
createField(this, schema, model, false);
220240
input = el.getElementsByTagName("select")[0];
221241
});
222242

223243
it("should contain the value", (done) => {
224-
vm.$nextTick( () => {
244+
vm.$nextTick(() => {
225245
expect(input.value).to.be.equal("2");
226246
done();
227247
});
228248
});
229249

230250
it("input value should be the model value after changed", (done) => {
231251
model.city = 3;
232-
vm.$nextTick( () => {
252+
vm.$nextTick(() => {
233253
expect(input.value).to.be.equal("3");
234254
done();
235255
});
@@ -240,7 +260,7 @@ describe("fieldSelect.vue", function() {
240260
input.value = "4";
241261
trigger(input, "change");
242262

243-
vm.$nextTick( () => {
263+
vm.$nextTick(() => {
244264
expect(model.city).to.be.equal(4);
245265
done();
246266
});

0 commit comments

Comments
 (0)