Top

Forms


Looks good!
Looks good!
@
Please choose a username.
Please provide a valid city.
Please select a valid state.
Please provide a valid zip.
You must agree before submitting.
   <Card
    :cardClass="'height-equal'"
    :headerTitle="'Validation Form'"
    :border="true"
    :padding="false"
  >
    <template #header5>
      <p class="f-m-light mt-1">
        Custom feedback styles apply custom colors, borders, focus styles, and background
        icons to better communicate feedback.Background icons for
        <code>&lt;select&gt;</code>s are only available with <code>form-select</code> and
        not <code>form-control.</code>
      </p>
    </template>

    <form
      class="row g-3 needs-validation custom-input"
      novalidate
      @submit.prevent="submitForm()"
    >
      <div class="col-12">
        <InputWrapper :title="'First Name'">
          <InputField
            :formSubmitted="formSubmitted"
            :errorMessage="'First name is required.'"
            v-model:modelValue="validationForm.first_name"
            :inputId="'first-name'"
            :placeholder="'Enter first name'"
          />
        </InputWrapper>
      </div>
      <div class="col-12">
        <InputWrapper :title="'Password'">
          <InputField
            :formSubmitted="formSubmitted"
            :errorMessage="'Password is required.'"
            v-model:modelValue="validationForm.password"
            :inputId="'password'"
            :inputType="'password'"
            :placeholder="'Enter password'"
          />
        </InputWrapper>
      </div>
      <div class="col-12">
        <InputWrapper :title="'State'">
          <Select
            getValueKey="label"
            display-key="label"
            :placeholder="'Select state'"
            v-model="validationForm.state"
            :errorMessage="'Please select state.'"
            :options="states"
            :formSubmitted="formSubmitted"
          />
        </InputWrapper>
      </div>
      <div class="col-md-6">
        <InputWrapper :title="'City'">
          <InputField
            :formSubmitted="formSubmitted"
            :errorMessage="'City is required.'"
            v-model:modelValue="validationForm.city"
            :inputId="'city'"
            :placeholder="'Enter city'"
          />
        </InputWrapper>
      </div>
      <div class="col-md-6">
        <InputWrapper :title="'Zip'">
          <InputField
            :formSubmitted="formSubmitted"
            :errorMessage="'Zip is required.'"
            v-model:modelValue="validationForm.zip"
            :inputId="'zip'"
            :placeholder="'Enter zip'"
          />
        </InputWrapper>
      </div>
      <div class="col-12">
        <div class="card-wrapper border rounded-3 checkbox-checked">
          <h6 class="sub-title">Select Your Payment Method</h6>
          <div class="radio-form">
            <div class="form-check">
              <input
                class="form-check-input"
                id="validationFormCheck25"
                type="radio"
                name="radio-stacked"
                required
              />
              <label class="form-check-label" for="validationFormCheck25"
                >MaterCard</label
              >
            </div>
            <div class="form-check">
              <input
                class="form-check-input"
                id="validationFormCheck23"
                type="radio"
                name="radio-stacked"
                required
              />
              <label class="form-check-label" for="validationFormCheck23">VISA</label>
            </div>
          </div>
        </div>
      </div>
      <div class="col-12">
        <Select
          getValueKey="label"
          display-key="label"
          :placeholder="'Select Your Favorite Pixelstrap theme'"
          v-model="validationForm.favorite_theme"
          :errorMessage="'Please select your favorite pixelstrap theme.'"
          :options="selectTheme"
          :formSubmitted="formSubmitted"
        />
      </div>
      <div class="col-12">
        <InputWrapper :title="'Choose File'">
          <InputField
            :formSubmitted="formSubmitted"
            :errorMessage="'File is required.'"
            v-model:modelValue="validationForm.document"
            :inputId="'document'"
            :inputType="'file'"
          />
        </InputWrapper>
      </div>
      <div class="col-12">
        <InputWrapper :title="'Description'">
          <InputField
            :formSubmitted="formSubmitted"
            :errorMessage="'Description is required.'"
            v-model:modelValue="validationForm.description"
            :inputId="'description'"
            :inputType="'textarea'"
          />
        </InputWrapper>
      </div>
      <div class="col-12">
        <div class="form-check">
          <Checkbox
            :formSubmitted="formSubmitted"
            :class="'form-check-input'"
            :label="'Agree to terms and conditions'"
            :errorMessage="'You must agree before submitting.'"
            v-model:modelValue="validationForm.condition"
            :inputId="'condition'"
          />
        </div>
      </div>
      <div class="col-12">
        <button class="btn btn-primary" type="submit">Submit form</button>
      </div>
    </form>
  </Card>

Inside Your script tags add


import { ref, reactive, defineAsyncComponent } from "vue";

import { initCheckboxField, initInputField, initSelectField } from "@/core/data/common";
import { states } from "@/core/data/country";
import { selectTheme } from "@/core/data/forms/formControl";
import { resetForm } from "@/utils/index";
import { validateForm } from "@/utils/validators/formValidators";

const Card = defineAsyncComponent(() => import("@/components/shared/card/Card.vue"));
const InputWrapper = defineAsyncComponent(
  () => import("@/components/shared/formElements/InputWrapper.vue")
);
const InputField = defineAsyncComponent(
  () => import("@/components/shared/formElements/InputField.vue")
);
const Select = defineAsyncComponent(
  () => import("@/components/shared/formElements/Select.vue")
);
const Checkbox = defineAsyncComponent(
  () => import("@/components/shared/formElements/Checkbox.vue")
);

let formSubmitted = ref(false);
let validationForm = reactive({
  first_name: initInputField(),
  password: initInputField(),
  state: initSelectField(),
  city: initInputField(),
  zip: initInputField(),
  favorite_theme: initSelectField(),
  document: initInputField(),
  description: initInputField(),
  condition: initCheckboxField(),
});

function submitForm() {
  formSubmitted.value = true;
  const { isValid, formData } = validateForm(validationForm);

  if (isValid) {
    validationForm = resetForm(validationForm);
    formSubmitted.value = false;
  }
}

Inside Your ts tags add

type FieldType = "text" | "checkbox" | "select" | "number" | "date" | string;
interface BaseField {
  data: T;
  type?: FieldType;
  errorMessage?: string;
}

type FormField = string | number | boolean | BaseField | string[];

export type FormFields = Record;

interface ValidateFormResult {
  isValid: boolean;
  formData: Record;
}

export function validateForm(
  form: FormFields,
  nonRequiredFields: string[] = []
): ValidateFormResult {
  const formData: Record = {};
  let isValid = true;

  for (const key in form) {
    const field = form[key];
    const isRequired = !nonRequiredFields.includes(key);

    if (typeof field === "object" && field !== null && "data" in field) {
      const value = field.data;
      const fieldType = field.type ?? "text";

      let cleanedValue: unknown;

      if (fieldType === "checkbox") {
        cleanedValue = Boolean(value);
        if (isRequired) {
          field.errorMessage = !cleanedValue ? field.errorMessage || "This field is required" : "";
          if (!cleanedValue) isValid = false;
        } else {
          field.errorMessage = "";
        }
      } else if (typeof value === "string") {
        cleanedValue = value.trim();
      } else if (Array.isArray(value)) {
        cleanedValue = value;
      } else {
        cleanedValue = value ?? "";
      }

      if (fieldType !== "checkbox") {
        const isEmpty =
          (Array.isArray(cleanedValue) && cleanedValue.length === 0) || cleanedValue === "";
        if (isRequired) {
          field.errorMessage = isEmpty ? field.errorMessage || "This field is required" : "";
          if (isEmpty) isValid = false;
        } else {
          field.errorMessage = "";
        }
      }

      formData[key] = cleanedValue;
    } else {
      const value = typeof field === "string" ? field.trim() : (field ?? "");
      formData[key] = value;

      if (isRequired && typeof value === "string" && value === "") {
        isValid = false;
      }
    }
  }

  return { isValid, formData };
}

   
<form class="form theme-form">
 <div class="card-body p-0">
  <div class="row">
   <div class="col">
    <div class="mb-3">
      <label class="form-label" for="exampleFormControlInput1">Email address</label>
      <input class="form-control" id="exampleFormControlInput1" type="email" placeholder="name@example.com" data-bs-original-title="" title="">
    </div>
   </div>
  </div>
 </div>
</form>
<div class="row">
 <div class="custom-radio-ml col-lg-3 col-md-6">
  <div class="form-check radio radio-primary">
   <input class="form-check-input" id="radio1" type="radio" name="radio1" value="option1" data-bs-original-title="" title="">
   <label class="form-check-label" for="radio1">Option<span class="digits"> 1</span></label>
  </div>
  <div class="form-check radio radio-primary">
   <input class="form-check-input" id="radio3" type="radio" name="radio1" value="option1" disabled="" data-bs-original-title="" title="">
   <label class="form-check-label" for="radio3">Disabled</label>
  </div>
  <div class="form-check radio radio-primary">
   <input class="form-check-input" id="radio4" type="radio" name="radio1" value="option1" checked="" data-bs-original-title="" title="">
   <label class="form-check-label" for="radio4">Checked</label>
  </div>
</div>
<div class="col-md-6 col-lg-3">
 <div class="form-check checkbox mb-0">
  <input class="form-check-input" id="checkbox1" type="checkbox" data-bs-original-title="" title="">
  <label class="form-check-label my-0" for="checkbox1">Default</label>
 </div>
 <div class="form-check checkbox mb-0">
  <input class="form-check-input" id="checkbox2" type="checkbox" disabled="" data-bs-original-title="" title="">
  <label class="form-check-label my-0" for="checkbox2">Disabled</label>
 </div>
 <div class="form-check checkbox mb-0">
  <input class="form-check-input" id="checkbox3" type="checkbox" checked="" data-bs-original-title="" title="">
  <label class="form-check-label my-0" for="checkbox3">Checked</label>
 </div>
</div>
</div>
Left Addon
@
<form>
<div class="mb-3 m-form__group">
 <div class="form-label">Left Addon</div>
  <div class="input-group">
   <span class="input-group-text">@</span>
   <input class="form-control" type="text" placeholder="Email" data-bs-original-title="" title="">
  </div>
 </div>
</form>
import Datepicker from '@vuepic/vue-datepicker';
import '@vuepic/vue-datepicker/dist/main.css'
.component('Datepicker', Datepicker)

Inside Your template tags add

<datepicker  datepicker class=" datetimepicker-input digits" v-model="date" :format="format" />

Inside Your script tags add

import { ref } from 'vue';
    let date = ref(null);

      const format = (date: Date | null): string => {
          if (date === null) {
              return '';
          }
      
          const day = date.getDate();
          const month = date.getMonth() + 1;
          const year = date.getFullYear();
      
          return ` ${day}/${month}/${year}`;
      };
<label class="switch">
 <input type="checkbox" checked="" data-bs-original-title="" title="">
 <span class="switch-state"></span>
</label>
<label class="switch">
 <input type="checkbox" data-bs-original-title="" title="">
 <span class="switch-state"></span>
</label>

Inside Your template tags add


<button class="decrement-touchspin btn-touchspin touchspin-primary" @click="primeryDecrement()"><i
      class="fa fa-minus"></i>
</button>
 <input class="input-touchspin spin-outline-primary" type="number" v-model="conter">
 <span class="input-group-text">%</span>
 <button class="increment-touchspin btn-touchspin touchspin-primary" @click="primeryIncrement()"><i
         class="fa fa-plus"></i>
</button>

Inside Your script tags add

import { ref, defineAsyncComponent } from 'vue'
  let conter = ref<number>(0)
  function primeryIncrement() {
      conter.value++
  }
  function primeryDecrement() {
      if (conter.value > 0) {
          conter.value--
      }
  }                 
 
<div id="the-basics">
<form class="theme-form">
<div>
  <input class="typeahead form-control" type="text" placeholder="States of USA" />
</div>
</form>
</div>
To use typeahead you have to add the following script files

import { ref, } from 'vue'

interface data {
    placeholder: string,
    minInputLength: number,
    hint: boolean
}
export let options = ref({
    placeholder: 'States of USA',
    minInputLength: 1,
    hint: false
})
export let listFiltered = ref([])
export let list = ref(['alabama',
    'alaska',
    'arizona',
    'arkansas',
    'california',
    'colorado',
    'connecticut',
    'delaware',
    'florida',
    'georgia',
    'hawaii',
    'idaho',
    'illinois',
    'indiana',
    'iowa',
    'kansas',
    'kentucky',
    'louisiana',
    'maine',
    'maryland',
    'massachusetts',
    'michigan',
    'minnesota',
    'mississippi',
    'missouri',
    'montana',
    'nebraska',
    'nevada',
    'new hampshire',
    'new jersey',
    'new mexico',
    'new york',
    'north carolina',
    'north dakota',
    'ohio',
    'oklahoma',
    'oregon',
    'pennsylvania',
    'rhode island',
    'south carolina',
    'south dakota',
    'tennessee',
    'texas',
    'utah',
    'vermont',
    'virginia',
    'washington',
    'west virginia',
    'wisconsin',
    'wyoming',
])
export let lists = ref(['West Side Story - 1961',
    'Lawrence of Arabia - 1962',
    'Tom Jones - 1963',
    'My Fair Lady - 1964',
    'The Sound of Music - 1965',
    'A Man for All Seasons - 1966',
    'In the Heat of the Night - 1967',
    'Oliver! - 1968',
    'Midnight Cowboy - 1969',
    'Patton - 1970',
    'The French Connection - 1971',
    'The Godfather - 1972',
    'The Sting - 1973',
    'The Godfather Part II - 1974',
    'One Flew over the Cuckoo"s Nest - 1975',
    'Rocky - 1976',
    'Annie Hall - 1978',
    'The Deer Hunter - 1979',
    'Kramer vs. Kramer - 1980',
    'Ordinary People - 1981',
    'Chariots of Fire - 1982',
    'Gandhi - 1983',
    'Terms of Endearment - 1984',
    'Amadeus - 1985',
    'Out of Africa - 1986',
    'Platoon - 1987',
    'The Last Emperor - 1988',
    'Rain Man - 1989',
    'Driving Miss Daisy - 1990',
    'Dances With Wolves - 1991',
    'The Silence of the Lambs - 1992',
    'Unforgiven - 1993',
    'Schindler’s List - 1994',
    'Forrest Gump - 1995',
    'Braveheart - 1996',
    'The English Patient - 1997',
    'Titanic - 1998',
    'Shakespeare in Love - 1999',
    'American Beauty - 2000',
    'Gladiator - 2001',
    'A Beautiful Mind - 2002',
    'Chicago - 2003',
    'The Lord of the Rings: The Return of the King - 2004',
    'Million Dollar Baby - 2005',
    'Crash - 2005',
    'The Departed - 2006',
    'No Country for Old Men - 2007',
    'Slumdog Millionaire - 2008',
    'The Hurt Locker - 2009',
    'The King"s Speech - 2010',
    'The Artist - 2011',
    'Argo - 2012',
])
export let multiple = ref(["Boston Celtics", "Dallas Mavericks", "Brooklyn Nets", "Houston Rockets", "New York Knicks", "Memphis Grizzlies", "Philadelphia 76ers", "New Orleans Hornets", "Toronto Raptors", "San Antonio Spurs", "Chicago Bulls", "Denver Nuggets", "Cleveland Cavaliers", "Minnesota Timberwolves", "Detroit Pistons", "Portland Trail Blazers", "Indiana Pacers", "Oklahoma City Thunder", "Milwaukee Bucks", "Utah Jazz", "Atlanta Hawks", "Golden State Warriors", "Charlotte Bobcats", "Los Angeles Clippers", "Miami Heat", "Los Angeles Lakers", "Orlando Magic", "Phoenix Suns", "Washington Wizards", "Sacramento Kings", "New Jersey Devils", "New York Islanders", "New York Rangers", "Philadelphia Flyers", "Pittsburgh Penguins", "Chicago Blackhawks", "Columbus Blue Jackets", "Detroit Red Wings", "Nashville Predators", "St. Louis Blues", "Boston Bruins", "Buffalo Sabres", "Montreal Canadiens", "Ottawa Senators", "Toronto Maple Leafs", "Calgary Flames", "Colorado Avalanche", "Edmonton Oilers", "Minnesota Wild", "Vancouver Canucks", "Carolina Hurricanes", "Florida Panthers", "Tampa Bay Lightning", "Washington Capitals", "Winnipeg Jets", "Anaheim Ducks", "Dallas Stars", "Los Angeles Kings", "Phoenix Coyotes", "San Jose Sharks"]
)
export let scroll = ref(["Andorra", "United Arab Emirates", "Afghanistan", "Antigua and Barbuda", "Anguilla", "Albania", "Armenia", "Angola", "Antarctica", "Argentina", "American Samoa", "Austria", "Australia", "Aruba", "Åland", "Azerbaijan", "Bosnia and Herzegovina", "Barbados", "Bangladesh", "Belgium", "Burkina Faso", "Bulgaria", "Bahrain", "Burundi", "Benin", "Saint Barthélemy", "Bermuda", "Brunei", "Bolivia", "Bonaire", "Brazil", "Bahamas", "Bhutan", "Bouvet Island", "Botswana", "Belarus", "Belize", "Canada", "Cocos [Keeling] Islands", "Congo", "Central African Republic", "Republic of the Congo", "Switzerland", "Ivory Coast", "Cook Islands", "Chile", "Cameroon", "China", "Colombia", "Costa Rica", "Enzo", "Cape Verde", "Curacao", "Christmas Island", "Cyprus", "Czechia", "Germany", "Djibouti", "Denmark", "Dominica", "Dominican Republic", "Algeria", "Ecuador", "Estonia", "Egypt", "Western Sahara", "Eritrea", "Spain", "Ethiopia", "Finland", "Fiji", "Falkland Islands", "Micronesia", "Faroe Islands", "France", "Gabon", "United Kingdom", "Grenada", "Georgia", "French Guiana", "Guernsey", "Ghana", "Gibraltar", "Greenland", "Gambia", "Guinea", "Guadeloupe", "Equatorial Guinea", "Greece", "South Georgia and the South Sandwich Islands", "Guatemala", "Guam", "Guinea-Bissau", "Guyana", "Hong Kong", "Heard Island and McDonald Islands", "Honduras", "Croatia", "Haiti", "Hungary", "Indonesia", "Ireland", "Israel", "Isle of Man", "India", "British Indian Ocean Territory", "Iraq", "Iran", "Iceland", "Italy", "Jersey", "Jamaica", "Jordan", "Japan", "Kenya", "Kyrgyzstan", "Cambodia", "Kiribati", "Comoros", "Saint Kitts and Nevis", "North Korea", "South Korea", "Kuwait", "Cayman Islands", "Kazakhstan", "Laos", "Lebanon", "Saint Lucia", "Liechtenstein", "Sri Lanka", "Liberia", "Lesotho", "Lithuania", "Luxembourg", "Latvia", "Libya", "Morocco", "Monaco", "Moldova", "Montenegro", "Saint Martin", "Madagascar", "Marshall Islands", "Macedonia", "Mali", "Myanmar [Burma]", "Mongolia", "Macao", "Northern Mariana Islands", "Martinique", "Mauritania", "Montserrat", "Malta", "Mauritius", "Maldives", "Malawi", "Mexico", "Malaysia", "Mozambique", "Namibia", "New Caledonia", "Niger", "Norfolk Island", "Nigeria", "Nicaragua", "Netherlands", "Norway", "Nepal", "Nauru", "Niue", "New Zealand", "Oman", "Panama", "Peru", "French Polynesia", "Papua New Guinea", "Philippines", "Pakistan", "Poland", "Saint Pierre and Miquelon", "Pitcairn Islands", "Puerto Rico", "Palestine", "Portugal", "Palau", "Paraguay", "Qatar", "Réunion", "Romania", "Serbia", "Russia", "Rwanda", "Saudi Arabia", "Solomon Islands", "Seychelles", "Sudan", "Sweden", "Singapore", "Saint Helena", "Slovenia", "Svalbard and Jan Mayen", "Slovakia", "Sierra Leone", "San Marino", "Senegal", "Somalia", "Suriname", "South Sudan", "São Tomé and Príncipe", "El Salvador", "Sint Maarten", "Syria", "Swaziland", "Turks and Caicos Islands", "Chad", "French Southern Territories", "Togo", "Thailand", "Tajikistan", "Tokelau", "East Timor", "Turkmenistan", "Tunisia", "Tonga", "Turkey", "Trinidad and Tobago", "Tuvalu", "Taiwan", "Tanzania", "Ukraine", "Uganda", "U.S. Minor Outlying Islands", "United States", "Uruguay", "Uzbekistan", "Vatican City", "Saint Vincent and the Grenadines", "Venezuela", "British Virgin Islands", "U.S. Virgin Islands", "Vietnam", "Vanuatu", "Wallis and Futuna", "Samoa", "Kosovo", "Yemen", "Mayotte", "South Africa", "Zambia", "Zimbabwe"
])
export let remote = ref(['West Side Story',
    'Lawrence of Arabia',
    'Tom Jones',
    'My Fair Lady',
    'The Sound of Music',
    'A Man for All Seasons',
    'In the Heat of the Night',
    'Oliver!',
    'Midnight Cowboy',
    'Patton',
    'The French Connection',
    'The Godfather',
    'The Sting',
    'The Godfather Part II',
    'One Flew over the Cuckoo"s Nest',
    'Rocky',
    'Annie Hall',
    'The Deer Hunter',
    'Kramer vs. Kramer',
    'Ordinary People',
    'Chariots of Fire',
    'Gandhi',
    'Terms of Endearment',
    'Amadeus',
    'Out of Africa',
    'Platoon',
    'The Last Emperor',
    'Rain Man',
    'Driving Miss Daisy',
    'Dances With Wolves',
    'The Silence of the Lambs',
    'Unforgiven',
    'Schindler’s List',
    'Forrest Gump',
    'Braveheart',
    'The English Patient',
    'Titanic',
    'Shakespeare in Love',
    'American Beauty',
    'Gladiator',
    'A Beautiful Mind',
    'Chicago',
    'The Lord of the Rings: The Return of the King',
    'Million Dollar Baby',
    'Crash',
    'The Departed',
    'No Country for Old Men',
    'Slumdog Millionaire',
    'The Hurt Locker',
    'The King"s Speech',
    'The Artist',
    'Argo',

])


export function selectItem(item: string) {

}
export function onInput(event: { items: string[] }) {

    listFiltered.value = event.items;
}
export function onBlur(event: { items: string[] }) {

    listFiltered.value = event.items;
}              
            
npm i vue3-form-wizard

Inside Your template tags add

 <form-wizard @on-complete="onComplete">
  <tab-content>
      <div class="col-xs-12">
          <div class="col-md-12">
              <div class="mb-3">
                  <label class="control-label">First Name</label>
                  <input class="form-control" type="text" placeholder="Johan" required>
              </div>
              <div class="mb-3">
                  <label class="control-label">Last Name</label>
                  <input class="form-control" type="text" placeholder="Deo" required>
              </div>
          </div>
      </div>
  </tab-content>
  <tab-content>
      <div class="col-xs-12 ">
          <div class="col-md-12">
              <div class="mb-3">
                  <label class="control-label">Email</label>
                  <input class="form-control" type="text" placeholder="name@example.com" required>
              </div>
              <div class="mb-3">
                  <label class="control-label">Password</label>
                  <input class="form-control" type="password" placeholder="Password" required>
              </div>
          </div>
      </div>
  </tab-content>
  <tab-content>
      <div class="col-xs-12 ">
          <div class="col-md-12">
              <div class="mb-3">
                  <label class="control-label">Birth date</label>
                  <input class="form-control" type="date" required>
              </div>
              <div class="mb-3">
                  <label class="control-label">Have Passport</label>
                  <input class="form-control" type="text" placeholder="yes/No" required>
              </div>
          </div>
      </div>
  </tab-content>
  <tab-content>
      <div class="col-xs-12 ">
          <div class="col-md-12">
              <div class="mb-3">
                  <label class="control-label">State</label>
                  <input class="form-control mt-1" type="text" placeholder="State" required>
              </div>
              <div class="mb-3">
                  <label class="control-label">City</label>
                  <input class="form-control mt-1" type="text" placeholder="City" required>
              </div>
          </div>
      </div>
  </tab-content>
</form-wizard>

Inside Your script tags add

 import { ref, defineAsyncComponent, onMounted } from 'vue'
  import { tab } from "@/core/data/forms"
  import { FormWizard, TabContent } from "vue3-form-wizard";
  import 'vue3-form-wizard/dist/style.css'
  function onComplete() {
      alert('Yay, Done')
   }