primevue-mirror/doc/steps/InteractiveDoc.vue

544 lines
19 KiB
Vue

<template>
<DocSectionText v-bind="$attrs">
<p>In order to add interactivity to the component, disable <i>readonly</i> to control the Steps.</p>
</DocSectionText>
<div class="card">
<Steps :model="items" aria-label="Form Steps">
<template #item="{ label, item, index, props }">
<router-link v-if="item.route" v-slot="routerProps" :to="item.route" custom>
<a :href="routerProps.href" v-bind="props.action" @click="($event) => routerProps.navigate($event)" @keydown.enter="($event) => routerProps.navigate($event)">
<span v-bind="props.step">{{ index + 1 }}</span>
<span v-bind="props.label">{{ label }}</span>
</a>
</router-link>
</template>
</Steps>
</div>
<NuxtPage v-slot="{ Component }" :formData="formObject" @prev-page="prevPage($event)" @next-page="nextPage($event)" @complete="complete">
<keep-alive>
<component :is="Component" />
</keep-alive>
</NuxtPage>
<br class="mt-4" />
<DocSectionCode :code="code" />
</template>
<script>
export default {
data() {
return {
items: [
{
label: 'Personal',
route: '/steps'
},
{
label: 'Seat',
route: '/steps/seat'
},
{
label: 'Payment',
route: '/steps/payment'
},
{
label: 'Confirmation',
route: '/steps/confirmation'
}
],
formObject: {},
code: {
basic: `<div class="card">
<Steps :model="items" aria-label="Form Steps">
<template #item="{ label, item, index, props }">
<router-link v-if="item.route" v-slot="routerProps" :to="item.route" custom>
<a :href="routerProps.href" v-bind="props.action" @click="($event) => routerProps.navigate($event)" @keydown.enter="($event) => routerProps.navigate($event)">
<span v-bind="props.step">{{ index + 1 }}</span>
<span v-bind="props.label">{{ label }}</span>
</a>
</router-link>
</template>
</Steps>
</div>
<router-view v-slot="{ Component }" :formData="formObject" @prev-page="prevPage($event)" @next-page="nextPage($event)" @complete="complete">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>`,
options: `<template>
<div>
<div class="card">
<Steps :model="items" aria-label="Form Steps">
<template #item="{ label, item, index, props }">
<router-link v-if="item.route" v-slot="routerProps" :to="item.route" custom>
<a :href="routerProps.href" v-bind="props.action" @click="($event) => routerProps.navigate($event)" @keydown.enter="($event) => routerProps.navigate($event)">
<span v-bind="props.step">{{ index + 1 }}</span>
<span v-bind="props.label">{{ label }}</span>
</a>
</router-link>
</template>
</Steps>
</div>
<Toast />
<router-view v-slot="{Component}" :formData="formObject" @prevPage="prevPage($event)" @nextPage="nextPage($event)" @complete="complete">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
</div>
</template>
<script>
export default {
data() {
return {
items: [
{
label: 'Personal',
route: '/'
},
{
label: 'Seat',
route: '/seat'
},
{
label: 'Payment',
route: '/payment'
},
{
label: 'Confirmation',
route: '/confirmation'
}
],
formObject: {}
}
},
methods: {
nextPage(event) {
for (let field in event.formData) {
this.formObject[field] = event.formData[field];
}
this.$router.push(this.items[event.pageIndex + 1].to);
},
prevPage(event) {
this.$router.push(this.items[event.pageIndex - 1].to);
},
complete() {
this.$toast.add({severity:'success', summary:'Order submitted', detail: 'Dear, ' + this.formObject.firstname + ' ' + this.formObject.lastname + ' your order completed.'});
}
}
}
<\/script>
<style scoped>
::v-deep(b) {
display: block;
}
::v-deep(.p-card-body) {
padding: 2rem;
}
</style>`,
composition: `<template>
<div>
<div class="card">
<Steps :model="items" aria-label="Form Steps">
<template #item="{ label, item, index, props }">
<router-link v-if="item.route" v-slot="routerProps" :to="item.route" custom>
<a :href="routerProps.href" v-bind="props.action" @click="($event) => routerProps.navigate($event)" @keydown.enter="($event) => routerProps.navigate($event)">
<span v-bind="props.step">{{ index + 1 }}</span>
<span v-bind="props.label">{{ label }}</span>
</a>
</router-link>
</template>
</Steps>
</div>
<Toast />
<router-view v-slot="{Component}" :formData="formObject" @prevPage="prevPage($event)" @nextPage="nextPage($event)" @complete="complete">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
</div>
</template>
<script setup>
import { ref } from "vue";
import { useRouter } from "vue-router";
import { useToast } from "primevue/usetoast";
const router = useRouter();
const toast = useToast();
const items = ref([
{
label: 'Personal',
route: "/"
},
{
label: 'Seat',
route: "/seat",
},
{
label: 'Payment',
route: "/payment",
},
{
label: 'Confirmation',
route: "/confirmation",
}
]);
const formObject = ref({});
const nextPage = (event) => {
for (let field in event.formData) {
formObject.value[field] = event.formData[field];
}
router.push(items.value[event.pageIndex + 1].to);
};
const prevPage = (event) => {
router.push(items.value[event.pageIndex - 1].to);
};
const complete = () => {
toast.add({severity:'success', summary:'Order submitted', detail: 'Dear, ' + formObject.value.firstname + ' ' + formObject.value.lastname + ' your order completed.'});
};
<\/script>
<style scoped>
::v-deep(b) {
display: block;
}
::v-deep(.p-card-body) {
padding: 2rem;
}
</style>`,
pages: [
{
tabName: 'PersonalDemo',
content: `
<template>
<div class="stepsdemo-content">
<Card>
<template v-slot:title>
Personal Information
</template>
<template v-slot:subtitle>
Enter your personal information
</template>
<template v-slot:content>
<div class="p-fluid">
<div class="field">
<label for="firstname">Firstname</label>
<InputText id="firstname" v-model="firstname" :class="{'p-invalid': validationErrors.firstname && submitted}" />
<small v-show="validationErrors.firstname && submitted" class="p-error">Firstname is required.</small>
</div>
<div class="field">
<label for="lastname">Lastname</label>
<InputText id="lastname" v-model="lastname" :class="{'p-invalid': validationErrors.lastname && submitted}" />
<small v-show="validationErrors.lastname && submitted" class="p-error">Lastname is required.</small>
</div>
<div class="field">
<label for="age">Age</label>
<InputNumber id="age" v-model="age" />
</div>
</div>
</template>
<template v-slot:footer>
<div class="grid grid-nogutter justify-content-between">
<i></i>
<Button label="Next" @click="nextPage()" icon="pi pi-angle-right" iconPos="right" />
</div>
</template>
</Card>
</div>
</template>
<script>
export default {
data () {
return {
firstname: '',
lastname: '',
age: null,
submitted: false,
validationErrors: {}
}
},
methods: {
nextPage() {
this.submitted = true;
if (this.validateForm() ) {
this.$emit('next-page', {formData: {firstname: this.firstname, lastname: this.lastname, age: this.age}, pageIndex: 0});
}
},
validateForm() {
if (!this.firstname.trim())
this.validationErrors['firstname'] = true;
else
delete this.validationErrors['firstname'];
if (!this.lastname.trim())
this.validationErrors['lastname'] = true;
else
delete this.validationErrors['lastname'];
return !Object.keys(this.validationErrors).length;
}
}
}
<\/script>
`
},
{
tabName: 'SeatDemo',
content: `
<template>
<div class="stepsdemo-content">
<Card>
<template v-slot:title>
Seat Information
</template>
<template v-slot:subtitle>
Choose your seat
</template>
<template v-slot:content>
<div class="p-fluid formgrid grid">
<div class="field col-12 md:col-6">
<label for="class">Class</label>
<Dropdown inputId="class" v-model="selectedClass" :options="classes" @change="setVagons($event)" optionLabel="name" placeholder="Select a Class" />
</div>
<div class="field col-12 md:col-6">
<label for="lastname">Wagon</label>
<Dropdown inputId="wagon" v-model="selectedVagon" :options="vagons" @change="setSeats($event)" optionLabel="vagon" placeholder="Select a Vagon" />
</div>
<div class="field col-12">
<label for="seat">Seat</label>
<Dropdown inputId="seat" v-model="selectedSeat" :options="seats" optionLabel="seat" placeholder="Select a Seat" />
</div>
</div>
</template>
<template v-slot:footer>
<div class="grid grid-nogutter justify-content-between">
<Button label="Back" @click="prevPage()" icon="pi pi-angle-left" />
<Button label="Next" @click="nextPage()" icon="pi pi-angle-right" iconPos="right" />
</div>
</template>
</Card>
</div>
</template>
<script>
export default {
data () {
return {
selectedClass: '',
classes: [
{name: 'First Class', code: 'A', factor: 1},
{name: 'Second Class', code: 'B', factor: 2},
{name: 'Third Class', code: 'C', factor: 3}
],
vagons: [],
selectedVagon: '',
seats: [],
selectedSeat: ''
}
},
methods: {
setVagons(event) {
if (this.selectedClass && event.value) {
this.vagons = [];
this.seats = [];
for (let i = 1; i < 3 * event.value.factor; i++) {
this.vagons.push({vagon: i + event.value.code, type: event.value.name, factor: event.value.factor});
}
}
},
setSeats(event) {
if (this.selectedVagon && event.value) {
this.seats = [];
for (let i = 1; i < 10 * event.value.factor; i++) {
this.seats.push({seat: i, type: event.value.type});
}
}
},
nextPage() {
this.$emit('next-page', {formData: {class: this.selectedClass.name, vagon: this.selectedVagon.vagon, seat: this.selectedSeat.seat}, pageIndex: 1});
},
prevPage() {
this.$emit('prev-page', {pageIndex: 1});
}
}
}
<\/script>
`
},
{
tabName: 'PaymentDemo',
content: `
<template>
<div class="stepsdemo-content">
<Card>
<template v-slot:title>
Payment Information
</template>
<template v-slot:subtitle>
Enter your card details
</template>
<template v-slot:content>
<div class="p-fluid formgrid grid">
<div class="field col-12">
<label for="class">Card Holder Name</label>
<InputText type="text" v-model="cardholderName" />
</div>
<div class="field col-8">
<label id="number" for="lastname">Number</label>
<InputMask id="number" mask="9999-9999-9999-9999" v-model="cardholderNumber" />
</div>
<div class="field col-2">
<label id="date" for="date">Date</label>
<InputMask id="date" mask="99/99" v-model="date" />
</div>
<div class="field col-2">
<label for="cvv">CVV</label>
<InputMask id="cvv" mask="999" v-model="cvv" />
</div>
<div class="field-checkbox col-12">
<Checkbox id="remember" v-model="remember" :binary="true" />
<label for="remember" class="p-checkbox-label">Save credit card information for future</label>
</div>
</div>
</template>
<template v-slot:footer>
<div class="grid grid-nogutter justify-content-between">
<Button label="Back" @click="prevPage()" icon="pi pi-angle-left" />
<Button label="Next" @click="nextPage()" icon="pi pi-angle-right" iconPos="right" />
</div>
</template>
</Card>
</div>
</template>
<script>
export default {
data () {
return {
cardholderName:'',
cardholderNumber:'',
date:'',
cvv:'',
remember:false
}
},
methods: {
nextPage() {
this.$emit('next-page', {formData: {cardholderName: this.cardholderName, cardholderNumber: this.cardholderNumber, date: this.date, cvv: this.cvv}, pageIndex: 2});
},
prevPage() {
this.$emit('prev-page', {pageIndex: 2});
}
}
}
<\/script>
`
},
{
tabName: 'ConfirmationDemo',
content: `
<template>
<div class="stepsdemo-content">
<Card>
<template v-slot:title>
Confirmation
</template>
<template v-slot:content>
<div class="field col-12">
<label for="class">Name</label>
<b>{{formData.firstname ? formData.firstname : '-'}} {{formData.lastname ? formData.lastname : '-'}}</b>
</div>
<div class="field col-12">
<label for="Age">Age</label>
<b>{{formData.age ? formData.age : '-'}}</b>
</div>
<div class="field col-12">
<label for="Age">Seat Class</label>
<b>{{formData.class ? formData.class : '-'}}</b>
</div>
<div class="field col-12">
<label for="Age">Wagon Number</label>
<b>{{formData.vagon ? formData.vagon : '-'}}</b>
</div>
<div class="field col-12">
<label for="Age">Seat</label>
<b>{{formData.seat ? formData.seat : '-'}}</b>
</div>
<div class="field col-12">
<label for="Age">Cardholder Name</label>
<b>{{formData.cardholderName ? formData.cardholderName : '-'}}</b>
</div>
<div class="field col-12">
<label for="Age">Card Number</label>
<b>{{formData.cardholderNumber ? formData.cardholderNumber : '-'}}</b>
</div>
<div class="field col-12">
<label for="Age">Date</label>
<b>{{formData.date ? formData.date : '-'}}</b>
</div>
<div class="field col-12">
<label for="Age">CVV</label>
<b>{{formData.cvv && formData.cvv.length === 3 ? '**' + formData.cvv[2] : '-'}}</b>
</div>
</template>
<template v-slot:footer>
<div class="grid grid-nogutter justify-content-between">
<Button label="Back" @click="prevPage()" icon="pi pi-angle-left" />
<Button label="Complete" @click="complete()" icon="pi pi-check" iconPos="right" class="p-button-success"/>
</div>
</template>
</Card>
</div>
</template>
<script>
export default {
props: {
formData: Object
},
methods: {
prevPage() {
this.$emit('prev-page', {pageIndex: 3});
},
complete() {
this.$emit('complete');
}
}
}
<\/script>
`
}
]
}
};
},
methods: {
nextPage(event) {
for (let field in event.formData) {
this.formObject[field] = event.formData[field];
}
this.$router.push(this.items[event.pageIndex + 1].to);
},
prevPage(event) {
this.$router.push(this.items[event.pageIndex - 1].to);
},
complete() {
this.$toast.add({ severity: 'success', summary: 'Order submitted', detail: 'Dear, ' + this.formObject.firstname + ' ' + this.formObject.lastname + ' your order completed.' });
}
}
};
</script>