Using methods inside of a method in Vue JS - vue.js

I'm trying to access a method within another method in Vue. I'm positive I saw this done in a tutorial I followed.
Here is my code
<template>
<button #click="submit">Submit</button>
</template>
<script>
export default {
name: 'FormExample',
methods: {
submit() {
validate();
alert('done');
},
validate() {
alert('validated')
}
},
}
</script>
When I trigger the submit() it says the validate is not defined.
I'm doing as i'd like to use the validate method in multiple methods without repeating code. Where should the validation code live if not as a method?

You need to use this for calling method.
methods: {
submit() {
this.validate();
alert('done');
},
validate() {
alert('validated')
}
},

Related

Call Method from Differnt Vue Component (file)

I need to call method from different vue component which resides in different file I've tried with ref and didn't work for me and I know this might be simple but im new to vue please help me to do this task.
Both files reside in same folder
DefinitionManager - need to call method inside this component
methods: {
closeDrawer() {
this.drawer = false;
}
DefinitionMaker - I need to call above method by this component method
methods: {
CallDrawerMethod() {
Call Method from Definition Manager component
}
just add a ref in the child component and call that.
<template>
<div>
<DefinitionManager ref="definationManager"/>
</div>
<t/emplate>
<script>
import DefinitionManager from './DefinitionManager.vue'
export default {
components: {
DefinitionManager
},
methods: {
CallDrawerMethod() {
this.$refs.definationManager.closeDrawer();
}
}
}
</script>

How to create a VForm component with validation functionality like Vuetify in Vue 2?

In Vuetify, you can set up code like below and the VForm component can automatically check if all inputs within VForm are valid without passing any props back and forth. How can I achieve this functionality for my own form and input components in Vue 2?
<template>
<v-form v-model="formIsValid">
<v-text-field :rules="[required]"></v-text-field>
</v-form>
</template>
<script>
data() {
return {
formIsValid: false
}
},
methods: {
required(val) {
return !!val || 'Required.'
}
}
</script>
You can explore vuetify source code to learn how they do that.
First, you have to understand provide/inject, https://v2.vuejs.org/v2/api/#provide-inject
A very simplified version of their concept is like below,
VForm.vue
export default {
data() {
return {
inputs: []
}
},
provide () {
// provide this Form component for child, so child can register itself
return { form: this }
},
methods: {
register(input) {
this.inputs.push(input);
},
validate() {
// loop through child registered inputs,
// run every child.validate() to validate all child
this.inputs.forEach(input => {
input.validate();
});
}
}
}
VInput.vue
export default {
props: {
rules: {
default: () => [],
type: Array
}
},
// inject parent VForm component
inject: ['form'],
created() {
// with inject above, you can use this.form to reference parent VForm
this.form.register(this);
},
methods: {
validate() {
// use rules to validate input
}
}
}
Usage
anything provide by v-form can be used in v-input with inject.
<template>
<v-form>
<v-input :rules="rules"/>
<v-form/>
</template>
Most of the logic is in these files, and vuetify did much more than the logic above. Learn to study open source code, open source project is awesome.
VForm: https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/components/VForm/VForm.ts
registrable mixin used by VForm:
https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/mixins/registrable/index.ts
VInput: https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/components/VInput/VInput.ts
validatable mixin used by VInput: https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/mixins/validatable/index.ts

Vue Dynamic Form Values AND Keys, with pre existing value for render, why not rendering?

I am trying to create a dynamic 'quick input' form with Vue.
A simple text input that has a dynamic data key so that I can change what I'm submitting to axios. I couldn't figure out how to get a dynamic key name coming from a prop eg
data() {
return {
DYNAMIC-NAME-FROM-PROP: value
}
}
So I've got a values: {} bit of data that gets filled by the props instead.
The code below achieves everything EXCEPT pre-rendering the existing value.
See the comments next to v-model in the tempate:
<template>
<div class="relative">
<input
type="text"
v-model="values[fieldName]" // This is not rendering on load
// v-model="values[this.$props.field]" -> 'this' is null error #input
#keydown.enter.prevent="submit"
/>
</div>
</template>
<script>
export default {
props: ["userId", "field", "preFill"],
data() {
return {
values: {},
fieldName: this.$props.field,
};
},
mounted() {
this.values[this.$props.field] = this.$props.preFill;
},
methods: {
submit() {
axios.post(`/admin/${this.userId}/update`, this.values).then(response => {
// success
});
}
}
};
</script>
Am I going about this completely wrong?
Or am I 'nearly there' and just need to fix the v-model render issue?
To set a dynamic key name on an object in javascript, it turns out you can use square brackets, as in:
{
[keyName] : value
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names
So my code is fixed by simply passing the prop as the key in the axios call:
submit() {
axios
.post(`/admin/${this.userId}/update`, {
[this.$props.field]: this.value
})
.then(response => {
// we out here
});
}

Extending Vue Lifecycle Hooks

I have a special application where I would like to run a method on every component when it is mounted. So I could have the method as a global mixin or something and then simply do..
mounted(){
this.mySpecialMethod();
}
However, I was wondering if it is possible to simply extend Vues mounted hook so the method is always run on every component when it is mounted. I have not been able to find in info on this.
If you really want to have everything call your mounted hook, you can use a global mixin.
Below, we have the mixin myMixin that will log to console every time something is mounted or destroyed. When you run the example, you can see that every time the plus button is clicked, it runs both the component's mounted hook as well as the mixin's hook.
If you want to extend this so that it can be reusable as a library, you can create a plugin out of it.
const foo = {
template: "<div #click='onClick'>hello</div>",
mounted() {
console.log("Foo's mounted");
},
methods: {
onClick() {
console.log("click");
}
}
}
const myMixin = {
mounted() {
console.log("I've been mounted");
},
destroyed() {
console.log("I've been destroyed");
}
};
Vue.mixin(myMixin);
const app = new Vue({
el: "#app",
data() {
return {
foos: []
};
},
components: {
foo
},
methods: {
add() {
this.foos.push("fizz");
},
remove() {
this.foos.pop();
}
}
});
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
<button #click="add()">+</button><button #click="remove()">-</button>
<ul>
<li v-for="f in foos">
<foo></foo>
</ul>
</div>

Vue - Call Function from facebook button inside Vue-Component

trying to implement the Facebook-Login button inside of a vue component. How can I call a function on the the surrounding component from the custom attribute "onLogin" from the button?
HTML
<complogin :page="page" inline-template v-if="page=='login'">
<div data-max-rows="1" onlogin="fbLogin()" data-size="medium" data-show-faces="false" data-auto-logout-link="false" class="div fb-login-button"></div>
</complogin>
JS
Vue.component('complogin',{
data: function() {
return { foo: "bar" }
},
methods: {
fbLogin:function() {
console.log("Hello!")
},
}
})
Found a solution:
Attached the Component-Method via lifecycle hook to the window event and then just called it.
loaded: function() {
window.componentMethod = this.componentMethod
}