diff --git a/LICENSE b/LICENSE
index 29a7e3b..42fcd9e 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2016 10Quality
+Copyright (c) 2017 10Quality
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index d873de8..55df581 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,9 @@
[![GitHub version](https://badge.fury.io/gh/10quality%2Fvue-form.svg)](https://badge.fury.io/gh/10quality%2Fvue-form)
[![Bower version](https://badge.fury.io/bo/10q-vue-form.svg)](https://badge.fury.io/bo/10q-vue-form)
-Form handler component for [Vue v1](http://vuejs.org/).
+Form handler component for [Vue](http://vuejs.org/) v2.
+
+**NOTE** Use [v1.0 branch](https://github.com/10quality/vue-form/tree/v1.0) to use this with Vue v1.
View [DEMO](http://codepen.io/amostajo/pen/vKdPbj).
@@ -44,7 +46,7 @@ Add the component in your vue view.
```html
-
+
-
+
```
*NOTE:* `inline-template` must be present.
@@ -90,7 +92,7 @@ Data sent by form should be binded to the `request` data model. In other words,
As reference, a basic contact form sample:
```html
-
+
@@ -115,7 +117,7 @@ As reference, a basic contact form sample:
-
+
```
### Response
@@ -134,7 +136,7 @@ If the following data is found, the form will *auto-process* the response (json)
This response can be displayed in the template like:
```html
-
+
@@ -146,7 +148,7 @@ This response can be displayed in the template like:
-
+
```
Computed properties to use in template:
@@ -160,7 +162,7 @@ Property | Data Type | Description
Another example using Bootstrap:
```html
-
+
@@ -173,7 +175,7 @@ Another example using Bootstrap:
-
+
```
#### Redirection
@@ -193,7 +195,7 @@ If the following data is found, the form will redirect the current window to the
Form comes with a child component called `results`. This component will facilitate the handling of data returned by request (thought for searches).
```html
-
+
@@ -204,7 +206,7 @@ Form comes with a child component called `results`. This component will facilita
/>
@@ -219,7 +221,7 @@ Form comes with a child component called `results`. This component will facilita
-
+
```
In the example above, `results` child component is handling search results returned by the response (assuming `response` contains only results) and it is computing them into a property called `records`.
@@ -241,11 +243,11 @@ Prop | Data Type | Default | Description
Another example:
```html
-
+
```
-In the example above, the response returned a list of errors per input. `input-handler` will process the response and if errors are found, it will add an error class to the input wrapper and will list the erros under the input using a `
` HTML tag.
+In the example above, the response returned a list of errors per input. `input-handler` will process the response and if errors are found (response must be passed as `v-model`), it will add an error class to the input wrapper and will list the erros under the input using a `
` HTML tag.
#### Props
@@ -339,14 +341,14 @@ Form comes with a set of validation rules that can be applied to input values pr
In the following example, the input will validate that name is not empty (is a required field) and that it has at least 8 characters:
```html
-
+
@@ -359,7 +361,7 @@ In the following example, the input will validate that name is not empty (is a r
-
+
```
List of available rules to use:
@@ -383,34 +385,25 @@ Rule | Params | Sample
Events dispatched by form:
-Event | Data sent | Description
----------------- | ---------------------------- | -------------------
-`vform_success` | | Dispatched once response is returned and assigned to model `response`.
-`vform_error` | `e` Error response returned. | Dispatched on request error. (Error is thrown to console too).
-`vform_complete` | | Dispatched after request completed. (Success or error)
-`vform_invalid` | `errors` List of errors. | Dispatched and broadcasted when a validation ocurred.
+Event | Data sent | Description
+---------- | ---------------------------- | -------------------
+`success` | | Emitted once response is returned and assigned to model `response`.
+`error` | `e` Error response returned. | Emitted on request error. (Error is thrown to console too).
+`complete` | | Emitted after request completed. (Success or error)
+`invalid` | `errors` List of errors. | Emitted and broadcasted when a validation ocurred.
Usage example:
-```javacript
-var app = new Vue({
- el: '#app', // Assuming binding is app
- events: {
- 'vform_success': function() {
- // TODO MY CODE
- },
- 'vform_error': function(e) {
- // TODO MY CODE
- },
- 'vform_complete': function() {
- // TODO MY CODE
- },
- 'vform_invalid': function(errors) {
- // TODO MY CODE
- },
- },
-});
+```html
+
',
props:
{
/**
* Name of the error key to listen to.
- * @since 1.0
+ * @since 1.0.0
* @var string
*/
listen:
@@ -343,17 +340,18 @@ Vue.component('vform', Vue.extend({
},
/**
* CSS class to apply to wrapper.
- * @since 1.0
+ * @since 1.0.0
+ * @since 2.0.0 Refactored to cssClass
* @var string
*/
- class:
+ cssClass:
{
type: String,
default: '',
},
/**
* CSS class to apply to wrapper when errors are available.
- * @since 1.0
+ * @since 1.0.0
* @var string
*/
classError:
@@ -363,10 +361,11 @@ Vue.component('vform', Vue.extend({
},
/**
* Input errors to listen to.
- * @since 1.0
+ * @since 1.0.0
+ * @since 2.0.0 Refactored to "value" in order to use v-model directive.
* @var object
*/
- response:
+ value:
{
type: [Object, Array],
default: function() {
@@ -394,10 +393,10 @@ Vue.component('vform', Vue.extend({
inputErrors: function()
{
var errors = [];
- if (this.response.errors !== undefined
- && this.response.errors[this.listen] !== undefined
+ if (this.value.errors !== undefined
+ && this.value.errors[this.listen] !== undefined
) {
- errors = this.response.errors[this.listen];
+ errors = this.value.errors[this.listen];
}
return errors;
},
@@ -575,17 +574,18 @@ Vue.component('vform', Vue.extend({
/**
* Adds error to response.
* @since 1.0.2
+ * @since 2.0.0 Remove $set.
*
* @param object options
*/
addError: function(options)
{
if (this.$parent.response === undefined)
- this.$parent.$set('response', {});
+ this.$parent.response = {};
if (this.$parent.response.errors === undefined)
- this.$parent.$set('response.errors', {});
+ this.$parent.response.errors = {};
if (this.$parent.response.errors[this.listen] === undefined)
- this.$parent.$set('response.errors.'+this.listen, []);
+ this.$parent.response.errors[this.listen] = [];
var message = this.$parent.errors[options[0]];
if (options.length > 1)
message = message.replace(/\%1\%/, options[1]);
@@ -594,22 +594,24 @@ Vue.component('vform', Vue.extend({
this.$parent.response.errors[this.listen].push(message);
},
},
- }),
+ },
/**
* Results.
* Handles response results.
* Vue sub component.
* @since 1.0.0
+ * @since 2.0.0 Refactored to Vue2.
*/
- 'results': Vue.extend({
+ 'results': {
props:
{
/**
* Results model.
* @since 1.0.0
+ * @since 2.0.0 Refactored to "value" to use v-model directive.
* @var mixed
*/
- model:
+ value:
{
type: [Array, Object, String],
default: function()
@@ -667,18 +669,19 @@ Vue.component('vform', Vue.extend({
/**
* Returns computed records.
* @since 1.0.0
+ * @since 2.0.0 Remove $set.
*
* @return array
*/
records: function()
{
- if (!this.$parent.hasMessage && Array.isArray(this.model)) {
+ if (!this.$parent.hasMessage && Array.isArray(this.value)) {
if (this.clearOnFetch) {
- this.$set('buffer', this.model);
+ this.buffer = this.value;
} else {
- for (var i in this.model) {
- if (this.model[i] !== undefined && this.model[i] !== null)
- this.buffer.push(this.model[i]);
+ for (var i in this.value) {
+ if (this.value[i] !== undefined && this.value[i] !== null)
+ this.buffer.push(this.value[i]);
}
}
}
@@ -700,6 +703,6 @@ Vue.component('vform', Vue.extend({
if (this.fetchOnready)
this.$parent.submit();
},
- }),
+ },
},
}));
\ No newline at end of file
diff --git a/dist/vue.form.min.js b/dist/vue.form.min.js
index f06a577..43e041e 100644
--- a/dist/vue.form.min.js
+++ b/dist/vue.form.min.js
@@ -1 +1 @@
-"use strict";Vue.component("vform",Vue.extend({props:{action:{type:String,"default":""},method:{type:String,"default":"POST"},headers:{type:Object,"default":function(){}},timeout:{type:[String,Number],"default":void 0},credentials:{type:[String,Boolean],"default":void 0},emulateHttp:{type:[String,Boolean],"default":void 0},emulateJson:{type:[String,Boolean],"default":void 0},errors:{type:Object,"default":function(){return{required:"Required field.",number:"Value must be numeric.",email:"Email value is invalid.",min:"Value must have at least %1% character(s).",min_number:"Value must be at least %1%.",max:"Value must have no more than %1% character(s).",max_number:"Value must be no more than %1%.",between:"Value must have between %1% to %2% characters.",between_number:"Value must be between %1% to %2%.",equals:"Value must be equal to %1%.",required_if:"Required field.",url:"Url value is invalid."}}},id:{type:[String,Number],"default":void 0},key:{type:[String,Number],"default":void 0},responseJson:{type:[String,Boolean],"default":!1},responseBlob:{type:[String,Boolean],"default":!1}},data:function(){return{request:{},isLoading:!1,response:{}}},computed:{hasMessage:function(){return void 0!=this.response.message},hasError:function(){return void 0!=this.response.error&&this.response.error}},methods:{submit:function(){var a=!0;this.$set("response",{});for(var b in this.$children)"function"==typeof this.$children[b].validate&&(a=this.$children[b].validate()&&a);a?(this.$set("isLoading",!0),this.$http(this.getOptions()).then(this.onSubmit,this.onError)):(this.$dispatch("vform_invalid",this.response.errors),this.$broadcast("vform_invalid",this.response.errors))},onSubmit:function(a){return this.$set("response",this.responseJson?a.json():this.responseBlob?a.blob():a.data),this.$dispatch("vform_success"),this.$broadcast("vform_success"),void 0!==this.response.errors&&Object.keys(this.response.errors).length>0&&(this.$dispatch("vform_invalid",this.response.errors),this.$broadcast("vform_invalid",this.response.errors)),void 0!==a.data.redirect?window.location=a.data.redirect:void this.onComplete()},onComplete:function(){this.$set("isLoading",!1),this.$dispatch("vform_complete"),this.$broadcast("vform_complete")},onError:function(a){console.log(a),this.$dispatch("vform_error",a),this.$broadcast("vform_error",a),this.onComplete()},getOptions:function(){var a={url:this.action,method:this.method};switch(void 0!==this.headers&&(a.headers=this.headers),void 0!==this.timeout&&(a.timeout=this.timeout),void 0!==this.credentials&&(a.credentials="boolean"==typeof this.credentials?this.credentials:"true"===this.credentials),void 0!==this.emulateHttp&&(a.emulateHTTP="boolean"==typeof this.emulateHttp?this.emulateHttp:"true"===this.emulateHttp),void 0!==this.emulateJson&&(a.emulateJSON="boolean"==typeof this.emulateJson?this.emulateJson:"true"===this.emulateJson),this.method){case"post":case"POST":case"put":case"PUT":case"patch":case"PATCH":a.body=this.request;break;default:a.params=this.request}return a}},components:{"input-handler":Vue.extend({template:'
{{error}}
',props:{listen:{type:String,"default":""},"class":{type:String,"default":""},classError:{type:String,"default":void 0},response:{type:[Object,Array],"default":function(){return{}}},validations:{type:String,"default":""}},computed:{inputErrors:function(){var a=[];return void 0!==this.response.errors&&void 0!==this.response.errors[this.listen]&&(a=this.response.errors[this.listen]),a},hasErrors:function(){return this.inputErrors.length>0},errorCss:function(){var a={};return void 0!==this.classError&&(a[this.classError]=this.hasErrors),a}},methods:{validate:function(){var a=!0,b=this.validations.split("|");for(var c in b){var d=b[c].split(":");switch(d[0]){case"required":void 0!==this.$parent.request[this.listen]&&0!==this.$parent.request[this.listen].length||(this.addError(d),a=!1);break;case"number":void 0!==this.$parent.request[this.listen]&&this.$parent.request[this.listen].length>0&&isNaN(this.$parent.request[this.listen])&&(this.addError(d),a=!1);break;case"min":if(d.length<2)throw"Minimum value is not defined in validation rules";void 0!==this.$parent.request[this.listen]&&this.$parent.request[this.listen].length>0&&this.$parent.request[this.listen].length0&&this.$parent.request[this.listen].length>parseInt(d[1])&&(this.addError(d),a=!1);break;case"max_number":if(d.length<2)throw"Minimum value is not defined in validation rules";void 0!==this.$parent.request[this.listen]&&parseInt(this.$parent.request[this.listen])>parseInt(d[1])&&(this.addError(d),a=!1);break;case"between":if(d.length<3)throw"One or all between values are not defined in validation rules";void 0!==this.$parent.request[this.listen]&&this.$parent.request[this.listen].length>0&&(this.$parent.request[this.listen].lengthparseInt(d[2]))&&(this.addError(d),a=!1);break;case"between_number":if(d.length<3)throw"One or all between values are not defined in validation rules";void 0!==this.$parent.request[this.listen]&&(parseInt(this.$parent.request[this.listen])parseInt(d[2]))&&(this.addError(d),a=!1);break;case"email":var e=/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;void 0!==this.$parent.request[this.listen]&&this.$parent.request[this.listen].length>0&&!e.test(this.$parent.request[this.listen])&&(this.addError(d),a=!1);break;case"equals":if(d.length<2)throw"Comparison field is not defined in validation rules";void 0!==this.$parent.request[this.listen]&&this.$parent.request[this.listen]!==this.$parent.request[d[1]]&&(this.addError(d),a=!1);break;case"required_if":if(d.length<2)throw"Comparison field is not defined in validation rules";void 0!==this.$parent.request[d[1]]&&this.$parent.request[d[1]].length>0&&(void 0===this.$parent.request[this.listen]||0===this.$parent.request[this.listen].length)&&(this.addError(d),a=!1);break;case"url":var e=/(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/;void 0!==this.$parent.request[this.listen]&&this.$parent.request[this.listen].length>0&&!e.test(this.$parent.request[this.listen])&&(this.addError(d),a=!1)}}return a},addError:function(a){void 0===this.$parent.response&&this.$parent.$set("response",{}),void 0===this.$parent.response.errors&&this.$parent.$set("response.errors",{}),void 0===this.$parent.response.errors[this.listen]&&this.$parent.$set("response.errors."+this.listen,[]);var b=this.$parent.errors[a[0]];a.length>1&&(b=b.replace(/\%1\%/,a[1])),a.length>2&&(b=b.replace(/\%2\%/,a[2])),this.$parent.response.errors[this.listen].push(b)}}}),results:Vue.extend({props:{model:{type:[Array,Object,String],"default":function(){return[]}},request:{type:Object,"default":function(){return{}}},fetchOnready:{type:[String,Boolean],"default":!1},clearOnFetch:{type:[String,Boolean],"default":!0}},data:function(){return{buffer:[]}},computed:{records:function(){if(!this.$parent.hasMessage&&Array.isArray(this.model))if(this.clearOnFetch)this.$set("buffer",this.model);else for(var a in this.model)void 0!==this.model[a]&&null!==this.model[a]&&this.buffer.push(this.model[a]);return this.buffer},hasRecords:function(){return this.records.length>0}},ready:function(){this.fetchOnready&&this.$parent.submit()}})}}));
\ No newline at end of file
+"use strict";Vue.component("vform",Vue.extend({props:{action:{type:String,"default":""},method:{type:String,"default":"POST"},headers:{type:Object,"default":function(){}},timeout:{type:[String,Number],"default":void 0},credentials:{type:[String,Boolean],"default":void 0},emulateHttp:{type:[String,Boolean],"default":void 0},emulateJson:{type:[String,Boolean],"default":void 0},errors:{type:Object,"default":function(){return{required:"Required field.",number:"Value must be numeric.",email:"Email value is invalid.",min:"Value must have at least %1% character(s).",min_number:"Value must be at least %1%.",max:"Value must have no more than %1% character(s).",max_number:"Value must be no more than %1%.",between:"Value must have between %1% to %2% characters.",between_number:"Value must be between %1% to %2%.",equals:"Value must be equal to %1%.",required_if:"Required field.",url:"Url value is invalid."}}},id:{type:[String,Number],"default":void 0},index:{type:[String,Number],"default":void 0},responseJson:{type:[String,Boolean],"default":!1},responseBlob:{type:[String,Boolean],"default":!1}},data:function(){return{request:{},isLoading:!1,response:{}}},computed:{hasMessage:function(){return void 0!=this.response.message},hasError:function(){return void 0!=this.response.error&&this.response.error}},methods:{submit:function(){var a=!0;this.response={};for(var b in this.$children)"function"==typeof this.$children[b].validate&&(a=this.$children[b].validate()&&a);a?(this.isLoading=!0,this.$http(this.getOptions()).then(this.onSubmit,this.onError)):this.$emit("invalid",this.response.errors)},onSubmit:function(a){return this.response=this.responseJson?a.json():this.responseBlob?a.blob():a.data,this.$emit("success",a),void 0!==this.response.errors&&Object.keys(this.response.errors).length>0&&this.$emit("invalid",this.response.errors),void 0!==a.data.redirect?window.location=a.data.redirect:void this.onComplete()},onComplete:function(){this.isLoading=!1,this.$emit("complete")},onError:function(a){this.$emit("error",a),this.onComplete()},getOptions:function(){var a={url:this.action,method:this.method};switch(void 0!==this.headers&&(a.headers=this.headers),void 0!==this.timeout&&(a.timeout=this.timeout),void 0!==this.credentials&&(a.credentials="boolean"==typeof this.credentials?this.credentials:"true"===this.credentials),void 0!==this.emulateHttp&&(a.emulateHTTP="boolean"==typeof this.emulateHttp?this.emulateHttp:"true"===this.emulateHttp),void 0!==this.emulateJson&&(a.emulateJSON="boolean"==typeof this.emulateJson?this.emulateJson:"true"===this.emulateJson),this.method){case"post":case"POST":case"put":case"PUT":case"patch":case"PATCH":a.body=this.request;break;default:a.params=this.request}return a}},components:{"input-handler":{template:'
',props:{listen:{type:String,"default":""},cssClass:{type:String,"default":""},classError:{type:String,"default":void 0},value:{type:[Object,Array],"default":function(){return{}}},validations:{type:String,"default":""}},computed:{inputErrors:function(){var a=[];return void 0!==this.value.errors&&void 0!==this.value.errors[this.listen]&&(a=this.value.errors[this.listen]),a},hasErrors:function(){return this.inputErrors.length>0},errorCss:function(){var a={};return void 0!==this.classError&&(a[this.classError]=this.hasErrors),a}},methods:{validate:function(){var a=!0,b=this.validations.split("|");for(var c in b){var d=b[c].split(":");switch(d[0]){case"required":void 0!==this.$parent.request[this.listen]&&0!==this.$parent.request[this.listen].length||(this.addError(d),a=!1);break;case"number":void 0!==this.$parent.request[this.listen]&&this.$parent.request[this.listen].length>0&&isNaN(this.$parent.request[this.listen])&&(this.addError(d),a=!1);break;case"min":if(d.length<2)throw"Minimum value is not defined in validation rules";void 0!==this.$parent.request[this.listen]&&this.$parent.request[this.listen].length>0&&this.$parent.request[this.listen].length0&&this.$parent.request[this.listen].length>parseInt(d[1])&&(this.addError(d),a=!1);break;case"max_number":if(d.length<2)throw"Minimum value is not defined in validation rules";void 0!==this.$parent.request[this.listen]&&parseInt(this.$parent.request[this.listen])>parseInt(d[1])&&(this.addError(d),a=!1);break;case"between":if(d.length<3)throw"One or all between values are not defined in validation rules";void 0!==this.$parent.request[this.listen]&&this.$parent.request[this.listen].length>0&&(this.$parent.request[this.listen].lengthparseInt(d[2]))&&(this.addError(d),a=!1);break;case"between_number":if(d.length<3)throw"One or all between values are not defined in validation rules";void 0!==this.$parent.request[this.listen]&&(parseInt(this.$parent.request[this.listen])parseInt(d[2]))&&(this.addError(d),a=!1);break;case"email":var e=/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;void 0!==this.$parent.request[this.listen]&&this.$parent.request[this.listen].length>0&&!e.test(this.$parent.request[this.listen])&&(this.addError(d),a=!1);break;case"equals":if(d.length<2)throw"Comparison field is not defined in validation rules";void 0!==this.$parent.request[this.listen]&&this.$parent.request[this.listen]!==this.$parent.request[d[1]]&&(this.addError(d),a=!1);break;case"required_if":if(d.length<2)throw"Comparison field is not defined in validation rules";void 0!==this.$parent.request[d[1]]&&this.$parent.request[d[1]].length>0&&(void 0===this.$parent.request[this.listen]||0===this.$parent.request[this.listen].length)&&(this.addError(d),a=!1);break;case"url":var e=/(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/;void 0!==this.$parent.request[this.listen]&&this.$parent.request[this.listen].length>0&&!e.test(this.$parent.request[this.listen])&&(this.addError(d),a=!1)}}return a},addError:function(a){void 0===this.$parent.response&&(this.$parent.response={}),void 0===this.$parent.response.errors&&(this.$parent.response.errors={}),void 0===this.$parent.response.errors[this.listen]&&(this.$parent.response.errors[this.listen]=[]);var b=this.$parent.errors[a[0]];a.length>1&&(b=b.replace(/\%1\%/,a[1])),a.length>2&&(b=b.replace(/\%2\%/,a[2])),this.$parent.response.errors[this.listen].push(b)}}},results:{props:{value:{type:[Array,Object,String],"default":function(){return[]}},request:{type:Object,"default":function(){return{}}},fetchOnready:{type:[String,Boolean],"default":!1},clearOnFetch:{type:[String,Boolean],"default":!0}},data:function(){return{buffer:[]}},computed:{records:function(){if(!this.$parent.hasMessage&&Array.isArray(this.value))if(this.clearOnFetch)this.buffer=this.value;else for(var a in this.value)void 0!==this.value[a]&&null!==this.value[a]&&this.buffer.push(this.value[a]);return this.buffer},hasRecords:function(){return this.records.length>0}},ready:function(){this.fetchOnready&&this.$parent.submit()}}}}));
\ No newline at end of file
diff --git a/package.json b/package.json
index 38e9028..502744d 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,8 @@
{
"name": "vue-form",
- "version": "1.0.9",
+ "version": "2.0.0",
"description": "Form component for Vue JS.",
- "main": "dist/vue.social-share.js",
+ "main": "dist/vue.form.min.js",
"repository": {
"type": "git",
"url": "https://github.com/10quality/vue-form.git"
@@ -25,5 +25,9 @@
"grunt": "^0.4.5",
"grunt-contrib-copy": "^0.8.2",
"grunt-contrib-uglify": "^0.11.0"
+ },
+ "dependencies": {
+ "vue": "^2.3.4",
+ "vue-resource": "^1.3.4"
}
}
diff --git a/src/vue.form.js b/src/vue.form.js
index bc778fc..b8f48b7 100644
--- a/src/vue.form.js
+++ b/src/vue.form.js
@@ -6,7 +6,7 @@
* @author Alejandro Mostajo
* @copyright 10Quality
* @license MIT
- * @version 1.0.9
+ * @version 2.0.0
*/
Vue.component('vform', Vue.extend({
props:
@@ -120,9 +120,10 @@ Vue.component('vform', Vue.extend({
/**
* Form loop key (in case it its used inside a v-for).
* @since 1.0.5
+ * @since 2.0.0 Refactored due to be a reserved name.
* @var string
*/
- key:
+ index:
{
type: [String, Number],
default: undefined,
@@ -199,22 +200,22 @@ Vue.component('vform', Vue.extend({
* @since 1.0.0
* @since 1.0.1 Options generated based on method.
* @since 1.0.2 Validations added.
+ * @since 2.0.0 Use $emit and remove $set.
*/
submit: function()
{
// Input validations
var isValid = true;
- this.$set('response', {});
+ this.response = {};
for (var i in this.$children) {
if (typeof(this.$children[i].validate) === 'function')
isValid = this.$children[i].validate() && isValid;
}
if (isValid) {
- this.$set('isLoading', true);
+ this.isLoading = true;
this.$http(this.getOptions()).then(this.onSubmit, this.onError);
} else {
- this.$dispatch('vform_invalid', this.response.errors);
- this.$broadcast('vform_invalid', this.response.errors);
+ this.$emit('invalid', this.response.errors);
}
},
/**
@@ -224,25 +225,21 @@ Vue.component('vform', Vue.extend({
* @since 1.0.3 Added event broadcast.
* @since 1.0.4 Response errors triggers invalid event.
* @since 1.0.9 Forces response conversion to jsob or blob.
+ * @since 2.0.0 Use $emit and remove $set.
*
* @param object response Response
*/
onSubmit: function(response)
{
- this.$set(
- 'response',
- this.responseJson
- ? response.json()
- : (this.responseBlob
- ? response.blob()
- : response.data
- )
- );
- this.$dispatch('vform_success');
- this.$broadcast('vform_success');
+ this.response = this.responseJson
+ ? response.json()
+ : (this.responseBlob
+ ? response.blob()
+ : response.data
+ );
+ this.$emit('success', response);
if (this.response.errors !== undefined && Object.keys(this.response.errors).length > 0) {
- this.$dispatch('vform_invalid', this.response.errors);
- this.$broadcast('vform_invalid', this.response.errors);
+ this.$emit('invalid', this.response.errors);
}
if (response.data.redirect !== undefined)
return window.location = response.data.redirect;
@@ -253,26 +250,25 @@ Vue.component('vform', Vue.extend({
* @since 1.0.0
* @since 1.0.1 Added event dispatch.
* @since 1.0.3 Added event broadcast.
+ * @since 2.0.0 Use $emit and remove $set.
*/
onComplete: function()
{
- this.$set('isLoading', false);
- this.$dispatch('vform_complete');
- this.$broadcast('vform_complete');
+ this.isLoading = false;
+ this.$emit('complete');
},
/**
* Handles submission error.
* @since 1.0.0
* @since 1.0.1 Added event dispatch.
* @since 1.0.3 Added event broadcast.
+ * @since 2.0.0 Use $emit instead.
*
* @param object e Error
*/
onError: function(e)
{
- console.log(e);
- this.$dispatch('vform_error', e);
- this.$broadcast('vform_error', e);
+ this.$emit('error', e);
this.onComplete();
},
/**
@@ -325,15 +321,16 @@ Vue.component('vform', Vue.extend({
* Input Handler.
* Handles input errors.
* Vue sub component.
- * @since 1.0.2
+ * @since 1.0.0
+ * @since 2.0.0 Refactored to Vue2.
*/
- 'input-handler': Vue.extend({
- template: '
{{error}}
',
+ 'input-handler': {
+ template: '
',
props:
{
/**
* Name of the error key to listen to.
- * @since 1.0
+ * @since 1.0.0
* @var string
*/
listen:
@@ -343,17 +340,18 @@ Vue.component('vform', Vue.extend({
},
/**
* CSS class to apply to wrapper.
- * @since 1.0
+ * @since 1.0.0
+ * @since 2.0.0 Refactored to cssClass
* @var string
*/
- class:
+ cssClass:
{
type: String,
default: '',
},
/**
* CSS class to apply to wrapper when errors are available.
- * @since 1.0
+ * @since 1.0.0
* @var string
*/
classError:
@@ -363,10 +361,11 @@ Vue.component('vform', Vue.extend({
},
/**
* Input errors to listen to.
- * @since 1.0
+ * @since 1.0.0
+ * @since 2.0.0 Refactored to "value" in order to use v-model directive.
* @var object
*/
- response:
+ value:
{
type: [Object, Array],
default: function() {
@@ -394,10 +393,10 @@ Vue.component('vform', Vue.extend({
inputErrors: function()
{
var errors = [];
- if (this.response.errors !== undefined
- && this.response.errors[this.listen] !== undefined
+ if (this.value.errors !== undefined
+ && this.value.errors[this.listen] !== undefined
) {
- errors = this.response.errors[this.listen];
+ errors = this.value.errors[this.listen];
}
return errors;
},
@@ -575,17 +574,18 @@ Vue.component('vform', Vue.extend({
/**
* Adds error to response.
* @since 1.0.2
+ * @since 2.0.0 Remove $set.
*
* @param object options
*/
addError: function(options)
{
if (this.$parent.response === undefined)
- this.$parent.$set('response', {});
+ this.$parent.response = {};
if (this.$parent.response.errors === undefined)
- this.$parent.$set('response.errors', {});
+ this.$parent.response.errors = {};
if (this.$parent.response.errors[this.listen] === undefined)
- this.$parent.$set('response.errors.'+this.listen, []);
+ this.$parent.response.errors[this.listen] = [];
var message = this.$parent.errors[options[0]];
if (options.length > 1)
message = message.replace(/\%1\%/, options[1]);
@@ -594,22 +594,24 @@ Vue.component('vform', Vue.extend({
this.$parent.response.errors[this.listen].push(message);
},
},
- }),
+ },
/**
* Results.
* Handles response results.
* Vue sub component.
* @since 1.0.0
+ * @since 2.0.0 Refactored to Vue2.
*/
- 'results': Vue.extend({
+ 'results': {
props:
{
/**
* Results model.
* @since 1.0.0
+ * @since 2.0.0 Refactored to "value" to use v-model directive.
* @var mixed
*/
- model:
+ value:
{
type: [Array, Object, String],
default: function()
@@ -667,18 +669,19 @@ Vue.component('vform', Vue.extend({
/**
* Returns computed records.
* @since 1.0.0
+ * @since 2.0.0 Remove $set.
*
* @return array
*/
records: function()
{
- if (!this.$parent.hasMessage && Array.isArray(this.model)) {
+ if (!this.$parent.hasMessage && Array.isArray(this.value)) {
if (this.clearOnFetch) {
- this.$set('buffer', this.model);
+ this.buffer = this.value;
} else {
- for (var i in this.model) {
- if (this.model[i] !== undefined && this.model[i] !== null)
- this.buffer.push(this.model[i]);
+ for (var i in this.value) {
+ if (this.value[i] !== undefined && this.value[i] !== null)
+ this.buffer.push(this.value[i]);
}
}
}
@@ -700,6 +703,6 @@ Vue.component('vform', Vue.extend({
if (this.fetchOnready)
this.$parent.submit();
},
- }),
+ },
},
}));
\ No newline at end of file
diff --git a/tests/test1.html b/tests/test1.html
index 4e9812d..0b8a48f 100644
--- a/tests/test1.html
+++ b/tests/test1.html
@@ -1,60 +1,65 @@
-
+
+