SlideShare a Scribd company logo
Vue.js - Zastosowanie i budowa
komponentów
Amadeusz Kozłowski
Front End Developer
amadeuszkozlowski@gmail.com
#1 - Tree organized
#2 - Single - file component
<template>
<div v-if=”isActive”>
{{ message }}
</div>
</template>
<script>
export default {
props: [],
data() {
return {
isActive: ‘false’,
message:
‘lorem’,
}
},
methods: {
}
}
</script>
Vue.component('stepper-form',
require('./components/StepperForm.vue'));
const app = new Vue({
el: '#app'
});
#3 - Props
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<h3>My journey with Vue</h3>
<h3>Blogging with Vue</h3>
#3 - Props
Vue.component('blog-post', {
props: ['title'],
props: {
title: {
default: 'Lorem title',
type: String
}
},
template: '<h3>{{ title }}</h3>'
})
<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post></blog-post>
<h3>My journey with Vue</h3>
<h3>Blogging with Vue</h3>
<h3>Lorem title</h3>
#4 - v-for
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"
></blog-post>
v-bind: = :
#5 - Events
<button v-on:click="$emit('enlarge-text', 2)">
Enlarge text
</button>
<blog-post
...
v-on:enlarge-text="postFontSize += $event"
></blog-post>
v-on: = @
#6 - v-model
<input v-model="searchText">
does the same thing as:
<input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value"
>
#7 - Slots
Vue.component('alert-box', {
template: `
<div class="demo-alert-
box">
<slot></slot>
</div>`
})
<alert-box>
Something bad happened.
</alert-box>
<div class="demo-alert-box">
Something bad happened.
</div>
#8 - Form Stepper
#9 - Blade + Design <div class="container py-8" id="app">
<div class="w-full">
<div class="border border-grey p-4 text-right mb-8 lg:mb-0">
<button class="btn btn--black mr-4 w-24">Powrót</button>
<button class="btn btn--green w-24">Dalej</button>
<button class="btn btn--red w-24">Wyślij</button>
</div>
<div class="flex flex-col lg:flex-row items-center w-full justify-between lg:py-8">
<ul class="steps flex items-center justify-center flex-col mb-8 lg:mb-0 h-screen/2">
<li class="step line done cursor-pointer"><span>1</span></li>
<li class="step line active"><span>2</span></li>
<li class="step pointer-events-none"><span>3</span></li>
</ul>
<div class="lg:mr-auto lg:ml-8">
<form action="/">
<div>
<h2 class="mb-4">Krok 1</h2>
<div class="grid grid-columns-1 grid-gap-8">
<label class="font-bold" for="name">Imię*
<input class="mt-2 w-full" type="text" name="name" id="name">
</label>
<label class="font-bold" for="second_name">Nazwisko*
<input class="mt-2 w-full" type="text" name="second_name"
id="second_name">
</label>
</div>
</div>
</form>
</div>
<div class="mb-8 lg:mb-0 lg:w-64 lg:ml-8">
<img src="{{ asset('images/Vue.jpg') }}" alt="">
</div>
</div>
</div>
</div>
#9 - Blade + Design <div class="container py-8" id="app">
<div class="w-full">
<div class="border border-grey p-4 text-right mb-8 lg:mb-0">
<button class="btn btn--black mr-4 w-24">Powrót</button>
<button class="btn btn--green w-24">Dalej</button>
<button class="btn btn--red w-24">Wyślij</button>
</div>
<div class="flex flex-col lg:flex-row items-center w-full justify-between lg:py-8">
<ul class="steps flex items-center justify-center flex-col mb-8 lg:mb-0 h-screen/2">
<li class="step line done cursor-pointer"><span>1</span></li>
<li class="step line active"><span>2</span></li>
<li class="step pointer-events-none"><span>3</span></li>
</ul>
<div class="lg:mr-auto lg:ml-8">
<form action="/">
<div>
<h2 class="mb-4">Krok 1</h2>
<div class="grid grid-columns-1 grid-gap-8">
<label class="font-bold" for="name">Imię*
<input class="mt-2 w-full" type="text" name="name" id="name">
</label>
<label class="font-bold" for="second_name">Nazwisko*
<input class="mt-2 w-full" type="text" name="second_name"
id="second_name">
</label>
</div>
</div>
</form>
</div>
<div class="mb-8 lg:mb-0 lg:w-64 lg:ml-8">
<img src="{{ asset('images/Vue.jpg') }}" alt="">
</div>
</div>
</div>
</div>
#9 - Blade + Design
<div class="border border-grey p-4 text-right mb-8 lg:mb-0">
<button class="btn btn--black mr-4 w-24">Powrót</button>
<button class="btn btn--green w-24">Dalej</button>
<button class="btn btn--red w-24">Wyślij</button>
</div>
#9 - Blade + Design
<ul class="steps flex items-center justify-center flex-col mb-8 lg:mb-0 h-screen/2">
<li class="step line done cursor-pointer"><span>1</span></li>
<li class="step line active"><span>2</span></li>
<li class="step pointer-events-none"><span>3</span></li>
</ul>
#9 - Blade + Design
<div class="lg:mr-auto lg:ml-8">
<form action="/">
<div>
<h2 class="mb-4">Krok 1</h2>
<div class="grid grid-columns-1 grid-gap-8">
<label class="font-bold" for="name">Imię*
<input class="mt-2 w-full" type="text"
name="name" id="name">
</label>
<label class="font-bold" for="second_name">Nazwisko*
<input class="mt-2 w-full" type="text"
name="second_name" id="second_name">
</label>
</div>
</div>
</form>
</div>
#10 Vue <- Blade <div class="container py-8" id="app">
<div class="w-full">
<div class="border border-grey p-4 text-right mb-8 lg:mb-0">
<button class="btn btn--black mr-4 w-24">Powrót</button>
<button class="btn btn--green w-24">Dalej</button>
<button class="btn btn--red w-24">Wyślij</button>
</div>
<div class="flex flex-col lg:flex-row items-center w-full justify-between lg:py-8">
<ul class="steps flex items-center justify-center flex-col mb-8 lg:mb-0 h-screen/2">
<li class="step line done cursor-pointer"><span>1</span></li>
<li class="step line active"><span>2</span></li>
<li class="step pointer-events-none"><span>3</span></li>
</ul>
<div class="lg:mr-auto lg:ml-8">
<form action="/">
<div>
<h2 class="mb-4">Krok 1</h2>
<div class="grid grid-columns-1 grid-gap-8">
<label class="font-bold" for="name">Imię*
<input class="mt-2 w-full" type="text" name="name" id="name">
</label>
<label class="font-bold" for="second_name">Nazwisko*
<input class="mt-2 w-full" type="text" name="second_name"
id="second_name">
</label>
</div>
</div>
</form>
</div>
<div class="mb-8 lg:mb-0 lg:w-64 lg:ml-8">
<img src="{{ asset('images/Vue.jpg') }}" alt="">
</div>
</div>
</div>
</div>
<div class="container py-8" id="app">
<stepper-parent>
<div class="lg:mr-auto lg:ml-8">
<form action="/">
<stepper-form :active="true">
@include('form.form1')
</stepper-form>
<stepper-form>
@include('form.form2')
</stepper-form>
<stepper-form>
@include('form.form3')
</stepper-form>
</form>
</div>
<div class="mb-8 lg:mb-0 lg:w-64 lg:ml-8">
<img src="{{ asset('images/Vue.jpg') }}" alt="">
</div>
</stepper-parent>
</div>
#11 Using slot
<template>
<div class="w-full">
<div class="border border-grey p-4 text-right mb-8 lg:mb-0"
<button class="btn btn--black mr-4 w-24">Powrót</butto
<button class="btn btn--green w-24">Dalej</button>
<button class="btn btn--red w-24">Wyślij</button>
</div>
<div class="flex flex-col lg:flex-row items-center w-full
justify-between lg:py-8">
<ul class="steps flex items-center justify-center flex-col m
lg:mb-0 h-screen/2">
<li class="step line done cursor-pointer"><span>1</sp
<li class="step line active"><span>2</span></li>
<li class="step pointer-events-none"><span>3</span>
</ul>
<slot></slot>
</div>
</div>
</template>
<div class="container py-8" id="app">
<stepper-parent>
<div class="lg:mr-auto lg:ml-8">
<form action="/">
<stepper-form :active="true">
@include('form.form1')
</stepper-form>
<stepper-form>
@include('form.form2')
</stepper-form>
<stepper-form>
@include('form.form3')
</stepper-form>
</form>
</div>
<div class="mb-8 lg:mb-0 lg:w-64 lg:ml-8">
<img src="{{ asset('images/Vue.jpg') }}" alt="">
</div>
</stepper-parent>
</div>
#12 - https://baianat.github.io/vee-validate/
VeeValidate
Input validation for Vue.js
#12 - https://baianat.github.io/vee-validate/
<h2 class="mb-4">Krok 1</h2>
<div class="grid grid-columns-1 grid-gap-8">
<label class="font-bold" for="name">Imię*
<input v-validate="'required'" class="mt-2 w-full" v-model="form.name" type="text"
name="name"
id="name">
<p v-show="errors.has('name')" class="text-green text-xs mt-2 md:absolute">@{{ errors.first('name') }}</p>
</label>
<label class="font-bold" for="second_name">Nazwisko*
<input v-validate="'required'" class="mt-2 w-full" v-model="form.secondName" type="text"
name="second_name"
id="second_name">
<p v-show="errors.has('second_name')"
class="text-green text-xs mt-2 md:absolute">@{{ errors.first('second_name') }}</p>
</label>
</div>
#13 - [stepper-form] init empty
<template>
<div>
<slot></slot>
</div>
</template>
<div class="container py-8" id="app">
<stepper-parent>
<div class="lg:mr-auto lg:ml-8">
<form action="/">
<stepper-form :active="true">
@include('form.form1')
</stepper-form>
<stepper-form>
@include('form.form2')
</stepper-form>
<stepper-form>
@include('form.form3')
</stepper-form>
</form>
</div>
<div class="mb-8 lg:mb-0 lg:w-64 lg:ml-8">
<img src="{{ asset('images/Vue.jpg') }}" alt="">
</div>
</stepper-parent>
</div>
#14 - [app.js] init components
require('./bootstrap');
window.Vue = require('vue');
Vue.component('stepper-parent', require('./components/StepperParent.vue'));
Vue.component('stepper-form', require('./components/StepperForm.vue'));
import VeeValidate from 'vee-validate';
Vue.use(VeeValidate);
const app = new Vue({
data: {
form: {},
},
el: '#app'
});
Vue.js - zastosowanie i budowa komponentów
#15 - [stepper-form] displaying steps
<template>
<transition name="slide" mode="in-out">
<div v-if="isActive">
<slot></slot>
</div>
</transition>
</template>
<script>
export default {
props: {
active: {
default: false,
type: Boolean,
}
},
#15 - [stepper-form] displaying steps
data() {
return {
isActive: false,
}
},
methods: {
open() {
this.isActive = true;
},
close() {
this.isActive = false;
},
toggle() {
return this.isActive ? this.close() : this.open();
}
},
mounted() {
if (this.active) {
this.open();
}
}
}
</script>
#16 - Animations
<style>
.slide-enter-active, .slide-leave-active {
transition: all .5s;
}
.slide-enter, .slide-leave-to
{
opacity: 0;
height: 0;
transform: translateX(100px) scale(0.1) rotate(-15deg);
}
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to
{
opacity: 0;
}
</style>
Vue.js - zastosowanie i budowa komponentów
#17 - [stepper-parent] init data
data() {
return {
totalSteps: 0,
actualStep: 1,
validated: 1,
}
},
mounted() {
this.totalSteps = this.$children.length;
}
#17 - [stepper-parent] init data
#17 - [stepper-parent] dynamic steps
<li v-for="step in totalSteps" :key="step"
class="step" @click="goToStep(step)"
:class="{ active: step === actualStep,
line: step < totalSteps,
'done cursor-pointer': step < actualStep || step <= validated,
'pointer-events-none': step > validated }">
<span>{{ step }}</span>
</li>
<ul class="steps flex items-center justify-center flex-col mb-8 lg:mb-0 h-screen/2">
<li class="step line done cursor-pointer"><span>1</span></li>
<li class="step line active"><span>2</span></li>
<li class="step pointer-events-none"><span>3</span></li>
</ul>
Aby odtworzyć film kliknij tutaj
#18 - [stepper-parent] dynamic buttons
<transition name="fade" mode="in-out">
<button v-show="actualStep !== 1"
class="btn btn--black mr-4 w-24"
@click="backStep">Powrót</button>
</transition>
<button :class="{'btn--green': actualStep < totalSteps,
'btn--red': actualStep === totalSteps,}"
class="btn w-24"
@click="nextButtonAction">
{{ actualStep < totalSteps ? 'Dalej' : 'Wyślij' }}
</button>
#19 - [stepper-parent] next prev logic
nextStep() {
this.goToStep(this.actualStep + 1);
if (this.actualStep > this.validated) {
this.validated++;
}
},
backStep() {
this.goToStep(this.actualStep - 1);
},
goToStep(step) {
this.$children[this.actualStep - 1].close();
this.actualStep = step;
let $this = this;
setTimeout(function () {
$this.$children[$this.actualStep - 1].open();
}, 500);
},
#19 - [stepper-parent] next prev logic
nextButtonAction() {
this.$parent.$validator.validate().then(result => {
if (!result) {
// invalid
return null;
}
else {
// valid
if (this.actualStep < this.totalSteps) {
return this.nextStep();
}
else {
return this.submit();
}
}
});
},
submit() {
alert(JSON.stringify(this.$parent.form, null, 4));
},
Aby odtworzyć film kliknij tutaj
Aby odtworzyć film kliknij tutaj
#20 - v-cloak
<stepper-parent>
<div class="lg:mr-auto lg:ml-8" v-cloak>
<form action="/">
<stepper-form :active="true">
@include('form.form1')
</stepper-form>
<stepper-form>
@include('form.form2')
</stepper-form>
<stepper-form>
@include('form.form3')
</stepper-form>
</form>
</div>
<div class="mb-8 lg:mb-0 lg:w-64 lg:ml-8">
<img src="{{ asset('images/Vue.jpg') }}" alt="">
</div>
</stepper-parent>
[v-cloak] {
display: none;
}
Aby odtworzyć film kliknij tutaj
Amadeusz Kozłowski
amadeuszkozlowski@gmail.com

More Related Content

PDF
QCon 2015 - Thinking in components: A new paradigm for Web UI
PDF
Desenvolvimento web com Ruby on Rails (parte 6)
PDF
Django Templates
PDF
Django Bogotá. CBV
PDF
Ch9 .Best Practices for Class-Based Views
PDF
Master AngularJS
PDF
WordPress Admin UI - Future Proofing Your Admin Pages
PPTX
jQuery Mobile Introduction ( demo on EZoapp )
QCon 2015 - Thinking in components: A new paradigm for Web UI
Desenvolvimento web com Ruby on Rails (parte 6)
Django Templates
Django Bogotá. CBV
Ch9 .Best Practices for Class-Based Views
Master AngularJS
WordPress Admin UI - Future Proofing Your Admin Pages
jQuery Mobile Introduction ( demo on EZoapp )

What's hot (20)

PDF
2012.sandiego.wordcamp
PDF
Data binding 入門淺談
PDF
jQuery Mobile: Progressive Enhancement with HTML5
PDF
Angular js quickstart
PDF
Knockout mvvm-m5-slides
PPTX
Client Web
PDF
Bootstrap 3 Cheat Sheet PDF Reference
PDF
W3C XBL 2.0 and Widgets 1.0
PDF
Stripes Framework
PPT
jQuery Mobile with HTML5
PDF
Unlock the next era of UI design with Polymer
PDF
22 j query1
PDF
Django class based views for beginners
PDF
Advanced JQuery Mobile tutorial with Phonegap
PPTX
Why Django for Web Development
PDF
Polymer
PDF
Hastening React SSR - Web Performance San Diego
PDF
Building iPhone Web Apps using "classic" Domino
PPTX
Big Data for each one of us
PDF
Jinja2 Templates - San Francisco Flask Meetup
2012.sandiego.wordcamp
Data binding 入門淺談
jQuery Mobile: Progressive Enhancement with HTML5
Angular js quickstart
Knockout mvvm-m5-slides
Client Web
Bootstrap 3 Cheat Sheet PDF Reference
W3C XBL 2.0 and Widgets 1.0
Stripes Framework
jQuery Mobile with HTML5
Unlock the next era of UI design with Polymer
22 j query1
Django class based views for beginners
Advanced JQuery Mobile tutorial with Phonegap
Why Django for Web Development
Polymer
Hastening React SSR - Web Performance San Diego
Building iPhone Web Apps using "classic" Domino
Big Data for each one of us
Jinja2 Templates - San Francisco Flask Meetup
Ad

More from Laravel Poland MeetUp (20)

PDF
WebRTC+Websockety - Jak stworzyłem aplikację do kamerek internetowych w Larav...
PDF
xD bug - Jak debugować PHP-owe aplikacje (Xdebug)
PDF
Kilka slajdów o castowaniu atrybutów w Eloquent
PDF
Licencje otwartego oprogramowania
PDF
Jak przyspieszyłem aplikację produkcyjną o ponad 40%
PDF
Jak przemycić Shape Up do Scruma?
PDF
Cykl życia zapytania HTTP (pod maską)
PDF
Enumy w Laravelu - dlaczego warto stosować?
PDF
Laravelowe paczki do uwierzytelniania
PDF
Przegląd najciekawszych wtyczek do Laravela
PDF
Walidacja w Laravelu
PDF
(prawie) Wszystko o Tinkerze
PDF
Laravel Dusk - prosty przepis na testy E2E
PDF
Laravel Octane - czy na pewno taki szybki?
PDF
Laravel Jobs i PHP8
PDF
Wszystko o Laravel Livewire
PDF
Laravel/PHP - zderzenie z PDFami
PDF
Action-based Laravel
PDF
Automatyzacja utrzymania jakości w środowisku PHP
PDF
Wstęp do Gitlab CI/CD w aplikacjach napisanych w Laravel
WebRTC+Websockety - Jak stworzyłem aplikację do kamerek internetowych w Larav...
xD bug - Jak debugować PHP-owe aplikacje (Xdebug)
Kilka slajdów o castowaniu atrybutów w Eloquent
Licencje otwartego oprogramowania
Jak przyspieszyłem aplikację produkcyjną o ponad 40%
Jak przemycić Shape Up do Scruma?
Cykl życia zapytania HTTP (pod maską)
Enumy w Laravelu - dlaczego warto stosować?
Laravelowe paczki do uwierzytelniania
Przegląd najciekawszych wtyczek do Laravela
Walidacja w Laravelu
(prawie) Wszystko o Tinkerze
Laravel Dusk - prosty przepis na testy E2E
Laravel Octane - czy na pewno taki szybki?
Laravel Jobs i PHP8
Wszystko o Laravel Livewire
Laravel/PHP - zderzenie z PDFami
Action-based Laravel
Automatyzacja utrzymania jakości w środowisku PHP
Wstęp do Gitlab CI/CD w aplikacjach napisanych w Laravel
Ad

Recently uploaded (20)

PDF
medical staffing services at VALiNTRY
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PDF
PTS Company Brochure 2025 (1).pdf.......
PPTX
Transform Your Business with a Software ERP System
PDF
Digital Systems & Binary Numbers (comprehensive )
PDF
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
PPTX
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPTX
assetexplorer- product-overview - presentation
PDF
Designing Intelligence for the Shop Floor.pdf
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
iTop VPN Free 5.6.0.5262 Crack latest version 2025
PPTX
Introduction to Artificial Intelligence
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PDF
Nekopoi APK 2025 free lastest update
medical staffing services at VALiNTRY
Odoo Companies in India – Driving Business Transformation.pdf
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PTS Company Brochure 2025 (1).pdf.......
Transform Your Business with a Software ERP System
Digital Systems & Binary Numbers (comprehensive )
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
wealthsignaloriginal-com-DS-text-... (1).pdf
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
Navsoft: AI-Powered Business Solutions & Custom Software Development
assetexplorer- product-overview - presentation
Designing Intelligence for the Shop Floor.pdf
Operating system designcfffgfgggggggvggggggggg
iTop VPN Free 5.6.0.5262 Crack latest version 2025
Introduction to Artificial Intelligence
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
Nekopoi APK 2025 free lastest update

Vue.js - zastosowanie i budowa komponentów

  • 1. Vue.js - Zastosowanie i budowa komponentów
  • 2. Amadeusz Kozłowski Front End Developer amadeuszkozlowski@gmail.com
  • 3. #1 - Tree organized
  • 4. #2 - Single - file component <template> <div v-if=”isActive”> {{ message }} </div> </template> <script> export default { props: [], data() { return { isActive: ‘false’, message: ‘lorem’, } }, methods: { } } </script> Vue.component('stepper-form', require('./components/StepperForm.vue')); const app = new Vue({ el: '#app' });
  • 5. #3 - Props Vue.component('blog-post', { props: ['title'], template: '<h3>{{ title }}</h3>' }) <blog-post title="My journey with Vue"></blog-post> <blog-post title="Blogging with Vue"></blog-post> <h3>My journey with Vue</h3> <h3>Blogging with Vue</h3>
  • 6. #3 - Props Vue.component('blog-post', { props: ['title'], props: { title: { default: 'Lorem title', type: String } }, template: '<h3>{{ title }}</h3>' }) <blog-post title="My journey with Vue"></blog-post> <blog-post title="Blogging with Vue"></blog-post> <blog-post></blog-post> <h3>My journey with Vue</h3> <h3>Blogging with Vue</h3> <h3>Lorem title</h3>
  • 7. #4 - v-for <blog-post v-for="post in posts" v-bind:key="post.id" v-bind:title="post.title" ></blog-post> v-bind: = :
  • 8. #5 - Events <button v-on:click="$emit('enlarge-text', 2)"> Enlarge text </button> <blog-post ... v-on:enlarge-text="postFontSize += $event" ></blog-post> v-on: = @
  • 9. #6 - v-model <input v-model="searchText"> does the same thing as: <input v-bind:value="searchText" v-on:input="searchText = $event.target.value" >
  • 10. #7 - Slots Vue.component('alert-box', { template: ` <div class="demo-alert- box"> <slot></slot> </div>` }) <alert-box> Something bad happened. </alert-box> <div class="demo-alert-box"> Something bad happened. </div>
  • 11. #8 - Form Stepper
  • 12. #9 - Blade + Design <div class="container py-8" id="app"> <div class="w-full"> <div class="border border-grey p-4 text-right mb-8 lg:mb-0"> <button class="btn btn--black mr-4 w-24">Powrót</button> <button class="btn btn--green w-24">Dalej</button> <button class="btn btn--red w-24">Wyślij</button> </div> <div class="flex flex-col lg:flex-row items-center w-full justify-between lg:py-8"> <ul class="steps flex items-center justify-center flex-col mb-8 lg:mb-0 h-screen/2"> <li class="step line done cursor-pointer"><span>1</span></li> <li class="step line active"><span>2</span></li> <li class="step pointer-events-none"><span>3</span></li> </ul> <div class="lg:mr-auto lg:ml-8"> <form action="/"> <div> <h2 class="mb-4">Krok 1</h2> <div class="grid grid-columns-1 grid-gap-8"> <label class="font-bold" for="name">Imię* <input class="mt-2 w-full" type="text" name="name" id="name"> </label> <label class="font-bold" for="second_name">Nazwisko* <input class="mt-2 w-full" type="text" name="second_name" id="second_name"> </label> </div> </div> </form> </div> <div class="mb-8 lg:mb-0 lg:w-64 lg:ml-8"> <img src="{{ asset('images/Vue.jpg') }}" alt=""> </div> </div> </div> </div>
  • 13. #9 - Blade + Design <div class="container py-8" id="app"> <div class="w-full"> <div class="border border-grey p-4 text-right mb-8 lg:mb-0"> <button class="btn btn--black mr-4 w-24">Powrót</button> <button class="btn btn--green w-24">Dalej</button> <button class="btn btn--red w-24">Wyślij</button> </div> <div class="flex flex-col lg:flex-row items-center w-full justify-between lg:py-8"> <ul class="steps flex items-center justify-center flex-col mb-8 lg:mb-0 h-screen/2"> <li class="step line done cursor-pointer"><span>1</span></li> <li class="step line active"><span>2</span></li> <li class="step pointer-events-none"><span>3</span></li> </ul> <div class="lg:mr-auto lg:ml-8"> <form action="/"> <div> <h2 class="mb-4">Krok 1</h2> <div class="grid grid-columns-1 grid-gap-8"> <label class="font-bold" for="name">Imię* <input class="mt-2 w-full" type="text" name="name" id="name"> </label> <label class="font-bold" for="second_name">Nazwisko* <input class="mt-2 w-full" type="text" name="second_name" id="second_name"> </label> </div> </div> </form> </div> <div class="mb-8 lg:mb-0 lg:w-64 lg:ml-8"> <img src="{{ asset('images/Vue.jpg') }}" alt=""> </div> </div> </div> </div>
  • 14. #9 - Blade + Design <div class="border border-grey p-4 text-right mb-8 lg:mb-0"> <button class="btn btn--black mr-4 w-24">Powrót</button> <button class="btn btn--green w-24">Dalej</button> <button class="btn btn--red w-24">Wyślij</button> </div>
  • 15. #9 - Blade + Design <ul class="steps flex items-center justify-center flex-col mb-8 lg:mb-0 h-screen/2"> <li class="step line done cursor-pointer"><span>1</span></li> <li class="step line active"><span>2</span></li> <li class="step pointer-events-none"><span>3</span></li> </ul>
  • 16. #9 - Blade + Design <div class="lg:mr-auto lg:ml-8"> <form action="/"> <div> <h2 class="mb-4">Krok 1</h2> <div class="grid grid-columns-1 grid-gap-8"> <label class="font-bold" for="name">Imię* <input class="mt-2 w-full" type="text" name="name" id="name"> </label> <label class="font-bold" for="second_name">Nazwisko* <input class="mt-2 w-full" type="text" name="second_name" id="second_name"> </label> </div> </div> </form> </div>
  • 17. #10 Vue <- Blade <div class="container py-8" id="app"> <div class="w-full"> <div class="border border-grey p-4 text-right mb-8 lg:mb-0"> <button class="btn btn--black mr-4 w-24">Powrót</button> <button class="btn btn--green w-24">Dalej</button> <button class="btn btn--red w-24">Wyślij</button> </div> <div class="flex flex-col lg:flex-row items-center w-full justify-between lg:py-8"> <ul class="steps flex items-center justify-center flex-col mb-8 lg:mb-0 h-screen/2"> <li class="step line done cursor-pointer"><span>1</span></li> <li class="step line active"><span>2</span></li> <li class="step pointer-events-none"><span>3</span></li> </ul> <div class="lg:mr-auto lg:ml-8"> <form action="/"> <div> <h2 class="mb-4">Krok 1</h2> <div class="grid grid-columns-1 grid-gap-8"> <label class="font-bold" for="name">Imię* <input class="mt-2 w-full" type="text" name="name" id="name"> </label> <label class="font-bold" for="second_name">Nazwisko* <input class="mt-2 w-full" type="text" name="second_name" id="second_name"> </label> </div> </div> </form> </div> <div class="mb-8 lg:mb-0 lg:w-64 lg:ml-8"> <img src="{{ asset('images/Vue.jpg') }}" alt=""> </div> </div> </div> </div> <div class="container py-8" id="app"> <stepper-parent> <div class="lg:mr-auto lg:ml-8"> <form action="/"> <stepper-form :active="true"> @include('form.form1') </stepper-form> <stepper-form> @include('form.form2') </stepper-form> <stepper-form> @include('form.form3') </stepper-form> </form> </div> <div class="mb-8 lg:mb-0 lg:w-64 lg:ml-8"> <img src="{{ asset('images/Vue.jpg') }}" alt=""> </div> </stepper-parent> </div>
  • 18. #11 Using slot <template> <div class="w-full"> <div class="border border-grey p-4 text-right mb-8 lg:mb-0" <button class="btn btn--black mr-4 w-24">Powrót</butto <button class="btn btn--green w-24">Dalej</button> <button class="btn btn--red w-24">Wyślij</button> </div> <div class="flex flex-col lg:flex-row items-center w-full justify-between lg:py-8"> <ul class="steps flex items-center justify-center flex-col m lg:mb-0 h-screen/2"> <li class="step line done cursor-pointer"><span>1</sp <li class="step line active"><span>2</span></li> <li class="step pointer-events-none"><span>3</span> </ul> <slot></slot> </div> </div> </template> <div class="container py-8" id="app"> <stepper-parent> <div class="lg:mr-auto lg:ml-8"> <form action="/"> <stepper-form :active="true"> @include('form.form1') </stepper-form> <stepper-form> @include('form.form2') </stepper-form> <stepper-form> @include('form.form3') </stepper-form> </form> </div> <div class="mb-8 lg:mb-0 lg:w-64 lg:ml-8"> <img src="{{ asset('images/Vue.jpg') }}" alt=""> </div> </stepper-parent> </div>
  • 20. #12 - https://baianat.github.io/vee-validate/ <h2 class="mb-4">Krok 1</h2> <div class="grid grid-columns-1 grid-gap-8"> <label class="font-bold" for="name">Imię* <input v-validate="'required'" class="mt-2 w-full" v-model="form.name" type="text" name="name" id="name"> <p v-show="errors.has('name')" class="text-green text-xs mt-2 md:absolute">@{{ errors.first('name') }}</p> </label> <label class="font-bold" for="second_name">Nazwisko* <input v-validate="'required'" class="mt-2 w-full" v-model="form.secondName" type="text" name="second_name" id="second_name"> <p v-show="errors.has('second_name')" class="text-green text-xs mt-2 md:absolute">@{{ errors.first('second_name') }}</p> </label> </div>
  • 21. #13 - [stepper-form] init empty <template> <div> <slot></slot> </div> </template> <div class="container py-8" id="app"> <stepper-parent> <div class="lg:mr-auto lg:ml-8"> <form action="/"> <stepper-form :active="true"> @include('form.form1') </stepper-form> <stepper-form> @include('form.form2') </stepper-form> <stepper-form> @include('form.form3') </stepper-form> </form> </div> <div class="mb-8 lg:mb-0 lg:w-64 lg:ml-8"> <img src="{{ asset('images/Vue.jpg') }}" alt=""> </div> </stepper-parent> </div>
  • 22. #14 - [app.js] init components require('./bootstrap'); window.Vue = require('vue'); Vue.component('stepper-parent', require('./components/StepperParent.vue')); Vue.component('stepper-form', require('./components/StepperForm.vue')); import VeeValidate from 'vee-validate'; Vue.use(VeeValidate); const app = new Vue({ data: { form: {}, }, el: '#app' });
  • 24. #15 - [stepper-form] displaying steps <template> <transition name="slide" mode="in-out"> <div v-if="isActive"> <slot></slot> </div> </transition> </template> <script> export default { props: { active: { default: false, type: Boolean, } },
  • 25. #15 - [stepper-form] displaying steps data() { return { isActive: false, } }, methods: { open() { this.isActive = true; }, close() { this.isActive = false; }, toggle() { return this.isActive ? this.close() : this.open(); } }, mounted() { if (this.active) { this.open(); } } } </script>
  • 26. #16 - Animations <style> .slide-enter-active, .slide-leave-active { transition: all .5s; } .slide-enter, .slide-leave-to { opacity: 0; height: 0; transform: translateX(100px) scale(0.1) rotate(-15deg); } .fade-enter-active, .fade-leave-active { transition: opacity .5s; } .fade-enter, .fade-leave-to { opacity: 0; } </style>
  • 28. #17 - [stepper-parent] init data data() { return { totalSteps: 0, actualStep: 1, validated: 1, } }, mounted() { this.totalSteps = this.$children.length; }
  • 30. #17 - [stepper-parent] dynamic steps <li v-for="step in totalSteps" :key="step" class="step" @click="goToStep(step)" :class="{ active: step === actualStep, line: step < totalSteps, 'done cursor-pointer': step < actualStep || step <= validated, 'pointer-events-none': step > validated }"> <span>{{ step }}</span> </li> <ul class="steps flex items-center justify-center flex-col mb-8 lg:mb-0 h-screen/2"> <li class="step line done cursor-pointer"><span>1</span></li> <li class="step line active"><span>2</span></li> <li class="step pointer-events-none"><span>3</span></li> </ul>
  • 31. Aby odtworzyć film kliknij tutaj
  • 32. #18 - [stepper-parent] dynamic buttons <transition name="fade" mode="in-out"> <button v-show="actualStep !== 1" class="btn btn--black mr-4 w-24" @click="backStep">Powrót</button> </transition> <button :class="{'btn--green': actualStep < totalSteps, 'btn--red': actualStep === totalSteps,}" class="btn w-24" @click="nextButtonAction"> {{ actualStep < totalSteps ? 'Dalej' : 'Wyślij' }} </button>
  • 33. #19 - [stepper-parent] next prev logic nextStep() { this.goToStep(this.actualStep + 1); if (this.actualStep > this.validated) { this.validated++; } }, backStep() { this.goToStep(this.actualStep - 1); }, goToStep(step) { this.$children[this.actualStep - 1].close(); this.actualStep = step; let $this = this; setTimeout(function () { $this.$children[$this.actualStep - 1].open(); }, 500); },
  • 34. #19 - [stepper-parent] next prev logic nextButtonAction() { this.$parent.$validator.validate().then(result => { if (!result) { // invalid return null; } else { // valid if (this.actualStep < this.totalSteps) { return this.nextStep(); } else { return this.submit(); } } }); }, submit() { alert(JSON.stringify(this.$parent.form, null, 4)); },
  • 35. Aby odtworzyć film kliknij tutaj
  • 36. Aby odtworzyć film kliknij tutaj
  • 37. #20 - v-cloak <stepper-parent> <div class="lg:mr-auto lg:ml-8" v-cloak> <form action="/"> <stepper-form :active="true"> @include('form.form1') </stepper-form> <stepper-form> @include('form.form2') </stepper-form> <stepper-form> @include('form.form3') </stepper-form> </form> </div> <div class="mb-8 lg:mb-0 lg:w-64 lg:ml-8"> <img src="{{ asset('images/Vue.jpg') }}" alt=""> </div> </stepper-parent> [v-cloak] { display: none; }
  • 38. Aby odtworzyć film kliknij tutaj