-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmtz-wizard.html
190 lines (187 loc) · 5.82 KB
/
mtz-wizard.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../iron-pages/iron-pages.html">
<!--
`mtz-wizard`
Maintains a curated list of steps for use in the stepper and manages selected state of the steps, provides convenience
methods for navigation and `wizard-form` interactions, is responsible for rendering the currently active step.
@demo demo/index.html
-->
<dom-module id="mtz-wizard">
<template>
<iron-pages
id="selector"
attr-for-selected="[[attrForSelected]]"
selectable="[[selectable]]"
selected-attribute="[[selectedAttribute]]"
selected-class="[[selectedClass]]"
selected-item="{{selectedItem}}"
selected="{{selected}}"
items="{{steps}}">
<slot></slot>
</iron-pages>
</template>
<script>
Polymer({
is: 'mtz-wizard',
properties: {
/* Determines if this wizard is active or not, used to attach/detach the steps from the DOM for data reset */
active: {
type: Boolean,
value: false,
reflectToAttribute: true,
},
/* The attribute to use to match the selection key against */
attrForSelected: {
type: String,
value: 'name',
},
/* Set to true when on the first step in the wizard */
onFirstStep: {
type: Boolean,
value: false,
readOnly: true,
notify: true,
},
/* Set to true when on the last step in the wizard */
onLastStep: {
type: Boolean,
value: false,
readOnly: true,
notify: true,
},
/* This is a CSS selector string. If this is set, only items that match the CSS selector are selectable. */
selectable: {
type: String,
value: '[wizard-step],.wizard-step',
},
/* The currently selected step, null if no step is selected */
selected: {
type: String,
value: null,
notify: true,
},
/* The attribute to set on elements when selected */
selectedAttribute: {
type: String,
value: 'active',
},
/* The class to set on elements when selected. */
selectedClass: String,
/* The currently selected item */
selectedItem: {
type: Object,
notify: true,
observer: '__selectedItemChanged',
},
/* The Set of HTMLElements that make up the steps */
steps: {
type: Array,
notify: true,
},
},
observers: [
'__setDefaultSelection(steps, attrForSelected)',
],
/**
* Fetches the model from all steps that have a form with a dirty model, returns as a map of step name to model.
*
* @param {HTMLElement[]} [steps = this.steps]
* @param {String} [attr = this.attrForSelected]
* @return {Object}
*/
getFormData(steps = this.steps, attr = this.attrForSelected) {
const data = (steps || []).reduce((model, step) => {
if (step.form && step.dirty)
model[step.getAttribute(attr)] = step.form.serializeForm();
return model;
}, {});
return data;
},
/**
* Changes the currently active step to the next step in the array of steps, loops from end to beginning.
*/
next() {
if (!this.onLastStep)
this.$.selector.selectNext();
},
/**
* Changes the currently active step to the previous step in the array of steps, loops from beginning to end.
*/
previous() {
if (!this.onFirstStep)
this.$.selector.selectPrevious();
},
/**
* Runs the reset logic on every step that has a form bound to it.
*
* @param {HTMLElement[]} [steps = this.steps]
*/
reset(steps = this.steps) {
(steps || []).forEach((step) => {
if (step.reset) step.reset();
});
},
/**
* Selects the step at the given key.
*
* @param {String} key - the key to selecte the step based on
* @return {HTMLElement}
*/
select(key) {
this.$.selector.select(key);
return this.selectedItem;
},
/**
* Selects the step at the given index.
*
* @param {Number} index
* @return {HTMLElement}
*/
selectIndex(index) {
this.$.selector.selectIndex(index);
return this.selectedItem;
},
/**
* Runs the validation logic on all steps with a form bound to them.
*
* @param {HTMLElement[]} [steps = this.steps]
* @return {Promise} - resolves with a Boolean that says if the wizard is valid or not
*/
validate(steps = this.steps) {
return Promise.all((steps || []).
map((step) => {
return Promise.resolve(!step.validate || step.validate());
})).
then((promises) => {
return promises.every(Boolean);
}).
catch(() => {
return false;
});
},
/**
* Sets the fallback selection as the first item.
* @private
*
* @param {HTMLElement[]} steps
* @param {String} attr - the attrForSelected property
*/
__setDefaultSelection(steps, attr) {
if (!this.selected && attr && steps && steps.length > 0) {
this.set('selected', steps[0].getAttribute(attr));
}
},
/**
* Runs when selected item is changed, used to set onFirstStep and onLastStep.
* @private
*
* @param {Object} item - the selected item
*/
__selectedItemChanged(item) {
const index = item ? this.$.selector.indexOf(item) : null;
this._setOnFirstStep(index === 0);
this._setOnLastStep(index === this.steps.length - 1);
},
});
</script>
</dom-module>