Skip to content

Commit 6f19746

Browse files
Merge pull request #35 from webdevnerdstuff/dev
Dev
2 parents f839892 + a8dd990 commit 6f19746

File tree

5 files changed

+466
-5
lines changed

5 files changed

+466
-5
lines changed

src/documentation/components/examples/ButtonsFieldExample.vue

+4-4
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,8 @@ const pages = computed(() => [
276276
{
277277
fields: [
278278
{
279-
align: buttonAlignModel,
280-
block: buttonBlock,
279+
align: buttonAlignModel.value,
280+
block: buttonBlock.value,
281281
label: 'I like buttons',
282282
name: 'iLikeButtons',
283283
options: [
@@ -309,8 +309,8 @@ const pages = computed(() => [
309309
type: 'buttons' as const,
310310
},
311311
{
312-
align: buttonAlignModel,
313-
block: buttonBlock,
312+
align: buttonAlignModel.value,
313+
block: buttonBlock.value,
314314
label: 'I like...',
315315
multiple: true,
316316
name: 'animalsILike',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
<template>
2+
<VStepperForm
3+
v-model="answers"
4+
color="primary"
5+
:pages="pages"
6+
@submit="submitForm"
7+
/>
8+
9+
<AnswersDialog
10+
v-model="dialog"
11+
:answers="answers"
12+
/>
13+
</template>
14+
15+
<script setup lang="ts">
16+
import type { MaybeRef } from 'vue';
17+
import AnswersDialog from '../AnswersDialog.vue';
18+
19+
20+
const dialog = ref(false);
21+
const answers = ref<{
22+
foobar: string | null;
23+
name: string | null;
24+
slug: string | null;
25+
}>({
26+
foobar: null,
27+
name: null,
28+
slug: null,
29+
});
30+
31+
watch(() => answers.value.name, (newVal) => {
32+
setTimeout(() => {
33+
answers.value.slug = newVal ? useSlugifyString(newVal) : '';
34+
}, 1);
35+
36+
if (newVal === 'foo' || answers.value.slug === '') {
37+
selectItems.value = fooItems;
38+
}
39+
40+
if (newVal === 'bar') {
41+
selectItems.value = barItems;
42+
}
43+
});
44+
45+
const fooItems = [
46+
{
47+
title: 'Foo',
48+
value: 'foo',
49+
},
50+
{
51+
title: 'Fiz',
52+
value: 'fiz',
53+
},
54+
];
55+
56+
const barItems = [
57+
{
58+
title: 'Baz',
59+
value: 'baz',
60+
},
61+
{
62+
title: 'Biz',
63+
value: 'biz',
64+
},
65+
];
66+
67+
const selectItems = ref(fooItems);
68+
69+
const pages = computed(() => {
70+
return [
71+
{
72+
fields: [
73+
{
74+
label: 'Name',
75+
name: 'name',
76+
type: 'text' as const,
77+
},
78+
{
79+
label: 'Slug',
80+
name: 'slug',
81+
type: 'text' as const,
82+
},
83+
{
84+
items: selectItems.value,
85+
label: 'Foobar',
86+
name: 'foobar',
87+
type: 'select' as const,
88+
},
89+
],
90+
},
91+
];
92+
});
93+
94+
const useSlugifyString: UseSlugifyString = (string, divider = '_') => {
95+
if (divider !== '_' && divider !== '-') {
96+
throw new Error('[slugifyStringHelper]: Divider must be either "_" or "-"');
97+
}
98+
99+
const unrefString = unref(string);
100+
101+
const a = 'àáâäæãåāăąçćčđďèéêëēėęěğǵḧîïíīįìłḿñńǹňôöòóœøōõőṕŕřßśšşșťțûüùúūǘůűųẃẍÿýžźż·/-,:;';
102+
const b = 'aaaaaaaaaacccddeeeeeeeegghiiiiiilmnnnnoooooooooprrsssssttuuuuuuuuuwxyyzzz------';
103+
const p = new RegExp(a.split('').join('|'), 'g');
104+
105+
let response = unrefString.toString().toLowerCase()
106+
// Replace spaces with divider //
107+
.replace(/\s+/g, divider)
108+
.replace(p, (c) => b.charAt(a.indexOf(c)))
109+
.replace(/&/g, `${divider}and${divider}`)
110+
.replace(/[^\w-]+/g, '');
111+
112+
if (divider === '_') {
113+
response = response.replace(/-+/g, '_')
114+
.replace(/__+/g, '_')
115+
.replace(/^_/, '')
116+
.replace(/^-+/, '')
117+
.replace(/-+$/, '');
118+
}
119+
120+
if (divider === '-') {
121+
response = response.replace(/_+/g, '-')
122+
.replace(/--+/g, '-')
123+
.replace(/^-/, '')
124+
.replace(/^_+/, '')
125+
.replace(/_+$/, '');
126+
}
127+
128+
return response;
129+
};
130+
131+
export interface UseSlugifyString {
132+
(
133+
string: MaybeRef<string>,
134+
divider?: string,
135+
): string;
136+
};
137+
138+
function submitForm(): void {
139+
dialog.value = true;
140+
}
141+
142+
const templateCode = computed(() => (
143+
`<template>
144+
<VStepperForm
145+
v-model="answers"
146+
color="primary"
147+
:pages="pages"
148+
@submit="submitForm"
149+
/>
150+
</template>`
151+
));
152+
153+
const scriptCode = computed(() => (
154+
`\<script setup\>
155+
const answers = ref<{
156+
foobar: string | null;
157+
name: string | null;
158+
slug: string | null;
159+
}>({
160+
foobar: null,
161+
name: null,
162+
slug: null,
163+
});
164+
165+
watch(() => answers.value.name, (newVal) => {
166+
// Ensure the slug value updates correctly by using a setTimeout //
167+
setTimeout(() => {
168+
answers.value.slug = newVal ? useSlugifyString(newVal) : '';
169+
}, 1);
170+
171+
if (newVal === 'foo' || answers.value.slug === '') {
172+
selectItems.value = fooItems;
173+
}
174+
175+
if (newVal === 'bar') {
176+
selectItems.value = barItems;
177+
}
178+
});
179+
180+
const fooItems = [
181+
{
182+
title: 'Foo',
183+
value: 'foo',
184+
},
185+
{
186+
title: 'Fiz',
187+
value: 'fiz',
188+
},
189+
];
190+
191+
const barItems = [
192+
{
193+
title: 'Baz',
194+
value: 'baz',
195+
},
196+
{
197+
title: 'Biz',
198+
value: 'biz',
199+
},
200+
];
201+
202+
const selectItems = ref(fooItems);
203+
204+
const pages = computed(() => {
205+
return [
206+
{
207+
fields: [
208+
{
209+
label: 'Name',
210+
name: 'name',
211+
type: 'text' as const,
212+
},
213+
{
214+
label: 'Slug',
215+
name: 'slug',
216+
type: 'text' as const,
217+
},
218+
{
219+
items: selectItems.value,
220+
label: 'Foobar',
221+
name: 'foobar',
222+
type: 'select' as const,
223+
},
224+
],
225+
},
226+
];
227+
});
228+
229+
const useSlugifyString: UseSlugifyString = (string, divider = '_') => {
230+
if (divider !== '_' && divider !== '-') {
231+
throw new Error('[slugifyStringHelper]: Divider must be either "_" or "-"');
232+
}
233+
234+
const unrefString = unref(string);
235+
236+
const a = 'àáâäæãåāăąçćčđďèéêëēėęěğǵḧîïíīįìłḿñńǹňôöòóœøōõőṕŕřßśšşșťțûüùúūǘůűųẃẍÿýžźż·/-,:;';
237+
const b = 'aaaaaaaaaacccddeeeeeeeegghiiiiiilmnnnnoooooooooprrsssssttuuuuuuuuuwxyyzzz------';
238+
const p = new RegExp(a.split('').join('|'), 'g');
239+
240+
let response = unrefString.toString().toLowerCase()
241+
// Replace spaces with divider //
242+
.replace(/\s+/g, divider)
243+
.replace(p, (c) => b.charAt(a.indexOf(c)))
244+
.replace(/&/g, \`$\{divider}and$\{divider}\`)
245+
.replace(/[^\w-]+/g, '');
246+
247+
if (divider === '_') {
248+
response = response.replace(/-+/g, '_')
249+
.replace(/__+/g, '_')
250+
.replace(/^_/, '')
251+
.replace(/^-+/, '')
252+
.replace(/-+$/, '');
253+
}
254+
255+
if (divider === '-') {
256+
response = response.replace(/_+/g, '-')
257+
.replace(/--+/g, '-')
258+
.replace(/^-/, '')
259+
.replace(/^_+/, '')
260+
.replace(/_+$/, '');
261+
}
262+
263+
return response;
264+
};
265+
266+
export interface UseSlugifyString {
267+
(
268+
string: MaybeRef<string>,
269+
divider?: string,
270+
): string;
271+
};
272+
\</script\>`
273+
));
274+
275+
const exampleCode = computed(() => ({
276+
desc: 'This example showcases how to build a form with dynamic questions and responses. When you enter "foo" or "bar" in the name field, the select field updates automatically.<br /><br />To ensure the "slug" value updates correctly, use a setTimeout function within the watcher to modify its value after the name field changes.',
277+
name: 'Dynamic Answers and Questions',
278+
script: scriptCode.value,
279+
template: templateCode.value,
280+
}));
281+
282+
defineExpose({
283+
exampleCode: exampleCode.value,
284+
});
285+
</script>
286+
287+
288+
<style lang="scss" scoped></style>

src/documentation/components/examples/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import ButtonsFieldExample from './ButtonsFieldExample.vue';
22
import ColumnsExample from './ColumnsExample.vue';
33
import ConditionalFieldExample from './ConditionalFieldExample.vue';
44
import ConditionalPageExample from './ConditionalPageExample.vue';
5+
import DynamicAnswersQuestionsExample from './DynamicAnswersQuestionsExample.vue';
56
import FieldSlotExample from './FieldSlotExample.vue';
67
import SimpleExample from './SimpleExample.vue';
78
import SummaryPageExample from './SummaryPageExample.vue';
@@ -14,6 +15,7 @@ export {
1415
ColumnsExample,
1516
ConditionalFieldExample,
1617
ConditionalPageExample,
18+
DynamicAnswersQuestionsExample,
1719
FieldSlotExample,
1820
SimpleExample,
1921
SummaryPageExample,

src/documentation/sections/ExampleSection.vue

+14-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
</h2>
1414
</v-col>
1515

16-
1716
<ExampleContainer
1817
:code="getTemplateCode('SimpleExampleRef')"
1918
:codeBlockSettings="codeBlockSettings"
@@ -116,6 +115,17 @@
116115
:open="refElementsOpen.ConditionalFieldExampleRef"
117116
/>
118117
</ExampleContainer>
118+
119+
<ExampleContainer
120+
:code="getTemplateCode('DynamicAnswersQuestionsExampleRef')"
121+
:codeBlockSettings="codeBlockSettings"
122+
@closePicker="closePicker('DynamicAnswersQuestionsExampleRef');"
123+
>
124+
<Example.DynamicAnswersQuestionsExample
125+
ref="DynamicAnswersQuestionsExampleRef"
126+
:open="refElementsOpen.DynamicAnswersQuestionsExampleRef"
127+
/>
128+
</ExampleContainer>
119129
</v-row>
120130
</template>
121131

@@ -136,6 +146,7 @@ const ConditionalFieldExampleRef = ref(null);
136146
const ConditionalPageExampleRef = ref(null);
137147
const SummaryPageExampleRef = ref(null);
138148
const TooltipExampleRef = ref(null);
149+
const DynamicAnswersQuestionsExampleRef = ref(null);
139150
140151
const ButtonsFieldExampleRef = ref(null);
141152
const ButtonsFieldExampleCode = ref();
@@ -145,6 +156,7 @@ const refElements = ref({
145156
ColumnsExampleRef,
146157
ConditionalFieldExampleRef,
147158
ConditionalPageExampleRef,
159+
DynamicAnswersQuestionsExampleRef,
148160
FieldSlotExampleRef,
149161
SimpleExampleRef,
150162
SummaryPageExampleRef,
@@ -157,6 +169,7 @@ const refElementsOpen = ref({
157169
ColumnsExampleRef: null,
158170
ConditionalFieldExampleRef: null,
159171
ConditionalPageExampleRef: null,
172+
DynamicAnswersQuestionsExampleRef: null,
160173
FieldSlotExampleRef: null,
161174
SimpleExampleRef: null,
162175
SummaryPageExampleRef: null,

0 commit comments

Comments
 (0)