Added text-field component to edit database text without it getting bashed by data cleaning

This commit is contained in:
Thaum Rystra
2019-02-06 19:38:27 +02:00
parent de4509ab6a
commit f8e83ebe7e
5 changed files with 93 additions and 15 deletions

View File

@@ -1,10 +1,10 @@
<template lang="html"> <template lang="html">
<div> <div>
<attribute-edit <attribute-edit
v-for="attribute in attributes" v-for="(attribute, index) in attributes"
:key="attribute._id" :key="attribute._id"
:attribute="attribute" :attribute="attribute"
@change="log" @change="e => change(index, e)"
/> />
</div> </div>
</template> </template>
@@ -35,10 +35,9 @@
], ],
}}, }},
methods: { methods: {
log: console.log,
change(index, e){ change(index, e){
for (let i in e){ for (let i in e){
this.attributes[index][i] = e[i]; this.attributes[index][i] = e[i].trim();
} }
}, },
}, },

View File

@@ -1,23 +1,23 @@
<template lang="html"> <template lang="html">
<div> <div>
<v-text-field <text-field
label="Name" label="Name"
:value="attribute.name" :value="attribute.name"
/> />
<v-text-field <text-field
label="Variable name" label="Variable name"
:value="attribute.variableName" :value="attribute.variableName"
@change="variableName => $emit('change', {variableName})" @change="variableName => $emit('change', {variableName})"
hint="Use this name in formulae to reference this attribute" hint="Use this name in formulae to reference this attribute"
/> />
<v-text-field <text-field
label="Base Value" label="Base Value"
type="number" type="number"
:value="attribute.baseValue" :value="attribute.baseValue"
@change="baseValue => $emit('change', {baseValue})" @change="baseValue => $emit('change', {baseValue})"
hint="This is the value of the attribute before effects are applied" hint="This is the value of the attribute before effects are applied"
/> />
<v-text-field <text-field
label="Damage" label="Damage"
type="number" type="number"
:value="-attribute.adjustment" :value="-attribute.adjustment"
@@ -46,7 +46,7 @@
:menu-props="{auto: true, lazy: true}" :menu-props="{auto: true, lazy: true}"
@change="reset => $emit('change', {reset})" @change="reset => $emit('change', {reset})"
/> />
<v-text-field <text-field
label="Reset Multiplier" label="Reset Multiplier"
type="number" type="number"
:value="attribute.resetMultiplier" :value="attribute.resetMultiplier"

View File

@@ -0,0 +1,75 @@
<template lang="html">
<v-text-field
:error="error"
:value="safeValue"
@input="input"
@focus="focused = true"
@blur="focused = false"
/>
</template>
<script>
/*
* Component to handle text fields that update the database.
* Won't bash the text field while it's focused, even if the database trims
* or otherwise sanitizes the input.
* Emits input events on every input and emits debounced change
* events based on the debounceTime set in its props.
* Losing focus will set the value to the database's current stored value.
*
* Because attributes that aren't properties are passed to the root element,
* this is a drop-in replacement for v-text-field
*
* TODO extract this functionality as a mixin, and share to textarea
*/
import { _ } from 'underscore';
export default {
data(){ return {
safeValue: this.value,
focused: false,
error: false,
errorMessages: null,
}},
props: {
value: [String, Number],
debounceTime: {
type: Number,
default: 250,
},
validator: Function,
},
watch: {
focused(isFocused){
if (!isFocused){
this.safeValue = this.value;
}
},
value(newValue){
if (!this.focused){
this.safeValue = this.value;
}
},
},
methods: {
input(val){
this.$emit('input', val);
this.update(val);
if (this.validator){
try {
this.validator(val);
this.error = false;
this.errorMessages = null;
} catch(e){
this.error = true;
this.errorMessages = e.message;
}
}
},
},
created(){
this.update = _.debounce(val => {
this.$emit('change', val);
}, this.debounceTime);
},
};
</script>

View File

@@ -8,13 +8,17 @@ import router from "/imports/ui/router.js";
import "vuetify/dist/vuetify.min.css"; import "vuetify/dist/vuetify.min.css";
import theme from '/imports/ui/theme.js'; import theme from '/imports/ui/theme.js';
// Global components
import TextField from '/imports/ui/components/global/TextField.vue';
Vue.component("text-field", TextField);
Vue.use(VueMeteorTracker); Vue.use(VueMeteorTracker);
Vue.use(Vuetify, { Vue.use(Vuetify, {
theme, theme,
iconfont: "md", iconfont: "md",
}); });
// App start // App start
Meteor.startup(() => { Meteor.startup(() => {
// Start the Vue app // Start the Vue app

10
app/package-lock.json generated
View File

@@ -104,7 +104,7 @@
}, },
"block-stream": { "block-stream": {
"version": "0.0.9", "version": "0.0.9",
"resolved": false, "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
"integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
"requires": { "requires": {
"inherits": "~2.0.0" "inherits": "~2.0.0"
@@ -483,7 +483,7 @@
}, },
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"resolved": false, "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
}, },
"ini": { "ini": {
@@ -1405,7 +1405,7 @@
"dependencies": { "dependencies": {
"readable-stream": { "readable-stream": {
"version": "2.3.6", "version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"requires": { "requires": {
"core-util-is": "~1.0.0", "core-util-is": "~1.0.0",
@@ -1448,7 +1448,7 @@
"dependencies": { "dependencies": {
"readable-stream": { "readable-stream": {
"version": "2.3.6", "version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"requires": { "requires": {
"core-util-is": "~1.0.0", "core-util-is": "~1.0.0",
@@ -1835,7 +1835,7 @@
"dependencies": { "dependencies": {
"minimist": { "minimist": {
"version": "1.2.0", "version": "1.2.0",
"resolved": false, "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
} }
} }