Skip to content

Commit 8c117fe

Browse files
authored
Merge pull request #496 from matestack/next_release
1.3.0 Release
2 parents 4b464da + efcc5be commit 8c117fe

Some content is hidden

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

72 files changed

+5649
-1510
lines changed

CHANGELOG.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,43 @@
11
# Changelog
22

3+
## v1.3.0 Release
4+
5+
### Potential breaking change
6+
7+
If you have used a `form_submit` component like this:
8+
9+
```ruby
10+
form_submit do
11+
button text: "Submit me!", attributes: { "v-bind:disabled": "loading" }
12+
end
13+
```
14+
15+
in order to disable the the button during submission of the form, please turn `loading` into `loading()`:
16+
17+
18+
```ruby
19+
form_submit do
20+
button text: "Submit me!", attributes: { "v-bind:disabled": "loading()" }
21+
end
22+
```
23+
24+
If you have implemented your own form components, please adjust them as described in the customize section of each form component. Most likely, you now have to provide exactly one root element per form component due to the reworked form components.
25+
26+
### Improvements
27+
28+
- Splitted form API docs into multiple files
29+
- Implements #474 Add HTML `<select>` tag to core components
30+
- Implements #492 Enable extendability of `form_*` components
31+
- Reworked `form_*` components in order to provide a better API for custom form components
32+
- `form_*` components are separate Vue.js components now
33+
- Each `form_*` uses a Vue.js mixin and a Ruby base class. This mixin and base class can be used in custom components in order to easy create own form components
34+
35+
## Bugfixes
36+
37+
- Fixes #490 Custom classes for checkboxes
38+
- Fixes #494 true/false checkboxes are initialized incorrectly
39+
40+
341
## v1.2.0 Release
442

543
### Improvements
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)