matestack-ui-vuejs 3.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +20 -0
- data/README.md +492 -0
- data/Rakefile +64 -0
- data/lib/matestack/ui/component.rb +1 -0
- data/lib/matestack/ui/isolated_component.rb +1 -0
- data/lib/matestack/ui/vue_js/components/action.js +70 -0
- data/lib/matestack/ui/vue_js/components/action.rb +46 -0
- data/lib/matestack/ui/vue_js/components/app.js +122 -0
- data/lib/matestack/ui/vue_js/components/app.rb +46 -0
- data/lib/matestack/ui/vue_js/components/async.js +104 -0
- data/lib/matestack/ui/vue_js/components/async.rb +84 -0
- data/lib/matestack/ui/vue_js/components/cable.js +96 -0
- data/lib/matestack/ui/vue_js/components/cable.rb +69 -0
- data/lib/matestack/ui/vue_js/components/collection/content.js +96 -0
- data/lib/matestack/ui/vue_js/components/collection/content.rb +32 -0
- data/lib/matestack/ui/vue_js/components/collection/filter.js +45 -0
- data/lib/matestack/ui/vue_js/components/collection/filter.rb +29 -0
- data/lib/matestack/ui/vue_js/components/collection/filter_reset.rb +19 -0
- data/lib/matestack/ui/vue_js/components/collection/helper.rb +128 -0
- data/lib/matestack/ui/vue_js/components/collection/next.rb +19 -0
- data/lib/matestack/ui/vue_js/components/collection/order.js +45 -0
- data/lib/matestack/ui/vue_js/components/collection/order.rb +28 -0
- data/lib/matestack/ui/vue_js/components/collection/order_toggle.rb +21 -0
- data/lib/matestack/ui/vue_js/components/collection/order_toggle_indicator.rb +30 -0
- data/lib/matestack/ui/vue_js/components/collection/page.rb +21 -0
- data/lib/matestack/ui/vue_js/components/collection/previous.rb +19 -0
- data/lib/matestack/ui/vue_js/components/form/base.rb +179 -0
- data/lib/matestack/ui/vue_js/components/form/checkbox.js +13 -0
- data/lib/matestack/ui/vue_js/components/form/checkbox.rb +109 -0
- data/lib/matestack/ui/vue_js/components/form/checkbox_mixin.js +90 -0
- data/lib/matestack/ui/vue_js/components/form/context.rb +15 -0
- data/lib/matestack/ui/vue_js/components/form/fields_for_add_item.js +50 -0
- data/lib/matestack/ui/vue_js/components/form/fields_for_add_item.rb +35 -0
- data/lib/matestack/ui/vue_js/components/form/fields_for_remove_item.rb +19 -0
- data/lib/matestack/ui/vue_js/components/form/form.js +276 -0
- data/lib/matestack/ui/vue_js/components/form/form.rb +77 -0
- data/lib/matestack/ui/vue_js/components/form/input.js +13 -0
- data/lib/matestack/ui/vue_js/components/form/input.rb +54 -0
- data/lib/matestack/ui/vue_js/components/form/input_mixin.js +79 -0
- data/lib/matestack/ui/vue_js/components/form/nested_form.js +153 -0
- data/lib/matestack/ui/vue_js/components/form/nested_form.rb +57 -0
- data/lib/matestack/ui/vue_js/components/form/radio.js +13 -0
- data/lib/matestack/ui/vue_js/components/form/radio.rb +85 -0
- data/lib/matestack/ui/vue_js/components/form/radio_mixin.js +75 -0
- data/lib/matestack/ui/vue_js/components/form/select.js +13 -0
- data/lib/matestack/ui/vue_js/components/form/select.rb +96 -0
- data/lib/matestack/ui/vue_js/components/form/select_mixin.js +76 -0
- data/lib/matestack/ui/vue_js/components/form/textarea.js +13 -0
- data/lib/matestack/ui/vue_js/components/form/textarea.rb +37 -0
- data/lib/matestack/ui/vue_js/components/form/textarea_mixin.js +54 -0
- data/lib/matestack/ui/vue_js/components/helpers.js +5 -0
- data/lib/matestack/ui/vue_js/components/isolated.js +105 -0
- data/lib/matestack/ui/vue_js/components/isolated.rb +86 -0
- data/lib/matestack/ui/vue_js/components/mixin.js +66 -0
- data/lib/matestack/ui/vue_js/components/onclick.js +18 -0
- data/lib/matestack/ui/vue_js/components/onclick.rb +37 -0
- data/lib/matestack/ui/vue_js/components/page_switch.js +24 -0
- data/lib/matestack/ui/vue_js/components/page_switch.rb +35 -0
- data/lib/matestack/ui/vue_js/components/runtime_render.js +17 -0
- data/lib/matestack/ui/vue_js/components/toggle.js +70 -0
- data/lib/matestack/ui/vue_js/components/toggle.rb +38 -0
- data/lib/matestack/ui/vue_js/components/transition.js +44 -0
- data/lib/matestack/ui/vue_js/components/transition.rb +40 -0
- data/lib/matestack/ui/vue_js/components/transition_handling_mixin.js +100 -0
- data/lib/matestack/ui/vue_js/components.rb +118 -0
- data/lib/matestack/ui/vue_js/event_hub.js +12 -0
- data/lib/matestack/ui/vue_js/helpers/query_params_helper.js +56 -0
- data/lib/matestack/ui/vue_js/index.js +94 -0
- data/lib/matestack/ui/vue_js/initialize.rb +10 -0
- data/lib/matestack/ui/vue_js/utils.rb +67 -0
- data/lib/matestack/ui/vue_js/version.rb +7 -0
- data/lib/matestack/ui/vue_js/vue.rb +75 -0
- data/lib/matestack/ui/vue_js/vue_attributes.rb +13 -0
- data/lib/matestack/ui/vue_js.rb +52 -0
- data/lib/matestack/ui/vue_js_component.rb +1 -0
- metadata +150 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
module Matestack
|
2
|
+
module Ui
|
3
|
+
module VueJs
|
4
|
+
module Components
|
5
|
+
module Form
|
6
|
+
class Input < Matestack::Ui::VueJs::Components::Form::Base
|
7
|
+
vue_name 'matestack-ui-core-form-input'
|
8
|
+
|
9
|
+
def initialize(*)
|
10
|
+
super
|
11
|
+
if ctx.type.to_s == "file"
|
12
|
+
if !form_context.is_nested_form? && form_context.multipart_option != true
|
13
|
+
raise "File Upload requires `multipart: true` in Form Config"
|
14
|
+
end
|
15
|
+
if form_context.is_nested_form? && form_context.parent_form_context.multipart_option != true
|
16
|
+
raise "File Upload requires `multipart: true` in Form Config"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def response
|
22
|
+
div class: 'matestack-ui-core-form-input' do
|
23
|
+
label input_label, ":for": id if input_label
|
24
|
+
input input_attributes
|
25
|
+
render_errors
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def component_id
|
30
|
+
"input-component-for-#{attribute_key}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def input_attributes
|
34
|
+
attributes
|
35
|
+
end
|
36
|
+
|
37
|
+
def init_value
|
38
|
+
return nil if ctx.type.to_s == "file"
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
42
|
+
def vue_props
|
43
|
+
{
|
44
|
+
init_value: init_value,
|
45
|
+
key: key,
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
import matestackEventHub from '../../event_hub'
|
2
|
+
|
3
|
+
const formInputMixin = {
|
4
|
+
inject: [
|
5
|
+
'parentFormUid',
|
6
|
+
'parentFormData',
|
7
|
+
'parentFormErrors',
|
8
|
+
'parentFormLoading',
|
9
|
+
'parentFormIsNestedForm',
|
10
|
+
'parentFormResetErrors',
|
11
|
+
'parentNestedFormRuntimeId'
|
12
|
+
],
|
13
|
+
methods: {
|
14
|
+
initialize: function(){
|
15
|
+
const self = this
|
16
|
+
let data = {};
|
17
|
+
|
18
|
+
for (let key in self.getRefs()) {
|
19
|
+
if (key.startsWith("input.")) {
|
20
|
+
let initValue = self.getRefs()[key]["attributes"]["init-value"];
|
21
|
+
|
22
|
+
self.parentFormData[key.replace("input.", "")] = null
|
23
|
+
|
24
|
+
if (initValue) {
|
25
|
+
self.setValue(initValue["value"])
|
26
|
+
self.afterInitialize(initValue["value"])
|
27
|
+
} else {
|
28
|
+
self.setValue(null)
|
29
|
+
self.afterInitialize(null)
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
},
|
35
|
+
filesAdded: function (key) {
|
36
|
+
const dataTransfer = event.dataTransfer || event.target;
|
37
|
+
const files = dataTransfer.files;
|
38
|
+
if (event.target.attributes.multiple) {
|
39
|
+
this.parentFormData[key] = [];
|
40
|
+
for (let index in files) {
|
41
|
+
if (files[index] instanceof File) {
|
42
|
+
this.parentFormData[key].push(files[index]);
|
43
|
+
}
|
44
|
+
}
|
45
|
+
} else {
|
46
|
+
this.parentFormData[key] = files[0];
|
47
|
+
}
|
48
|
+
},
|
49
|
+
inputChanged: function (key) {
|
50
|
+
if (this.parentFormIsNestedForm){
|
51
|
+
this.parentFormData["_destroy"] = false;
|
52
|
+
}
|
53
|
+
this.parentFormResetErrors(key);
|
54
|
+
|
55
|
+
},
|
56
|
+
afterInitialize: function(value){
|
57
|
+
// can be used in the main component for further initialization steps
|
58
|
+
},
|
59
|
+
setValue: function (value){
|
60
|
+
if(this.getRefs()["input."+this.props["key"]]){
|
61
|
+
this.getRefs()["input."+this.props["key"]].value = value; // reset file upload inputs properly
|
62
|
+
}
|
63
|
+
if(this.getRefs()["input."+this.props["key"]+"[]"]){
|
64
|
+
this.getRefs()["input."+this.props["key"]+"[]"].value = value; // reset multiple file upload inputs properly
|
65
|
+
}
|
66
|
+
this.parentFormData[this.props["key"]] = value;
|
67
|
+
}
|
68
|
+
},
|
69
|
+
mounted: function(){
|
70
|
+
this.registerScopedEvent("init", this.initialize, this.parentFormUid)
|
71
|
+
},
|
72
|
+
beforeUnmount: function(){
|
73
|
+
this.removeScopedEvent("init", this.initialize, this.parentFormUid)
|
74
|
+
}
|
75
|
+
|
76
|
+
|
77
|
+
}
|
78
|
+
|
79
|
+
export default formInputMixin
|
@@ -0,0 +1,153 @@
|
|
1
|
+
import { computed } from "vue";
|
2
|
+
import axios from "axios";
|
3
|
+
|
4
|
+
import matestackEventHub from "../../event_hub";
|
5
|
+
import componentMixin from "../mixin";
|
6
|
+
import componentHelpers from "../helpers";
|
7
|
+
|
8
|
+
const componentDef = {
|
9
|
+
mixins: [componentMixin],
|
10
|
+
template: componentHelpers.inlineTemplate,
|
11
|
+
data: function () {
|
12
|
+
return {
|
13
|
+
data: {},
|
14
|
+
errors: {},
|
15
|
+
isNestedForm: true,
|
16
|
+
hideNestedForm: false,
|
17
|
+
nestedFormRuntimeId: "",
|
18
|
+
nestedFormServerErrorIndex: "",
|
19
|
+
};
|
20
|
+
},
|
21
|
+
provide: function() {
|
22
|
+
return {
|
23
|
+
parentFormUid: computed(() => this.props["component_uid"]),
|
24
|
+
parentFormData: computed(() => this.data),
|
25
|
+
parentFormErrors: computed(() => this.errors),
|
26
|
+
parentNestedFormRuntimeId: computed(() => this.nestedFormRuntimeId),
|
27
|
+
parentFormMapToNestedForms: this.mapToNestedForms,
|
28
|
+
parentFormSetErrors: this.setErrors,
|
29
|
+
parentFormResetErrors: this.resetErrors,
|
30
|
+
}
|
31
|
+
},
|
32
|
+
inject: [
|
33
|
+
'parentFormData',
|
34
|
+
'parentFormErrors',
|
35
|
+
'parentNestedForms',
|
36
|
+
'parentDeletedNestedForms',
|
37
|
+
'parentFormMapToNestedForms'
|
38
|
+
],
|
39
|
+
methods: {
|
40
|
+
initDataKey: function (key, initValue) {
|
41
|
+
this.data[key] = initValue;
|
42
|
+
},
|
43
|
+
updateFormValue: function (key, value) {
|
44
|
+
this.data[key] = value;
|
45
|
+
},
|
46
|
+
hasErrors: function(){
|
47
|
+
//https://stackoverflow.com/a/27709663/13886137
|
48
|
+
for (var key in this.errors) {
|
49
|
+
if (this.errors[key] !== null && this.errors[key] != ""){
|
50
|
+
return true;
|
51
|
+
}
|
52
|
+
}
|
53
|
+
return false;
|
54
|
+
},
|
55
|
+
resetErrors: function (key) {
|
56
|
+
if (this.errors[key]) {
|
57
|
+
delete this.errors[key];
|
58
|
+
}
|
59
|
+
var serverErrorKey = this.props["fields_for"].replace("_attributes", "")+"["+this.nestedFormServerErrorIndex+"]."+key
|
60
|
+
if (this.parentFormErrors[serverErrorKey]) {
|
61
|
+
delete this.parentFormErrors[serverErrorKey];
|
62
|
+
}
|
63
|
+
},
|
64
|
+
setErrors: function(errors){
|
65
|
+
this.errors = errors;
|
66
|
+
},
|
67
|
+
setNestedFormServerErrorIndex: function(value){
|
68
|
+
this.nestedFormServerErrorIndex = value;
|
69
|
+
},
|
70
|
+
setErrorKey: function(key, value){
|
71
|
+
this.errors[key] = value;
|
72
|
+
},
|
73
|
+
flushErrors: function(key, value){
|
74
|
+
this.errors = {};
|
75
|
+
},
|
76
|
+
removeItem: function(){
|
77
|
+
this.data["_destroy"] = true
|
78
|
+
this.hideNestedForm = true;
|
79
|
+
var id = parseInt(this.nestedFormRuntimeId.replace("_"+this.props["fields_for"]+"_child_", ""));
|
80
|
+
this.parentDeletedNestedForms[this.props["fields_for"]].push(id);
|
81
|
+
var serverErrorKey = this.props["fields_for"].replace("_attributes", "")+"["+this.nestedFormServerErrorIndex+"]."
|
82
|
+
var self = this;
|
83
|
+
Object.keys(self.parentFormErrors).forEach(function(errorKey){
|
84
|
+
if (errorKey.lastIndexOf(serverErrorKey, 0) == 0) {
|
85
|
+
delete self.parentFormErrors[errorKey];
|
86
|
+
}
|
87
|
+
});
|
88
|
+
},
|
89
|
+
initValues: function () {
|
90
|
+
this.emitScopedEvent("init") // received by child input components
|
91
|
+
}
|
92
|
+
},
|
93
|
+
mounted: function () {
|
94
|
+
var self = this;
|
95
|
+
|
96
|
+
this.data = { "_destroy": false };
|
97
|
+
|
98
|
+
//initialize nestedForm data in parent form if required
|
99
|
+
if(this.parentFormData[this.props["fields_for"]] == undefined){
|
100
|
+
this.parentFormData[this.props["fields_for"]] = [];
|
101
|
+
}
|
102
|
+
if(this.parentNestedForms[this.props["fields_for"]] == undefined){
|
103
|
+
this.parentNestedForms[this.props["fields_for"]] = [];
|
104
|
+
}
|
105
|
+
if(this.parentDeletedNestedForms[this.props["fields_for"]] == undefined){
|
106
|
+
this.parentDeletedNestedForms[this.props["fields_for"]] = [];
|
107
|
+
}
|
108
|
+
|
109
|
+
var id = parseInt(self.getElement().querySelector('.matestack-form-fields-for').id.replace(this.props["fields_for"]+"_child_", ""))
|
110
|
+
|
111
|
+
//setup data binding for serverside rendered nested forms
|
112
|
+
if (isNaN(id)){
|
113
|
+
id = this.parentNestedForms[this.props["fields_for"]].length
|
114
|
+
this.nestedFormRuntimeId = "_"+this.props["fields_for"]+"_child_"+id
|
115
|
+
this.getElement().id = this.props["fields_for"]+"_child_"+id
|
116
|
+
this.initValues()
|
117
|
+
this.parentFormData[this.props["fields_for"]].push(this.data);
|
118
|
+
this.parentNestedForms[this.props["fields_for"]].push(this);
|
119
|
+
}
|
120
|
+
|
121
|
+
//setup data binding for runtime nested forms (dynamic add via matestack-ui-core-runtime-render)
|
122
|
+
if (!isNaN(id)){
|
123
|
+
this.nestedFormRuntimeId = "_"+this.props["fields_for"]+"_child_"+id
|
124
|
+
if(this.parentFormData[this.props["fields_for"]][id] == undefined){
|
125
|
+
//new runtime form
|
126
|
+
this.initValues()
|
127
|
+
this.parentFormData[this.props["fields_for"]].push(this.data);
|
128
|
+
this.parentNestedForms[this.props["fields_for"]].push(this);
|
129
|
+
}else{
|
130
|
+
//retreive state for existing runtime form (after remount for example)
|
131
|
+
this.data = this.parentFormData[this.props["fields_for"]][id]
|
132
|
+
if (this.data["_destroy"] == true){
|
133
|
+
this.hideNestedForm = true;
|
134
|
+
}
|
135
|
+
this.parentNestedForms[this.props["fields_for"]][id] = this;
|
136
|
+
Object.keys(this.parentFormErrors).forEach(function(errorKey){
|
137
|
+
if (errorKey.includes(".")){
|
138
|
+
let childErrorKey = errorKey.split(".")[1]
|
139
|
+
let childModelName = errorKey.split(".")[0].split("[")[0]
|
140
|
+
let childModelIndex = errorKey.split(".")[0].split("[")[1].split("]")[0]
|
141
|
+
let mappedChildModelIndex = self.parentFormMapToNestedForms(parseInt(childModelIndex), childModelName+"_attributes")
|
142
|
+
if(childModelName+"_attributes" == self.props["fields_for"] && mappedChildModelIndex == id){
|
143
|
+
self.setNestedFormServerErrorIndex(parseInt(childModelIndex))
|
144
|
+
self.setErrorKey(childErrorKey, self.parentFormErrors[errorKey])
|
145
|
+
}
|
146
|
+
}
|
147
|
+
})
|
148
|
+
}
|
149
|
+
}
|
150
|
+
}
|
151
|
+
};
|
152
|
+
|
153
|
+
export default componentDef;
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Matestack
|
2
|
+
module Ui
|
3
|
+
module VueJs
|
4
|
+
module Components
|
5
|
+
module Form
|
6
|
+
class NestedForm < Matestack::Ui::VueJs::Components::Form::Form
|
7
|
+
vue_name 'matestack-ui-core-form-nested-form'
|
8
|
+
|
9
|
+
optional :fields_for, :reject_blank
|
10
|
+
|
11
|
+
attr_accessor :prototype_template
|
12
|
+
|
13
|
+
# setup form context to allow child components like inputs to access the form configuration
|
14
|
+
def initialize(html_tag = nil, text = nil, options = {}, &block)
|
15
|
+
previous_form_context = Matestack::Ui::VueJs::Components::Form::Context.form_context
|
16
|
+
if !previous_form_context.nil?
|
17
|
+
@is_nested_form = true
|
18
|
+
@parent_form_context = previous_form_context
|
19
|
+
end
|
20
|
+
Matestack::Ui::VueJs::Components::Form::Context.form_context = self
|
21
|
+
super(html_tag, text, options, &block)
|
22
|
+
Matestack::Ui::VueJs::Components::Form::Context.form_context = previous_form_context
|
23
|
+
end
|
24
|
+
|
25
|
+
def component_id
|
26
|
+
"matestack-form-fields-for-#{context.fields_for}-#{SecureRandom.hex}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def response
|
30
|
+
div class: "matestack-form-fields-for", "v-show": "vc.hideNestedForm != true", id: options[:id] do
|
31
|
+
form_input key: context.for&.class&.primary_key, type: :hidden # required for existing model mapping
|
32
|
+
form_input key: :_destroy, type: :hidden, init: true if context.reject_blank == true
|
33
|
+
yield
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def vue_props
|
38
|
+
super.merge({
|
39
|
+
fields_for: ctx.fields_for,
|
40
|
+
primary_key: for_object_primary_key
|
41
|
+
})
|
42
|
+
end
|
43
|
+
|
44
|
+
def is_nested_form?
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def parent_form_context
|
49
|
+
@parent_form_context
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import formRadioMixin from "./radio_mixin";
|
2
|
+
import componentMixin from "../mixin";
|
3
|
+
import componentHelpers from "../helpers";
|
4
|
+
|
5
|
+
const componentDef = {
|
6
|
+
mixins: [componentMixin, formRadioMixin],
|
7
|
+
template: componentHelpers.inlineTemplate,
|
8
|
+
data() {
|
9
|
+
return {};
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
export default componentDef;
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Matestack
|
2
|
+
module Ui
|
3
|
+
module VueJs
|
4
|
+
module Components
|
5
|
+
module Form
|
6
|
+
class Radio < Matestack::Ui::VueJs::Components::Form::Base
|
7
|
+
vue_name 'matestack-ui-core-form-radio'
|
8
|
+
|
9
|
+
def response
|
10
|
+
div class: 'matestack-ui-core-form-radio' do
|
11
|
+
render_options
|
12
|
+
render_errors
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def render_options
|
17
|
+
radio_options.to_a.each do |item|
|
18
|
+
input radio_attributes(item)
|
19
|
+
label item_label(item), ":for": item_id(item)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def component_id
|
24
|
+
"radio-component-for-#{key}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def vue_props
|
28
|
+
{
|
29
|
+
init_value: init_value,
|
30
|
+
key: key,
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def radio_attributes(item)
|
35
|
+
attributes.merge({
|
36
|
+
":id": item_id(item),
|
37
|
+
name: item_name(item),
|
38
|
+
type: :radio,
|
39
|
+
"matestack-ui-core-ref": scoped_ref("select.#{key}"),
|
40
|
+
'value-type': value_type(item_value(radio_options.first))
|
41
|
+
}).tap do |attrs|
|
42
|
+
attrs[value_key(item)] = item_value(item)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def radio_options
|
47
|
+
@radio_options ||= options.delete(:options)
|
48
|
+
end
|
49
|
+
|
50
|
+
# calculated attributes
|
51
|
+
|
52
|
+
def item_value(item)
|
53
|
+
item.is_a?(Array) ? item.last : item
|
54
|
+
end
|
55
|
+
|
56
|
+
def item_label(item)
|
57
|
+
item.is_a?(Array) ? item.first : item
|
58
|
+
end
|
59
|
+
|
60
|
+
def item_id(item)
|
61
|
+
"#{id || key}+'_#{item_value(item)}'"
|
62
|
+
end
|
63
|
+
|
64
|
+
def item_name(item)
|
65
|
+
"#{key}_#{item_value(item)}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def v_model_type
|
69
|
+
item_value(radio_options.first).is_a?(Numeric) ? 'v-model.number' : 'v-model'
|
70
|
+
end
|
71
|
+
|
72
|
+
def value_key(value)
|
73
|
+
if value.is_a?(Array)
|
74
|
+
value[1].is_a?(Numeric) ? ':value' : 'value'
|
75
|
+
else
|
76
|
+
value.is_a?(Numeric) ? ':value' : 'value'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
const formRadioMixin = {
|
2
|
+
inject: [
|
3
|
+
'parentFormUid',
|
4
|
+
'parentFormData',
|
5
|
+
'parentFormErrors',
|
6
|
+
'parentFormLoading',
|
7
|
+
'parentFormIsNestedForm',
|
8
|
+
'parentFormResetErrors',
|
9
|
+
'parentNestedFormRuntimeId'
|
10
|
+
],
|
11
|
+
methods: {
|
12
|
+
initialize: function(){
|
13
|
+
const self = this
|
14
|
+
let data = {};
|
15
|
+
|
16
|
+
for (let key in self.getRefs()) {
|
17
|
+
let initValue;
|
18
|
+
let valueType;
|
19
|
+
|
20
|
+
if (key.startsWith("select.")) {
|
21
|
+
initValue = self.getRefs()[key]["attributes"]["init-value"];
|
22
|
+
valueType = self.getRefs()[key]["attributes"]["value-type"];
|
23
|
+
}
|
24
|
+
|
25
|
+
if (key.startsWith("select.")) {
|
26
|
+
if (key.startsWith("select.multiple.")) {
|
27
|
+
self.parentFormData[key.replace("select.multiple.", "")] = null
|
28
|
+
if (initValue) {
|
29
|
+
self.setValue(JSON.parse(initValue["value"]));
|
30
|
+
self.afterInitialize(JSON.parse(initValue["value"]))
|
31
|
+
} else {
|
32
|
+
self.setValue([]);
|
33
|
+
self.afterInitialize([]);
|
34
|
+
}
|
35
|
+
} else {
|
36
|
+
self.parentFormData[key.replace("select.", "")] = null
|
37
|
+
if (initValue) {
|
38
|
+
if (valueType && valueType["value"] == "Integer") {
|
39
|
+
self.setValue(parseInt(initValue["value"]));
|
40
|
+
self.afterInitialize(parseInt(initValue["value"]))
|
41
|
+
} else {
|
42
|
+
self.setValue(initValue["value"]);
|
43
|
+
self.afterInitialize(initValue["value"])
|
44
|
+
}
|
45
|
+
} else {
|
46
|
+
self.setValue(null);
|
47
|
+
self.afterInitialize(null)
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
},
|
53
|
+
inputChanged: function (key) {
|
54
|
+
if (this.parentFormIsNestedForm){
|
55
|
+
this.parentFormData["_destroy"] = false;
|
56
|
+
}
|
57
|
+
this.parentFormResetErrors(key);
|
58
|
+
},
|
59
|
+
afterInitialize: function(value){
|
60
|
+
// can be used in the main component for further initialization steps
|
61
|
+
},
|
62
|
+
setValue: function (value){
|
63
|
+
this.parentFormData[this.props["key"]] = value
|
64
|
+
}
|
65
|
+
},
|
66
|
+
mounted: function(){
|
67
|
+
this.registerScopedEvent("init", this.initialize, this.parentFormUid)
|
68
|
+
},
|
69
|
+
beforeUnmount: function(){
|
70
|
+
this.removeScopedEvent("init", this.initialize, this.parentFormUid)
|
71
|
+
}
|
72
|
+
|
73
|
+
}
|
74
|
+
|
75
|
+
export default formRadioMixin
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import formSelectMixin from "./select_mixin";
|
2
|
+
import componentMixin from "../mixin";
|
3
|
+
import componentHelpers from "../helpers";
|
4
|
+
|
5
|
+
const componentDef = {
|
6
|
+
mixins: [componentMixin, formSelectMixin],
|
7
|
+
template: componentHelpers.inlineTemplate,
|
8
|
+
data() {
|
9
|
+
return {};
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
export default componentDef;
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Matestack
|
2
|
+
module Ui
|
3
|
+
module VueJs
|
4
|
+
module Components
|
5
|
+
module Form
|
6
|
+
class Select < Matestack::Ui::VueJs::Components::Form::Base
|
7
|
+
vue_name 'matestack-ui-core-form-select'
|
8
|
+
|
9
|
+
def response
|
10
|
+
div class: 'matestack-ui-core-form-select' do
|
11
|
+
label input_label, ":for": id if input_label
|
12
|
+
select select_attributes do
|
13
|
+
render_options
|
14
|
+
end
|
15
|
+
render_errors
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def render_options
|
20
|
+
if placeholder
|
21
|
+
option value: nil, disabled: true, selected: init_value.nil?, text: placeholder
|
22
|
+
end
|
23
|
+
select_options.to_a.each do |item|
|
24
|
+
option_config = {}.tap do |attrs|
|
25
|
+
attrs[value_key(item)] = item_value(item)
|
26
|
+
attrs[:disabled] = item_disabled?(item)
|
27
|
+
end
|
28
|
+
option item_label(item), option_config
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def component_id
|
33
|
+
"select-component-for-#{key}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def vue_props
|
37
|
+
{
|
38
|
+
init_value: init_value,
|
39
|
+
key: key,
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def select_attributes
|
44
|
+
attributes.except(:options).merge({
|
45
|
+
multiple: multiple,
|
46
|
+
":id": id,
|
47
|
+
"matestack-ui-core-ref": scoped_ref("select#{'.multiple' if multiple}.#{key}"),
|
48
|
+
'value-type': value_type(select_options.first),
|
49
|
+
'init-value': init_value,
|
50
|
+
})
|
51
|
+
end
|
52
|
+
|
53
|
+
# select options
|
54
|
+
|
55
|
+
def select_options
|
56
|
+
@select_options ||= options.delete(:options)
|
57
|
+
end
|
58
|
+
|
59
|
+
# calculated attributes
|
60
|
+
|
61
|
+
def item_value(item)
|
62
|
+
item.is_a?(Array) ? item.last : item
|
63
|
+
end
|
64
|
+
|
65
|
+
def item_label(item)
|
66
|
+
item.is_a?(Array) ? item.first : item
|
67
|
+
end
|
68
|
+
|
69
|
+
def item_id(item)
|
70
|
+
"#{key}_#{item_value(item)}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def item_disabled?(item)
|
74
|
+
disabled_options && disabled_options.to_a.include?(item)
|
75
|
+
end
|
76
|
+
|
77
|
+
def v_model_type
|
78
|
+
item_value(select_options.first).is_a?(Numeric) ? 'v-model.number' : 'v-model'
|
79
|
+
end
|
80
|
+
|
81
|
+
def value_key(value)
|
82
|
+
value.is_a?(Numeric) ? ':value' : 'value'
|
83
|
+
end
|
84
|
+
|
85
|
+
# attributes
|
86
|
+
|
87
|
+
def disabled_options
|
88
|
+
@disabled_options ||= options.delete(:disabled_options)
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|