Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 57f690b

Browse files
committedJun 1, 2016
🚀 breaking: change form layout
change table, tr, td -> fieldset .form-group label, input
1 parent 3184fa4 commit 57f690b

File tree

3 files changed

+164
-191
lines changed

3 files changed

+164
-191
lines changed
 

‎dev/app.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
data-table(:rows="rows", :selected="selected", :select="selectRow")
55

66
.row(v-show="model")
7-
.col-md-6
7+
.col-md-5.col-md-offset-1
88
.buttons.text-center
99
button.btn.btn-default.new(@click="newModel")
1010
i.fa.fa-plus

‎src/formGenerator.vue

Lines changed: 133 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
<template lang="jade">
2-
table(v-if="schema != null")
3-
thead
4-
tbody
5-
tr(v-for="field in fields", v-if="fieldVisible(field)", :class="getFieldRowClasses(field)")
6-
td
7-
span.help(v-if="field.help")
8-
i.fa.fa-question-circle
9-
.helpText {{{field.help}}}
10-
| {{ field.label }}
11-
td
12-
.field-wrap
13-
component(:is="getFieldType(field)", :disabled="fieldDisabled(field)", :model.sync="model", :schema.sync="field")
14-
.buttons(v-if="field.buttons && field.buttons.length > 0")
15-
button.btn.btn-default(v-for="btn in field.buttons", @click="btn.onclick(model, field)", :class="btn.classes") {{ btn.label }}
16-
.hint(v-if="field.hint") {{ field.hint }}
17-
.errors(v-if="field.errors && field.errors.length > 0")
18-
span(v-for="error in field.errors", track-by="$index") {{ error }}
2+
fieldset(v-if="schema != null")
3+
.form-group(v-for="field in fields", v-if="fieldVisible(field)", :class="getFieldRowClasses(field)")
4+
label {{ field.label }}
5+
span.help(v-if="field.help")
6+
i.fa.fa-question-circle
7+
.helpText {{{field.help}}}
8+
.field-wrap
9+
component(:is="getFieldType(field)", :disabled="fieldDisabled(field)", :model.sync="model", :schema.sync="field")
10+
.buttons(v-if="field.buttons && field.buttons.length > 0")
11+
button.btn.btn-default(v-for="btn in field.buttons", @click="btn.onclick(model, field)", :class="btn.classes") {{ btn.label }}
12+
.hint(v-if="field.hint") {{ field.hint }}
13+
.errors(v-if="field.errors && field.errors.length > 0")
14+
span(v-for="error in field.errors", track-by="$index") {{ error }}
1915
</template>
2016

2117
<script>
@@ -102,6 +98,8 @@
10298
baseClasses[field.styleClasses] = true;
10399
}
104100
101+
baseClasses["field-" + field.type] = true;
102+
105103
return baseClasses;
106104
},
107105
@@ -164,175 +162,151 @@
164162
165163
$errorColor: lighten(#F00, 0%);
166164
167-
table {
168-
width: 70%;
169-
min-width: 350px;
170-
margin: auto;
165+
fieldset {
171166
172167
input, select, textarea {
173168
border-radius: 4px;
174169
border: 1px solid #BBB;
175170
padding: 2px 5px;
176171
}
177172
178-
td {
179-
padding: 0.3em 0.4em;
180-
181-
&:nth-child(1) {
182-
text-align: right;
183-
vertical-align: top;
184-
padding: 0.8em 0.5em;
185-
186-
span.help {
187-
margin-right: 0.3em;
188-
position: relative;
189-
190-
.helpText {
191-
background-color: #444;
192-
bottom: 30px;
193-
color: #fff;
194-
display: block;
195-
left: 0px;
196-
//margin-bottom: 15px;
197-
opacity: 0;
198-
padding: 20px;
199-
pointer-events: none;
200-
position: absolute;
201-
text-align: justify;
202-
width: 300px;
203-
//transform: translateY(10%);
204-
transition: all .25s ease-out;
205-
box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.5);
206-
border-radius: 6px;
207-
208-
a {
209-
font-weight: bold;
210-
text-decoration: underline;
211-
}
212-
}
213-
214-
/* This bridges the gap so you can mouse into the tooltip without it disappearing */
215-
.helpText:before {
216-
bottom: -20px;
217-
content: " ";
218-
display: block;
219-
height: 20px;
220-
left: 0;
221-
position: absolute;
222-
width: 100%;
223-
}
224-
225-
/* CSS Triangles - see Trevor's post */
226-
/*.helpText:after {
227-
border-left: solid transparent 10px;
228-
border-right: solid transparent 10px;
229-
border-top: solid #1496bb 10px;
230-
bottom: -10px;
231-
content: " ";
232-
height: 0;
233-
left: 50%;
234-
margin-left: -13px;
235-
position: absolute;
236-
width: 0;
237-
}*/
238-
239-
&:hover .helpText {
240-
opacity: 1;
241-
pointer-events: auto;
242-
transform: translateY(0px);
243-
}
244-
}
245-
} // nth-child(1)
246-
247-
&:nth-child(2) {
248-
249-
> .field-wrap {
250-
display: flex;
251-
252-
.buttons {
253-
white-space: nowrap;
254-
button {
255-
display: inline-block;
256-
margin: 0 2px;
257-
}
258-
}
259-
}
260-
261-
.hint {
262-
font-style: italic;
263-
font-size: 0.8em;
173+
span.help {
174+
margin-left: 0.3em;
175+
position: relative;
176+
177+
.helpText {
178+
background-color: #444;
179+
bottom: 30px;
180+
color: #fff;
181+
display: block;
182+
left: 0px;
183+
//margin-bottom: 15px;
184+
opacity: 0;
185+
padding: 20px;
186+
pointer-events: none;
187+
position: absolute;
188+
text-align: justify;
189+
width: 300px;
190+
//transform: translateY(10%);
191+
transition: all .25s ease-out;
192+
box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.5);
193+
border-radius: 6px;
194+
195+
a {
196+
font-weight: bold;
197+
text-decoration: underline;
264198
}
199+
}
265200
266-
.errors {
267-
201+
/* This bridges the gap so you can mouse into the tooltip without it disappearing */
202+
.helpText:before {
203+
bottom: -20px;
204+
content: " ";
205+
display: block;
206+
height: 20px;
207+
left: 0;
208+
position: absolute;
209+
width: 100%;
210+
}
211+
212+
/* CSS Triangles - see Trevor's post */
213+
/*.helpText:after {
214+
border-left: solid transparent 10px;
215+
border-right: solid transparent 10px;
216+
border-top: solid #1496bb 10px;
217+
bottom: -10px;
218+
content: " ";
219+
height: 0;
220+
left: 50%;
221+
margin-left: -13px;
222+
position: absolute;
223+
width: 0;
224+
}*/
225+
226+
&:hover .helpText {
227+
opacity: 1;
228+
pointer-events: auto;
229+
transform: translateY(0px);
230+
}
231+
} // span.help
232+
233+
> .field-wrap {
234+
display: flex;
235+
236+
.buttons {
237+
white-space: nowrap;
238+
button {
239+
display: inline-block;
240+
margin: 0 2px;
268241
}
242+
}
243+
}
269244
270-
} // nth-child(2)
271-
272-
} // td
273-
274-
tr.featured {
275-
td:nth-child(1) {
276-
font-weight: bold;
277-
}
245+
.hint {
246+
font-style: italic;
247+
font-size: 0.8em;
278248
}
279249
280-
tr.required {
281-
td:nth-child(1):after {
282-
content: "*";
283-
font-weight: normal;
284-
color: Red;
285-
padding-left: 0.1em;
286-
font-size: 0.8em;
287-
position: absolute;
288-
margin-top: -0.4em;
289-
}
290-
}
291250
251+
.form-group {
292252
293-
tr.disabled {
294-
td:nth-child(1) {
295-
color: #666;
296-
font-style: italic;
297-
}
298-
}
253+
label {
254+
font-weight: 400;
255+
}
299256
300-
tr.company {
301-
/* csak teszt */
302-
background-color: #EEE;
257+
&.featured {
258+
label {
259+
font-weight: bold;
260+
}
261+
}
303262
304-
}
263+
&.required {
264+
label:after {
265+
content: "*";
266+
font-weight: normal;
267+
color: Red;
268+
position: absolute;
269+
padding-left: 0.2em;
270+
font-size: 1em;
271+
}
272+
}
305273
306-
tr.error {
274+
&.disabled {
275+
label {
276+
color: #666;
277+
font-style: italic;
278+
}
279+
}
307280
308-
td:nth-child(1) {
309-
//color: $errorColor;
310-
}
281+
&.error {
282+
283+
label {
284+
//color: $errorColor;
285+
}
311286
312-
td:nth-child(2) {
313287
input:not([type="checkbox"]), textarea, select {
314288
border: 1px solid $errorColor;
315289
background-color: rgba($errorColor, 0.15);
316290
}
317-
}
318291
319-
.errors {
320-
color: $errorColor;
321-
font-size: 0.80em;
322-
span {
323-
display: block;
324-
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAiklEQVR4Xt2TMQoCQQxF3xdhu72MpZU3GU/meBFLOztPYrVWsQmEWSaMsIXgK8P8RyYkMjO2sAN+K9gTIAmDAlzoUzE7p4IFytvDCQWJKSStYB2efcAvqZFM0BcstMx5naSDYFzfLhh/4SmRM+6Agw/xIX0tKEDFufeDNRUc4XqLRz3qabVIf3BMHwl6Ktexn3nmAAAAAElFTkSuQmCC');
325-
background-repeat: no-repeat;
326-
padding-left: 17px;
327-
padding-top: 0px;
328-
margin-top: 0.2em;
329-
font-weight: 600;
330-
}
292+
.errors {
293+
color: $errorColor;
294+
font-size: 0.80em;
295+
span {
296+
display: block;
297+
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAiklEQVR4Xt2TMQoCQQxF3xdhu72MpZU3GU/meBFLOztPYrVWsQmEWSaMsIXgK8P8RyYkMjO2sAN+K9gTIAmDAlzoUzE7p4IFytvDCQWJKSStYB2efcAvqZFM0BcstMx5naSDYFzfLhh/4SmRM+6Agw/xIX0tKEDFufeDNRUc4XqLRz3qabVIf3BMHwl6Ktexn3nmAAAAAElFTkSuQmCC');
298+
background-repeat: no-repeat;
299+
padding-left: 17px;
300+
padding-top: 0px;
301+
margin-top: 0.2em;
302+
font-weight: 600;
303+
}
331304
332-
} // .errors
305+
} // .errors
333306
307+
} // .error
334308
335-
} // tr.error
309+
} // .form-group
336310
337-
} // table
311+
} // fieldset
338312
</style>

‎test/unit/specs/VueFormGenerator.spec.js

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,15 @@ describe("VueFormGenerator.vue", () => {
3434
createFormGenerator(schema);
3535
});
3636

37-
it("should be create HTML table", () => {
37+
it("should be create fieldset", () => {
3838
expect(vm.$el).to.be.exist;
39-
expect(el.getElementsByTagName("table")).to.be.length(1);
40-
41-
let table = el.getElementsByTagName("table")[0];
42-
expect(table.getElementsByTagName("tbody")).to.be.length(1);
39+
expect(el.getElementsByTagName("fieldset")).to.be.length(1);
4340
});
4441

4542
});
4643

47-
describe("check form row classes", () => {
48-
let tr;
44+
describe("check form-group classes", () => {
45+
let group;
4946
let schema = {
5047
fields: [
5148
{
@@ -62,74 +59,76 @@ describe("VueFormGenerator.vue", () => {
6259

6360
before( () => {
6461
createFormGenerator(schema);
65-
tr = el.getElementsByTagName("tr")[0];
62+
group = el.querySelector(".form-group");
6663
});
6764

68-
it("should be empty classList", () => {
69-
expect(tr.classList.length).to.be.equal(0);
65+
it("should be minimal classes", () => {
66+
expect(group.classList.length).to.be.equal(2);
67+
expect(group.classList.contains("form-group")).to.be.true;
68+
expect(group.classList.contains("field-text")).to.be.true;
7069
});
7170

7271
it("should be featured class", (done) => {
7372
vm.schema.fields[0].featured = true;
7473
vm.$nextTick(() => {
75-
expect(tr.classList.contains("featured")).to.be.true;
74+
expect(group.classList.contains("featured")).to.be.true;
7675
done();
7776
});
7877
});
7978

8079
it("should be readonly class", (done) => {
8180
vm.schema.fields[0].readonly = true;
8281
vm.$nextTick(() => {
83-
expect(tr.classList.contains("readonly")).to.be.true;
82+
expect(group.classList.contains("readonly")).to.be.true;
8483
done();
8584
});
8685
});
8786

8887
it("should be disabled class", (done) => {
8988
vm.schema.fields[0].disabled = true;
9089
vm.$nextTick(() => {
91-
expect(tr.classList.contains("disabled")).to.be.true;
90+
expect(group.classList.contains("disabled")).to.be.true;
9291
done();
9392
});
9493
});
9594

9695
it("should be required class", (done) => {
9796
vm.schema.fields[0].required = true;
9897
vm.$nextTick(() => {
99-
expect(tr.classList.contains("required")).to.be.true;
98+
expect(group.classList.contains("required")).to.be.true;
10099
done();
101100
});
102101
});
103102

104103
it("should be error class", (done) => {
105104
vm.$set("schema.fields[0].errors", [ "!!!" ]);
106105
vm.$nextTick(() => {
107-
expect(tr.classList.contains("error")).to.be.true;
106+
expect(group.classList.contains("error")).to.be.true;
108107
done();
109108
});
110109
});
111110

112111
it("should be add a custom classes", (done) => {
113112
vm.$set("schema.fields[0].styleClasses", "classA");
114113
vm.$nextTick(() => {
115-
expect(tr.classList.contains("classA")).to.be.true;
114+
expect(group.classList.contains("classA")).to.be.true;
116115
done();
117116
});
118117
});
119118

120119
it("should be add more custom classes", (done) => {
121120
vm.$set("schema.fields[0].styleClasses", [ "classB", "classC" ]);
122121
vm.$nextTick(() => {
123-
expect(tr.classList.contains("classB")).to.be.true;
124-
expect(tr.classList.contains("classC")).to.be.true;
122+
expect(group.classList.contains("classB")).to.be.true;
123+
expect(group.classList.contains("classC")).to.be.true;
125124
done();
126125
});
127126
});
128127

129128
});
130129

131130
describe("check form row caption cell", () => {
132-
let tr, tdCaption;
131+
let group, label;
133132
let schema = {
134133
fields: [
135134
{
@@ -143,19 +142,19 @@ describe("VueFormGenerator.vue", () => {
143142

144143
before( () => {
145144
createFormGenerator(schema);
146-
tr = el.getElementsByTagName("tr")[0];
147-
tdCaption = tr.getElementsByTagName("td")[0];
145+
group = el.querySelector(".form-group");
146+
label = group.querySelector("label");
148147
});
149148

150149
it("should be text of cell is the name of field", () => {
151-
expect(tdCaption).to.be.exist;
152-
expect(tdCaption.textContent).to.be.equal("Name");
150+
expect(label).to.be.exist;
151+
expect(label.textContent).to.be.equal("Name");
153152
});
154153

155154
it("should be a question icon if has helpText", (done) => {
156155
vm.schema.fields[0].help = "Sample help";
157156
vm.$nextTick(() => {
158-
let span = tr.querySelector(".help");
157+
let span = group.querySelector(".help");
159158
expect(span).to.be.exist;
160159
expect(span.querySelector("i")).to.be.exist;
161160
expect(span.querySelector(".helpText")).to.be.exist;
@@ -167,7 +166,7 @@ describe("VueFormGenerator.vue", () => {
167166
});
168167

169168
describe("check form row field cell", () => {
170-
let tr, tdField;
169+
let group, label;
171170
let schema = {
172171
fields: [
173172
{
@@ -183,24 +182,24 @@ describe("VueFormGenerator.vue", () => {
183182

184183
before( () => {
185184
createFormGenerator(schema);
186-
tr = el.getElementsByTagName("tr")[0];
187-
tdField = tr.getElementsByTagName("td")[1];
185+
group = el.querySelector(".form-group");
186+
label = group.querySelector("label");
188187
});
189188

190189
it("should be a .field-wrap div", () => {
191-
expect(tdField.querySelector(".field-wrap")).to.be.exist;
190+
expect(group.querySelector(".field-wrap")).to.be.exist;
192191
});
193192

194193
it("should be a hint div if hint is not null", () => {
195-
let hint = tdField.querySelector(".hint");
194+
let hint = group.querySelector(".hint");
196195
expect(hint).to.be.exist;
197196
expect(hint.textContent).to.be.equal("Hint text");
198197
});
199198

200199
it("should be .errors div if there are errors in fields", (done) => {
201200
vm.schema.fields[0].errors.push("Some error!", "Another error!");
202201
vm.$nextTick(() => {
203-
let div = tdField.querySelector(".errors");
202+
let div = group.querySelector(".errors");
204203
expect(div).to.be.exist;
205204
let errors = div.querySelectorAll("span");
206205
expect(errors.length).to.be.equal(2);
@@ -229,7 +228,7 @@ describe("VueFormGenerator.vue", () => {
229228

230229
it("should render only phone field", () => {
231230
expect(form.fields.length).to.be.equal(1);
232-
expect(el.getElementsByTagName("tr")[0].getElementsByTagName("td")[0].textContent).to.be.equal("phone");
231+
expect(el.querySelector(".form-group label").textContent).to.be.equal("phone");
233232
});
234233
});
235234

0 commit comments

Comments
 (0)
Please sign in to comment.