Save yourself a ton of work on your next project

Check out are examples libraries to get the idea how Laraform will help your next project to gain amazing effectivity

1

Shopify-like checkout form made from scratch with Laraform

// Data model:

            
Checkout form in ~400 lines of code

Dealing with checkouts are usually quite challenging, because they require a ton of fields, multiple steps and lot of conditions. This example is here to illustrate that creating complex forms shouldn't be a mess when you are using Laraform. Get a simple and straightforward structure and customize whatever you need.

Laraform features used:
  • Form wizard which is used to break form fields into steps
  • Nested elements for creating element groups and fields next to each other
  • Validation with Laravel compatible validators
  • Searchable select field for countries and states
  • Input mask for phone number
  • Floating labels for each field
  • Custom elements to create summaries
  • Custom template for radio groups for shipping and payment
  • Custom theme made for Shopify design
  • Conditional values for shipping method based on selected country
  • Conditional fields to show states, credit card details, billing address fields and account creation options
ShopifyCheckoutForm.vue app.js checkout.blade.php
              
<script>

// Custom Elements (Vue Single File Components)
import SummaryElement from './../elements/SummaryElement'
import PaymentElement from './../elements/PaymentElement'

export default {
  mixins: [Laraform],
  data: () => ({

    // Defining form steps
    wizard: {

      // 1st step - 'Customer information'
      customer_information: {
        label: 'Customer information',
        elements: ['contact_information', 'shipping_address'],
        labels: {
          previous: ' ',
          next: 'Continue to shipping method'
        }
      },

      // 2nd step - 'Shipping method'
      shipping_method: {
        label: 'Shipping method',
        elements: ['shipping_summary', 'shipping_method'],
        labels: {
          previous: '< Return to customer information',
          next: 'Continue to payment method'
        }
      },

      // 3rd step - 'Payment method'
      payment_method: {
        label: 'Payment method',
        elements: ['payment_summary', 'payment_method', 'billing_address', 'remember_me', 'terms'],
        labels: {
          previous: '< Return to shipping method',
          finish: 'Complete order'
        }
      },
    },

    // Defining form elements
    schema: {

      // 'Contact information' (email)
      contact_information: {
        type: 'group',
        label: 'Contact information',
        schema: {
          email: {
            type: 'text',
            placeholder: 'Email',
            label: false,
            floating: 'Email',
            rules: 'required|email:debounce=300',
          },
          updates: {
            type: 'checkbox',
            label: false,
            text: 'Keep me up to date on news and exclusive offers',
          },
        }
      },

      // 'Shipping address' (name, company, address fields, phone)
      shipping_address: {
        type: 'group',
        label: 'Shipping address',
        schema: {
          firstname: {
            type: 'text',
            placeholder: 'First name (optional)',
            floating: 'First name (optional)',
            columns: 6
          },
          lastname: {
            type: 'text',
            placeholder: 'Last name',
            floating: 'Last name',
            rules: 'required',
            columns: 6
          },
          company: {
            type: 'text',
            floating: 'Company (optional)',
            placeholder: 'Company (optional)',
          },
          address: {
            type: 'text',
            floating: 'Address',
            placeholder: 'Address',
            rules: 'required'
          },
          address2: {
            type: 'text',
            floating: 'Apartment, suite, etc. (optional)',
            placeholder: 'Apartment, suite, etc. (optional)',
          },
          city: {
            type: 'text',
            floating: 'City',
            placeholder: 'City',
            rules: 'required'
          },
          country: {
            type: 'select',
            floating: 'Country',
            placeholder: 'Country',
            rules: 'required',
            items: {
              'de': 'Germany',
              'us': 'United States',
            },
            columns: 8,
            // Using custom event to update column width when country changes
            onChange() {
              this.updateColumns(this.value == 'us' ? 5 : 8)
              this.form$.el$('shipping_address.zip_code').updateColumns(this.value == 'us' ? 3 : 4)
            }
          },
          state: {
            type: 'select',
            floating: 'State',
            placeholder: 'State',
            columns: 4,
            items: states,
            rules: 'required',
            // Should only appear if the country is USA
            conditions: [
              ['shipping_address.country', 'us']
            ],
          },
          zip_code: {
            type: 'text',
            floating: 'ZIP Code',
            placeholder: 'ZIP Code',
            rules: 'required',
            columns: 4
          },
          phone: {
            type: 'text',
            floating: 'Phone',
            placeholder: 'Phone',
            rules: 'required',
            // Using some fancy text mask
            mask: ['(', /[1-9]/, /\d/, /\d/, ')', ' ', /\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/, /\d/],
          },
        }
      },

      // Shipping summary block with custom SummaryElement imported at top
      shipping_summary: {
        component: SummaryElement,
        items: ['contact', 'ship_to']
      },

      // 'Shipping method' - using custom template for checkboxes
      shipping_method: {
        type: 'radiogroup',
        label: 'Shipping method',
        before: '<span class="group-description">Please Note - Orders will be ship the next business day. Please add one shipping day to all estimates.</span>',
        items: shippingUS,
        rules: 'required',
        slots: {
          radio: Vue.extend({
            inject: ['theme'],
            props: ['el$', 'item', 'value'],
            template: `
              <div :class="theme.classes.radioContainer">
                <label 
                  :class="el$.theme.classes.radioLabel"
                  :for="value"
                >
                  <input
                    type="radio"
                    v-model="el$.model"
                    :value="value"
                    :class="el$.theme.classes.radio"
                    :name="el$.fieldName"
                    :id="value"
                    @change="el$.handleChange"
                  />
                  <span class="info">
                    <span class="left">
                      <span class="carrier">{{ item.carrier }}</span> 
                      <span class="delivery">{{ item.delivery_date }}</span>
                    </span>
                    <span class="price">{{ item.price }}</span>
                  </span>
                </label>
              </div>`
          })
        },
        mounted() {
          this.$nextTick(() => {
            var country = this.form$.el$('shipping_address.country')

            country.on('change', () => {
              this.items = country.value == 'us' ? shippingUS : shippingEU
            })
          })
        }
      },

      // Payment summary block with custom SummaryElement imported at top
      payment_summary: {
        component: SummaryElement,
        items: ['contact', 'ship_to', 'method']
      },

      // 'Payment method' block
      payment_method: {
        type: 'group',
        label: 'Payment method',
        class: 'payment-method',
        before: '<span class="group-description">All transactions are secure and encrypted.</span>',
        schema: {

          // 'Credit card' option
          credit_card: {
            type: 'radio',
            text: 'Credit card',
            fieldName:  'payment_method',
            after: '<span class="card-logos"></span>',
            rules: [
              {
                required: ['payment_method.paypal', null]
              }
            ],
            messages: {
              required: 'One payment method must be choosen.'
            }
          },

          // Credit card details (if selected)
          credit_card_details: {
            type: 'group',
            class: 'credit-card-details',
            // Only appears if credit card is selected
            conditions: [
              ['payment_method.credit_card', 1]
            ],
            // Defines its child elements for credit card info
            schema: {
              card_number: {
                type: 'text',
                floating: 'Card number',
                placeholder: 'Card number (do not provide actual card number)',
              },
              cardholder_name: {
                type: 'text',
                floating: 'Cardholder name',
                placeholder: 'Cardholder name',
                columns: 6
              },
              expiration: {
                type: 'text',
                floating: 'MM / YY',
                placeholder: 'MM / YY',
                columns: 3
              },
              cvv: {
                type: 'text',
                floating: 'CVV',
                placeholder: 'CVV',
                columns: 3
              },
            }
          },

          // 'Paypal' option
          paypal: {
            type: 'radio',
            text: ' ',
            class: 'paypal-payment',
            fieldName:  'payment_method',
            after: '<span class="card-logos only-3"></span>',
            rules: [
              {
                required: ['payment_method.credit_card', null]
              }
            ],
            messages: {
              required: 'One payment method must be choosen.'
            }
          },
          // Paypal info window (if selected)
          paypal_payment: {
            component: PaymentElement,
            text: 'After clicking "Complete order", you will be redirected to PayPal to complete your purchase securely.',
            // Only appears if 'credit card' is selected
            conditions: [
              ['payment_method.paypal', 1]
            ],
          },
        },
      },

      // 'Billing address' block
      billing_address: {
        type: 'object',
        label: 'Billing address',
        class: 'billing-address',
        schema: {
          same: {
            type: 'radio',
            text: 'Same as shipping address',
            fieldName:  'billing_address',
            rules: [
              {
                required: ['billing_address.different', null]
              }
            ],
            messages: {
              required: 'One billing address option must be choosen.'
            }
          },
          different: {
            type: 'radio',
            text: 'Use a different billing address',
            fieldName:  'billing_address',
            rules: [
              {
                required: ['billing_address.same', null]
              }
            ],
            messages: {
              required: 'One billing address option must be choosen.'
            }
          },

          // Billing info block (if 'use different is selected')
          billing_info: {
            type: 'group',
            class: 'billing-address-fields',
            // Only appears if 'different' is selected
            conditions: [
              ['billing_address.different', 1]
            ],
            // Defines its child elements for billing info
            schema: {
              firstname: {
                type: 'text',
                placeholder: 'First name (optional)',
                floating: 'First name (optional)',
                columns: 6,
              },
              lastname: {
                type: 'text',
                placeholder: 'Last name',
                floating: 'Last name',
                columns: 6,
                rules: 'required'
              },
              company: {
                type: 'text',
                placeholder: 'Company (optional)',
                floating: 'Company (optional)',
              },
              address: {
                type: 'text',
                placeholder: 'Address',
                floating: 'Address',
                rules: 'required'
              },
              address2: {
                type: 'text',
                placeholder: 'Apartment, suite, etc. (optional)',
                floating: 'Apartment, suite, etc. (optional)',
              },
              city: {
                type: 'text',
                placeholder: 'City',
                floating: 'City',
                rules: 'required'
              },
              country: {
                type: 'select',
                floating: 'Country',
                placeholder: 'Country',
                items: {
                  'de': 'Germany',
                  'us': 'United States',
                },
                columns: 8,
                rules: 'required',
                // Using custom event to update column width when country changes
                onChange() {
                  this.updateColumns(this.value == 'us' ? 5 : 8)
                  this.form$.el$('billing_address.billing_info.zip_code').updateColumns(this.value == 'us' ? 3 : 4)
                }
              },
              state: {
                type: 'select',
                floating: 'State',
                placeholder: 'State',
                columns: 4,
                items: states,
                rules: 'required',
                // Should only appear if the country is USA
                conditions: [
                  ['billing_address.billing_info.country', 'us']
                ],
              },
              zip_code: {
                type: 'text',
                floating: 'ZIP Code',
                placeholder: 'ZIP Code',
                rules: 'required',
                columns: 4
              },
              phone: {
                type: 'text',
                placeholder: 'Phone',
                floating: 'Phone',
                rules: 'required'
              },
            }
          }
        },
      },

      // 'Remember me' block
      remember_me: {
        type: 'group',
        label: 'Remember me',
        class: 'remember-me',
        schema: {
          // 'Remember me' checkbox
          remember: {
            type: 'checkbox',
            text: 'Save my information for faster checkout',
          },

          // 'Mobile phone number' input (if 'Remember me' is checked)
          mobile_phone_number: {
            type: 'text',
            class: 'remember-me-number',
            floating: 'Mobile phone number',
            placeholder: 'Mobile phone number',
            mask: ['(', /[1-9]/, /\d/, /\d/, ')', ' ', /\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/, /\d/],
            addon: {
              before: '<span class="phone-icon"></span>'
            },
            columns: {
              field: 6
            },
            rules: 'required',
            // Only appears if 'Remember me' is checked) 
            conditions: [
              ['remember_me.remember', true]
            ],
          },

          // Additional description for 'Mobile phone number' (if 'Remember me' is checked)
          phone_description: {
            type: 'static',
            class: 'phone-description',
            content: '<span class="field-description">Next time you check out here or other stores powered by Shopify, Shopify will send you an authorization code by SMS to securely purchase with Shopify Pay.</span>',
            // Only appears if 'Remember me' is checked) 
            conditions: [
              ['remember_me.remember', true]
            ]
          }
        }
      },

      // 'Accept terms' checkbox (if 'Remember me' is checked)
      terms: {
        type: 'static',
        content: '<span class="accept-terms">By continuing, you agree to Shopify Pay’s <a href="#">Privacy Policy</a> and <a href="#">Terms of Service</a>.</span>',
        // Only appears if 'Remember me' is checked) 
        conditions: [
          ['remember_me.remember', true]
        ],
      }
    },

    // Selected theme
    theme: 'shopify',
  }),
  methods: {
    send() {
      alert('Your order has been processed. Thank you')
      this.reset()
    }
  }
}

const states = {
  AL: 'Alabama', AK: 'Alaska', AZ: 'Arizona', AR: 'Arkansas', CA: 'California', CO: 'Colorado',
  CT: 'Connecticut', DE: 'Delaware', DC: 'District Of Columbia', FL: 'Florida', GA: 'Georgia',
  HI: 'Hawaii', ID: 'Idaho', IL: 'Illinois', IN: 'Indiana', IA: 'Iowa', KS: 'Kansas', KY: 'Kentucky',
  LA: 'Louisiana', ME: 'Maine', MD: 'Maryland', MA: 'Massachusetts', MI: 'Michigan', MN: 'Minnesota',
  MS: 'Mississippi', MO: 'Missouri', MT: 'Montana', NE: 'Nebraska', NV: 'Nevada', NH: 'New Hampshire',
  NJ: 'New Jersey', NM: 'New Mexico', NY: 'New York', NC: 'North Carolina', ND: 'North Dakota',
  OH: 'Ohio', OK: 'Oklahoma', OR: 'Oregon', PA: 'Pennsylvania', RI: 'Rhode Island', SC: 'South Carolina',
  SD: 'South Dakota', TN: 'Tennessee', TX: 'Texas', UT: 'Utah', VT: 'Vermont', VA: 'Virginia',
  WA: 'Washington', WV: 'West Virginia', WI: 'Wisconsin', WY: 'Wyoming'
}

const shippingUS = {
  'usps': {
    carrier: 'USPS Priority Mail Express',
    delivery_date: '1 business days',
    price: '$66.46'
  },
  'fedex': {
    carrier: 'FedEx Home Delivery',
    delivery_date: '1 to 5 business days',
    price: '$66.98'
  },
  'ups': {
    carrier: 'UPS Second Day Air',
    delivery_date: '2 business days',
    price: '$120.82'
  },
}

const shippingEU = {
  'eu': {
    carrier: 'Free EU Shipping',
    delivery_date: '2-3 business days',
    price: 'FREE'
  }
}
</script>
            
              
import Laraform from '@laraform/laraform'

import ShopifyCheckoutForm from './path/to/ShopifyCheckoutForm.vue'
import shopifyTheme from './path/to/shopify-theme'

Laraform.theme('shopify', shopifyTheme)

Vue.use(Laraform)

const app = Vue({
  el: '#app',
  components: {
    ShopifyCheckoutForm,
  }
})
            
              
<html>
  <head>
    <!-- ... -->
  </head>
  <body>
    <div id="app">
      <shopify-checkout-form></shopify-checkout-form>
    </div>
  </body>
</html>
            
2

Simple login form with backend support

// Data model:

            
Your form is one entity

Building a form comes with many steps including rendering, validation, processing, etc. Laraform was built in a way which allows you to keep everything in one place. With one simple class you can cover every aspects of managing a form including its processing so you can keep your whole business logic all together.

Laraform features used:
  • Form schema defined in the backend
  • Backend hook to process form after validation
  • Validation with Laravel compatible validators
  • Frontend event for watching response
  • Built in toggle element for Remember me

More examples

Get a License

Get perpetual license with no project limit