Skip to content

Commit bd93ab0

Browse files
authored
Merge pull request #493 from matestack/20201221_reworked_form_components_for_extendability
Reworked form components for better extendability
2 parents 878f454 + c4fbaf4 commit bd93ab0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+5774
-1539
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ dynamic Web-App.
2929

3030
Documentation can be found [here](https://docs.matestack.io)
3131

32+
## Getting started
33+
34+
A getting started guide can be found [here](https://docs.matestack.io/docs/start/150-getting_started)
35+
3236
## Changelog
3337

3438
Changelog can be found [here](./CHANGELOG.md)
@@ -342,7 +346,7 @@ class Components::Card < Matestack::Ui::Component
342346
heading size: 5, text: title if title.present?
343347
end
344348
end
345-
349+
346350
def body_slot
347351
slot do
348352
paragraph class: "card-text", text: body
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
require_relative '../utils'
2+
require_relative '../has_errors'
3+
module Matestack::Ui::Core::Form::Checkbox
4+
class Base < Matestack::Ui::Core::Component::Dynamic
5+
include Matestack::Ui::Core::Form::Utils
6+
include Matestack::Ui::Core::Form::HasInputHtmlAttributes
7+
include Matestack::Ui::Core::Form::HasErrors
8+
9+
requires :key
10+
optional :value, :false_value, :multiple, :init, for: { as: :input_for }, label: { as: :input_label }, options: { as: :checkbox_options }
11+
12+
def component_id
13+
"checkbox-component-for-#{attr_key}"
14+
end
15+
16+
def input_key
17+
"$parent.data[\"#{key}\"]"
18+
end
19+
20+
def error_key
21+
"$parent.errors[\"#{key}\"]"
22+
end
23+
24+
def change_event
25+
"inputChanged('#{attr_key}')"
26+
end
27+
28+
def render_options
29+
# multiple
30+
if checkbox_options
31+
checkbox_options.to_a.each do |item|
32+
input html_attributes.merge(
33+
attributes: vue_attributes,
34+
type: :checkbox,
35+
id: "#{id_for_item(item_value(item))}",
36+
name: item_name(item),
37+
value: item_value(item)
38+
)
39+
label text: item_name(item), for: id_for_item(item_value(item))
40+
end
41+
# checked/unchecked checkbox (true/false checkbox)
42+
else
43+
input html_attributes.merge(
44+
attributes: vue_attributes_for_single_input,
45+
type: :hidden,
46+
id: id_for_item(value),
47+
value: (false_value || 0)
48+
)
49+
50+
input html_attributes.merge(
51+
attributes: vue_attributes_for_single_input,
52+
type: :checkbox,
53+
id: id_for_item(value),
54+
value: checked_value
55+
)
56+
57+
label text: input_label, for: id_for_item(value)
58+
end
59+
end
60+
61+
def vue_attributes
62+
(options[:attributes] || {}).merge({
63+
"@change": change_event,
64+
ref: "select.multiple.#{attr_key}",
65+
'init-value': init_value,
66+
'v-bind:class': "{ '#{input_error_class}': #{error_key} }",
67+
'value-type': value_type,
68+
"#{v_model_type}": input_key,
69+
})
70+
end
71+
72+
def vue_attributes_for_single_input
73+
(options[:attributes] || {}).merge({
74+
"@change": change_event,
75+
ref: "input.#{attr_key}",
76+
'init-value': init_value_for_single_input,
77+
'v-bind:class': "{ '#{input_error_class}': #{error_key} }",
78+
"#{v_model_type}": input_key
79+
})
80+
end
81+
82+
def init_value_for_single_input
83+
if init_value == true || init_value == 1
84+
return "true"
85+
end
86+
if init_value == false || init_value == 0
87+
return "false"
88+
end
89+
end
90+
91+
def value_type
92+
item_value(checkbox_options.first).is_a?(Integer) ? Integer : nil
93+
end
94+
95+
def item_value(item)
96+
item.is_a?(Array) ? item.last : item
97+
end
98+
99+
def item_name(item)
100+
item.is_a?(Array) ? item.first : item
101+
end
102+
103+
def checked_value
104+
value || 1
105+
end
106+
107+
def v_model_type
108+
if checkbox_options && checkbox_options.first.is_a?(Integer)
109+
'v-model.number'
110+
else
111+
'v-model'
112+
end
113+
end
114+
115+
def id_for_item(value)
116+
"#{html_attributes[:id]}_#{value}"
117+
end
118+
119+
end
120+
end
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import Vue from "vue/dist/vue.esm";
2+
3+
import formCheckboxMixin from "./mixin";
4+
import componentMixin from "../../component/component";
5+
6+
const componentDef = {
7+
mixins: [componentMixin, formCheckboxMixin],
8+
data() {
9+
return {};
10+
}
11+
}
12+
13+
let component = Vue.component("matestack-ui-core-form-checkbox", componentDef);
14+
15+
export default componentDef;
Lines changed: 7 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,16 @@
1-
require_relative '../utils'
2-
require_relative '../has_input_html_attributes'
3-
require_relative '../has_errors'
1+
require_relative './base'
2+
43
module Matestack::Ui::Core::Form::Checkbox
5-
class Checkbox < Matestack::Ui::Core::Component::Static
6-
include Matestack::Ui::Core::Form::Utils
7-
include Matestack::Ui::Core::Form::HasInputHtmlAttributes
8-
include Matestack::Ui::Core::Form::HasErrors
4+
class Checkbox < Base
95

10-
requires :key
11-
optional :value, :false_value, :multiple, :init, for: { as: :input_for }, label: { as: :input_label }, options: { as: :checkbox_options }
6+
vue_js_component_name "matestack-ui-core-form-checkbox"
127

138
def response
14-
# multiple values
15-
if checkbox_options
16-
checkbox_options.to_a.each do |item|
17-
input html_attributes.merge(
18-
attributes: vue_attributes,
19-
type: :checkbox,
20-
id: "#{id_for_item(item_value(item))}",
21-
name: item_name(item),
22-
value: item_value(item)
23-
)
24-
label text: item_name(item), for: id_for_item(item_value(item))
25-
end
26-
# checked/unchecked checkbox
27-
else
28-
form_input type: :hidden, key: key, value: (false_value || 0), errors: false
29-
form_input type: :checkbox, key: key, value: checked_value, id: id_for_item(value), errors: false
30-
label text: input_label, for: id_for_item(value)
31-
end
32-
render_errors
33-
end
34-
35-
def vue_attributes
36-
(options[:attributes] || {}).merge({
37-
"@change": change_event,
38-
ref: "select.multiple.#{attr_key}",
39-
'init-value': init_value,
40-
'v-bind:class': "{ '#{input_error_class}': #{error_key} }",
41-
'value-type': value_type,
42-
"#{v_model_type}": input_key,
43-
})
44-
end
45-
46-
def value_type
47-
item_value(checkbox_options.first).is_a?(Integer) ? Integer : nil
48-
end
49-
50-
def item_value(item)
51-
item.is_a?(Array) ? item.last : item
52-
end
53-
54-
def item_name(item)
55-
item.is_a?(Array) ? item.first : item
56-
end
57-
58-
def checked_value
59-
value || 1
60-
end
61-
62-
def v_model_type
63-
if checkbox_options && checkbox_options.first.is_a?(Integer)
64-
'v-model.number'
65-
else
66-
'v-model'
9+
div class: "matestack-ui-core-form-checkbox" do
10+
render_options
11+
render_errors
6712
end
6813
end
6914

70-
def change_event
71-
"inputChanged('#{attr_key}')"
72-
end
73-
74-
def id_for_item(value)
75-
"#{html_attributes[:id]}_#{value}"
76-
end
77-
7815
end
7916
end
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
const formCheckboxMixin = {
2+
methods: {
3+
initialize: function(){
4+
const self = this
5+
let data = {};
6+
7+
for (let key in self.$refs) {
8+
let initValue = self.$refs[key]["attributes"]["init-value"];
9+
let valueType = self.$refs[key]["attributes"]["value-type"];
10+
11+
if (key.startsWith("select.")) {
12+
if (key.startsWith("select.multiple.")) {
13+
if (initValue) {
14+
data[key.replace("select.multiple.", "")] = JSON.parse(initValue["value"]);
15+
Object.assign(self.$parent.data, data);
16+
self.afterInitialize(JSON.parse(initValue["value"]))
17+
} else {
18+
data[key.replace("select.multiple.", "")] = [];
19+
Object.assign(self.$parent.data, data);
20+
self.afterInitialize([])
21+
}
22+
} else {
23+
if (initValue) {
24+
if (valueType && valueType["value"] == "Integer") {
25+
data[key.replace("select.", "")] = parseInt(initValue["value"]);
26+
Object.assign(self.$parent.data, data);
27+
self.afterInitialize(parseInt(initValue["value"]))
28+
} else {
29+
30+
data[key.replace("select.", "")] = initValue["value"];
31+
Object.assign(self.$parent.data, data);
32+
self.afterInitialize(initValue["value"])
33+
}
34+
} else {
35+
data[key.replace("select.", "")] = null;
36+
Object.assign(self.$parent.data, data);
37+
self.afterInitialize(null)
38+
}
39+
}
40+
} else {
41+
if (initValue) {
42+
if(initValue["value"] === "true"){
43+
data[key.replace("input.", "")] = true;
44+
Object.assign(self.$parent.data, data);
45+
self.afterInitialize(true)
46+
}
47+
if(initValue["value"] === "false"){
48+
data[key.replace("input.", "")] = false;
49+
Object.assign(self.$parent.data, data);
50+
self.afterInitialize(false)
51+
}
52+
} else {
53+
data[key.replace("input.", "")] = null;
54+
Object.assign(self.$parent.data, data);
55+
self.afterInitialize(null)
56+
}
57+
}
58+
}
59+
60+
//without the timeout it's somehow not working
61+
setTimeout(function () {
62+
self.$forceUpdate()
63+
}, 1);
64+
},
65+
inputChanged: function (key) {
66+
this.$parent.resetErrors(key);
67+
this.$forceUpdate();
68+
},
69+
afterInitialize: function(value){
70+
// can be used in the main component for further initialization steps
71+
},
72+
setValue: function (value){
73+
this.$parent.data[this.componentConfig["key"]] = value
74+
this.$forceUpdate();
75+
}
76+
}
77+
78+
}
79+
80+
export default formCheckboxMixin

0 commit comments

Comments
 (0)