npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

vue-instant-form

v1.0.5

Published

Vue form generator based on JSON schema

Downloads

3

Readme

vue-instant-form

Vue form generator based on JSON schema

Installation

Quick Install

# yarn
yarn add vue-instant-form

# npm
npm install --save vue-instant-form

Available Fields

Setup

Import Component to your Vue Instance

import VueInstantForm from 'vue-instant-form';

const app = new Vue({
  el: '#app',
  components: {
    'vue-instant-form': VueInstantForm
  },
  data: function () {
    return {
      data: ...,
      schema: ...,
      actions: ...,
      options: ...
    }
  }
});

Component Usage

<head>
  <!-- vue-instant-form dependencies -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
        integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
  <script src="/static/lib/jquery-3.1.1.min.js"></script>
  <script src="/static/lib/bootstrap.min.js"></script>
  <script src="/static/lib/moment.min.js"></script>

  <!-- for specific field dependencies, we recommend you to check out the /static/lib folder -->
</head>

<body>
  <div id="app">
    <vue-instant-form  v-model="data"
                      :form-schema="schema"
                      :form-actions="actions"
                      :form-options="options"
                      ref="InstantForm">
    </vue-instant-form>
  </div>
</body>

Actions Buttons

There are three standard actions wrapped by buttons: submit, reset, and cancel.

  • Submit action performs standard form submission action. The handler acts as callbacks and form data is provided. However, form validation may be written inside the handler functions.
  • Reset action performs form reset, which means that all field will be filled with its default value (if possible).
  • Cancel action performs form cancel. However, there is no special function embedded in cancel action. Instead, you may do other things, like close container modal.
actions: {
  submit: {
    name: 'submit', label: 'Submit', icon: 'fa fa-check', class: 'btn btn-primary',
    handler: function (data) {
      console.info('onSubmit', data);
    }
  },
  reset: {
    name: 'reset', label: 'Reset', icon: 'fa fa-check', class: 'btn btn-sm btn-info',
    handler: function () {
      vm.$refs.InstantForm.reset();
    }
  },
  cancel: {
    name: 'cancel', label: 'Cancel', icon: 'fa fa-remove', class: 'btn btn-sm btn-warning',
    handler: function () {
      // close container modal, or do other things
    }
  }
}

Guides

Text

data: {
  name: 'Steve Job'
},
schema: {
  name: {
    type: 'text',
    label: 'Name',
    placeholder: 'Your full name',
    help: 'Please type your full name',
    onChanged: function (val) {
      console.log('onChanged', val);
    }
  }
}

Number

data: {
  height: 170
},
schema: {
  height: {
    type: 'number',
    label: 'Height',
    min: 0, //optional
    max: 0, //optional
    step: 0.01 //optional
  }
}

Email

data: {
  email: 170
},
schema: {
  email: {
    type: 'email',
    label: 'Email'
  }
}

Currency

data: {
  price: 1000.00
},
schema: {
  price: {
    type: 'currency',
    label: 'Price',
    default: 0, //optional
    min: 0, //optional
    max: 1000000 //optional
  }
}

Note: currency field supports only Indonesian Rupiah (Rp.) at the moment and highly utilizes jquery!

Phone Number

data: {
  phone: 1000.00
},
schema: {
  phone: {
    type: 'phone-number',
    label: 'Phone Number',
    delimiter: '-' //optional
  }
}

Select

Select field may return two kind of value: optionValue, and Object.

Return optionValue:

data: {
  gender: 2
},
schema: {
  gender: {
    type: 'select',
    label: 'Gender',
    options: [
      { id: 1, label: 'Male' },
      { id: 2, label: 'Female' }
    ],
    optionValue: 'id', // optional, default is 'id'
    optionLabel: 'label', // optional, default is 'label'
  }
}

Return object:

data: {
  gender: { id: 1, label: 'Male' }
},
schema: {
  gender: {
    type: 'select',
    label: 'Gender',
    options: [
      { id: 1, label: 'Male' },
      { id: 2, label: 'Female' }
    ],
    trackby: 'id',
    optionLabel: 'label', // optional, default is 'label'
  }
}

Custom label:

data: {
  gender: 2
},
schema: {
  gender: {
    type: 'select',
    label: 'Gender',
    options: [
      { id: 1, label: 'Male' },
      { id: 2, label: 'Female' }
    ],
    optionCustomLabel: function (option) {
      return option.label + ' - ' + option.id;
    }
  }
}

Select2

Dependencies: select2 (Get it here: http://select2.github.io)

Include select2 both js and css files:

<link rel="stylesheet" href="/static/lib/select2/css/select2.min.css">
<script src="/path/to/select2/js/select2.min.js"></script>

Schema definition (similiar with common select field):

data: {
  gender: 2
},
schema: {
  gender: {
    type: 'select2',
    label: 'Gender',
    options: [
      { id: 1, label: 'Male' },
      { id: 2, label: 'Female' }
    ],
    optionCustomLabel: function (option) {
      return option.label + ' - ' + option.id;
    }
  }
}

Select2 may return object as common select field do.

Auto Complete

Dependencies: jquery autocomplete (Get it here: https://www.devbridge.com/sourcery/components/jquery-autocomplete)

Include jquery autocomplete js files:

<script src="/path/to/jquery.autocomplete.min.js"></script>

Schema definition:

data: {
  country: 'Indonesia'
},
schema: {
  country: {
    type: 'autocomplete',
    label: 'Country',
    options: [ 'Indonesia', 'Japan' ]
  }
}

Date Time Picker

Dependencies: bootstrap-datetimepicker, developed by Malot (Get it here: http://www.malot.fr/bootstrap-datetimepicker)

Include both js and css files:

<link rel="stylesheet" href="/static/lib/bootstrap-datetimepicker.min.css">
<script src="/static/lib/bootstrap-datetimepicker.min.js"></script>

Schema definition:

data: {
  birthday: new Date()
},
schema: {
  birthday: {
    type: 'datetimepicker',
    label: 'Birth Day',
    mode: 'datepicker', // optional, default is 'datepicker'
  }
}

Datetimepicker component provides three modes: datepicker, datetimepicker, and timepicker.

File Upload

Dependencies: fine-uploader (Get it here: http://fineuploader.com)

Include both js and css files:

<link rel="stylesheet" href="/static/lib/fine-uploader/fine-uploader-gallery.min.css">
<script src="/static/lib/fine-uploader/fine-uploader.min.js"></script>

Write qq-template which is required by fine-uploader. There are three available template types provided by fine-uploader. If you aren't satisfied and need more UIs, please refer to http://docs.fineuploader.com/branch/master/features/styling.html for more styling options.

<!-- gallery style template provided by fine-uploader as default -->
<script type="text/template" id="qq-template">
  <div class="qq-uploader-selector qq-uploader qq-gallery" qq-drop-area-text="Drop files here">
    <div class="qq-total-progress-bar-container-selector qq-total-progress-bar-container">
      <div role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="qq-total-progress-bar-selector qq-progress-bar qq-total-progress-bar"></div>
    </div>
    <div class="qq-upload-drop-area-selector qq-upload-drop-area" qq-hide-dropzone>
      <span class="qq-upload-drop-area-text-selector"></span>
    </div>
    <div class="qq-upload-button-selector qq-upload-button">
      <div>Upload a file</div>
    </div>
          <span class="qq-drop-processing-selector qq-drop-processing">
              <span>Processing dropped files...</span>
              <span class="qq-drop-processing-spinner-selector qq-drop-processing-spinner"></span>
          </span>
    <ul class="qq-upload-list-selector qq-upload-list" role="region" aria-live="polite" aria-relevant="additions removals">
      <li>
        <span role="status" class="qq-upload-status-text-selector qq-upload-status-text"></span>
        <div class="qq-progress-bar-container-selector qq-progress-bar-container">
          <div role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="qq-progress-bar-selector qq-progress-bar"></div>
        </div>
        <span class="qq-upload-spinner-selector qq-upload-spinner"></span>
        <div class="qq-thumbnail-wrapper">
          <img class="qq-thumbnail-selector" qq-max-size="120" qq-server-scale>
        </div>
        <button type="button" class="qq-upload-cancel-selector qq-upload-cancel">X</button>
        <button type="button" class="qq-upload-retry-selector qq-upload-retry">
          <span class="qq-btn qq-retry-icon" aria-label="Retry"></span>
          Retry
        </button>

        <div class="qq-file-info">
          <div class="qq-file-name">
            <span class="qq-upload-file-selector qq-upload-file"></span>
            <span class="qq-edit-filename-icon-selector qq-btn qq-edit-filename-icon" aria-label="Edit filename"></span>
          </div>
          <input class="qq-edit-filename-selector qq-edit-filename" tabindex="0" type="text">
          <span class="qq-upload-size-selector qq-upload-size"></span>
          <button type="button" class="qq-btn qq-upload-delete-selector qq-upload-delete">
            <span class="qq-btn qq-delete-icon" aria-label="Delete"></span>
          </button>
          <button type="button" class="qq-btn qq-upload-pause-selector qq-upload-pause">
            <span class="qq-btn qq-pause-icon" aria-label="Pause"></span>
          </button>
          <button type="button" class="qq-btn qq-upload-continue-selector qq-upload-continue">
            <span class="qq-btn qq-continue-icon" aria-label="Continue"></span>
          </button>
        </div>
      </li>
    </ul>

    <dialog class="qq-alert-dialog-selector">
      <div class="qq-dialog-message-selector"></div>
      <div class="qq-dialog-buttons">
        <button type="button" class="qq-cancel-button-selector">Close</button>
      </div>
    </dialog>

    <dialog class="qq-confirm-dialog-selector">
      <div class="qq-dialog-message-selector"></div>
      <div class="qq-dialog-buttons">
        <button type="button" class="qq-cancel-button-selector">No</button>
        <button type="button" class="qq-ok-button-selector">Yes</button>
      </div>
    </dialog>

    <dialog class="qq-prompt-dialog-selector">
      <div class="qq-dialog-message-selector"></div>
      <input type="text">
      <div class="qq-dialog-buttons">
        <button type="button" class="qq-cancel-button-selector">Cancel</button>
        <button type="button" class="qq-ok-button-selector">Ok</button>
      </div>
    </dialog>
  </div>
</script>

Schema definition:

data: {
  files: [
    {
      id: 1,
      filename: 'avatar_c80a99bd5fd4_128.png',
      uuid: '226a8e3a-2f52-4322-a2d5-a7be28cf50ec',
      filetype: 'image/png'
    }
  ]
},
schema: {
  files: {
    type: 'file-upload',
    label: 'Upload file',
    withDelete: true,
    endpoint: 'http://localhost/fine_uploader',
    itemLimit: 1, // optional, default is unlimited
    help: 'This is help block' //optional
  }
}

File upload field requires server endpoint which receive data as POST and DELETE request. For the details please refers to http://docs.fineuploader.com/branch/master/endpoint_handlers/traditional.html. However, vue-instant-form already comes with Laravel endpoint example, please check LaravelController.php. Laravel endpoint highly utilize migration and model to realize database table uploaded_files which track all uploaded file, so you can add relation to other object at the back end.

Complete Laravel package (https://github.com/inimedia/foundation) can be installed by running:

composer require inimedia/foundation

Text Area

data: {
  description: 'Lorem ipsum dolor sit amet...'
},
schema: {
  description: {
    type: 'textarea',
    label: 'Description',
    rows: '5',
    default: '',
    placeholder: 'Please enter your description here',
    onChanged: function (val) {
      console.log('onChanged', val);
    }
  }
}

TODO

  • add built in validator
  • add two column support as option
  • checkbox and radio
  • field button
  • add docs for message and list field

Build and Debugging Setup

# install dependencies
npm install

# serve with hot reload at localhost:8080
npm run dev

# build for production with minification
npm run build

# run unit tests
npm run unit

# run e2e tests
npm run e2e

# run all tests
npm test

For detailed explanation on how things work, checkout the guide and docs for vue-loader.