In code below, I'm checking Id overlap.
I want to hand over the value set to the v-model as a payload
I'm using mapState, so I handed over this.info.userid, but it doesn't work.
It keeps saying that I'm referring to the undefined value.
What value should I refer to?
this is my registration.vue
<div class="user-details">
<div class="input-box">
<span class="details">아이디</span>
<div class="validate-box">
<Field
:rules="validateId"
type="text"
placeholder="아이디를 입력하세요"
v-model="info.userId"
name="userId"
required />
<ErrorMessage
class="error-box"
name="userId" />
</div>
<div>
<button #click="idCheck">
중복확인
</button>
</div>
</div>
</div>
import { mapState } from 'vuex'
import { Field, Form, ErrorMessage } from 'vee-validate';
methods: {
async idCheck() {
this.$store.dispatch('signup/idChecking', {
userId: this.info.userId
})
}
},
computed: {
...mapState('signup',{
info: 'Userinfo'
})
}
and code below is my store registration.js
state: {
Userinfo: {
userId: '',
password: '',
passwordConfirm: '',
userName: '',
birthDate: '',
phoneNumber: '',
email: '',
year: '',
month: '',
day: ''
}
},
actions: {
async idChecking(payload) {
const { userId } = payload
axios.get(`http://??.???.???.???:????/api/check/${userId}`)
.then(res => {
console.log(res)
})
.catch(error => {
console.log(error)
})
}
}
I resolve the problem.
I didn't put 'state' in async idChecking method.
async idChecking(state, payload) <- like this.
Related
I have a component that lists all the tasks.
When I create a task I want to show the date of creation on the added task and I want to list all the tasks.
The issue is all the tasks dates are converted to datetime now UTC.
<template>
<div class="tasks-wrapper">
<div class="tasks-header">
<h4>{{ $t('client.taskListingTitle') }}</h4>
<b-button variant="custom" #click="showAddTaskModal">{{ $t('client.addTask') }}</b-button>
</div>
<b-table
striped
hover
:items="tasks"
:fields="fields"
show-empty
:empty-text="$t('common.noResultsFound')">
<template #cell(createdOn)="data">
{{ formatDate(data.createdOn) }}
</template>
</b-table>
<AddTaskModal />
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
import AddTaskModal from '#/components/modals/AddTaskModal'
import moment from 'moment'
export default {
name: 'TaskListing',
components: {
AddTaskModal
},
data () {
return {
tasks: [],
fields: [
{ key: 'createdOn', label: this.$t('tasks.tableFields.date'), formatter: 'formatDate' },
{ key: 'domain', label: this.$t('tasks.tableFields.task') },
{ key: 'comment', label: this.$t('tasks.tableFields.comment') },
{ key: 'status', label: this.$t('tasks.tableFields.status') }
]
}
},
computed: {
...mapGetters('users', ['user'])
},
methods: {
...mapActions('tasks', ['fetchTasks']),
...mapActions('users', ['fetchUserById']),
formatDate: function (date) {
return moment(date).utc(true).format('DD.MM.YYYY HH:mm')
},
showAddTaskModal () {
this.$bvModal.show('addTaskModal')
}
},
async mounted () {
const currUserId = this.$router.history.current.params.id
if (this.user || this.user.userId !== currUserId) {
await this.fetchUserById(currUserId)
}
if (this.user.clientNumber !== null) {
const filters = { clientReferenceNumber: { value: this.user.clientNumber } }
this.tasks = await this.fetchTasks({ filters })
}
}
}
</script>
If I delete this:
<template #cell(createdOn)="data">
{{ formatDate(data.createdOn) }}
</template>
the dates are displayed correctly on the task lists, however, when a task is added an Invalid Date is shown. I need to refresh the page of it works.
Any ideas?
I've got a view and a component. I'm trying to do auth here.
As a user, I input username and password, click login. This emits the information to the parent component, which makes a fetch request to API gateway in AWS. This fetch response has a header X-Session-Id that I'm interested in.
I've got the emit bit working fine.
However, I'm unable to pass the header value back to the component, and I'm unable to set new_password_required to true, which would add a new input field for a new password, as well as replace the login button with a reset password button.
I feel like I need to do this with props, but I'm unable to successfully pass the values from parent to child.
Also, should the reset password bit have its own component?
Here's my code below. This is my first frontend, so I'm not familiar with how I am supposed to share it (e.g. with a playground). Also, I'm trying to stick to vanilla vue for now since I'm learning (I've only get vue-router installed I think)
parent:
<template>
<div id="app" class="small-container">
<login-form #login:user="loginUser($event)" />
</div>
</template>
<script>
import LoginForm from "#/components/LoginForm.vue";
export default {
name: "Login",
components: {
LoginForm
},
data() {
return {
session_id: String,
new_password_required: Boolean
};
},
methods: {
async loginUser(loginEvent) {
try {
const response = await fetch(
process.env.VUE_APP_API_GATEWAY_ENDPOINT + "/login/user",
{
method: "POST",
body: JSON.stringify(loginEvent)
}
);
const data = await response.json();
console.log(data);
if (data.headers["X-Session-Id"] != null) {
this.session_id = data.headers["X-Session-Id"];
this.new_password_required = true;
}
} catch (error) {
console.error(error);
}
},
async resetPassword(resetPasswordEvent) {
try {
const response = await fetch(
process.env.VUE_APP_API_GATEWAY_ENDPOINT + "/reset/user/password",
{
method: "POST",
body: JSON.stringify(resetPasswordEvent)
}
);
const data = await response.json();
console.log(data);
} catch (error) {
console.error(error);
}
}
}
};
</script>
Component:
<template>
<div id="login-form">
<h1>Serverless App</h1>
<form>
<label for="email_address">Email Address:</label><br />
<input
v-model="login_details.email_address"
type="text"
id="email_address"
name="email_address"
/><br />
<label for="password">Password:</label><br />
<input
v-model="login_details.password"
type="password"
id="password"
name="password"
/>
<label v-if="new_password_required" for="new_password"
>New Password:</label
><br />
<input
v-if="new_password_required"
v-model="login_details.new_password"
type="password"
id="new_password"
name="new_password"
/>
</form>
<button v-if="!new_password_required" #click="loginUser($event)">
Login
</button>
<button v-if="new_password_required" #click="resetPassword($event)">
Reset Password
</button>
</div>
</template>
<script>
export default {
name: "LoginForm",
props: {
session_id: String,
new_password_required: {
type: Boolean,
default: () => false
}
},
data() {
return {
login_details: {
email_address: "",
password: "",
new_password: ""
}
};
},
methods: {
loginUser() {
console.log("testing loginUser...");
const loginEvent = {
email_address: this.login_details.email_address,
password: this.login_details.password
};
this.$emit("login:user", loginEvent);
},
resetPassword() {
console.log("testing resetPassword...");
const resetPasswordEvent = {
email_address: this.login_details.email_address,
password: this.login_details.password,
new_password: this.login_details.new_password,
session_id: this.login_details.sessionId
};
this.$emit("reset:Password", resetPasswordEvent);
}
}
};
</script>
Your child component looks good, however, you need to pass the props through in the parent component as shown here:
<login-form #login:user="loginUser($event)" :session-id="xidhere"
:new-password-required="newPasswordRequired"/>
As these values are updated in the parent component, the child component should be updated.
As a note, name your props using camel case, and then use kebab-case in your HTML.
So your login-form props should be updated to:
props: {
sessionId: String,
newPasswordRequired: {
type: Boolean,
default: () => false
}
},
Also, as you are emitting the event to parent, there may be no need to send the session id to the child, just add this to your api call before you send it.
Figured it out. I created a new child component for resetting password. Perhaps it can be dry'd up a bit? I'm new at this. Happy for any pointers :)
PARENT
<template>
<div id="app" class="small-container">
<login-form v-if="!new_password_required" #login:user="loginUser($event)" />
<reset-password-form
v-if="new_password_required"
:session_id="session_id"
#reset:password="resetPassword($event)"
/>
</div>
</template>
<script>
import LoginForm from "#/components/LoginForm.vue";
import ResetPasswordForm from "#/components/ResetPasswordForm.vue";
export default {
name: "Login",
components: {
LoginForm,
ResetPasswordForm
},
data() {
return {
session_id: "",
new_password_required: false
};
},
methods: {
async loginUser(loginEvent) {
try {
const response = await fetch(
process.env.VUE_APP_API_GATEWAY_ENDPOINT + "/login/user",
{
method: "POST",
body: JSON.stringify(loginEvent)
}
);
const data = await response.json();
console.log(data);
if (data.headers["X-Session-Id"] != null) {
this.session_id = data.headers["X-Session-Id"];
this.new_password_required = true;
}
} catch (error) {
console.error(error);
}
},
async resetPassword(resetPasswordEvent) {
try {
const response = await fetch(
process.env.VUE_APP_API_GATEWAY_ENDPOINT + "/reset/user/password",
{
method: "POST",
body: JSON.stringify(resetPasswordEvent)
}
);
const data = await response.json();
console.log(data);
} catch (error) {
console.error(error);
}
}
}
};
</script>
CHILD: login-form
<template>
<div id="login-form">
<h1>Serverless Release Dashboard</h1>
<form>
<label for="email_address">Email Address:</label><br />
<input
v-model="login_details.email_address"
type="text"
id="email_address"
name="email_address"
/><br />
<label for="password">Password:</label><br />
<input
v-model="login_details.password"
type="password"
id="password"
name="password"
/>
</form>
<button #click="loginUser($event)">
Login
</button>
</div>
</template>
<script>
export default {
name: "LoginForm",
data() {
return {
login_details: {
email_address: "",
password: ""
}
};
},
methods: {
loginUser() {
console.log("testing loginUser...");
const loginEvent = {
email_address: this.login_details.email_address,
password: this.login_details.password
};
this.$emit("login:user", loginEvent);
}
}
};
</script>
CHILD: reset-password-form
<template>
<div id="reset-password-form">
<h1>Serverless Release Dashboard</h1>
<form>
<label for="email_address">Email Address:</label><br />
<input
v-model="login_details.email_address"
type="text"
id="email_address"
name="email_address"
/><br />
<label for="password">Password:</label><br />
<input
v-model="login_details.password"
type="password"
id="password"
name="password"
/>
<label for="new_password">New Password:</label><br />
<input
v-model="login_details.new_password"
type="password"
id="new_password"
name="new_password"
/>
</form>
<button #click="resetPassword($event)">
Reset Password
</button>
</div>
</template>
<script>
export default {
name: "ResetPasswordForm",
props: {
email_address: String,
password: String,
session_id: String
},
data() {
return {
login_details: {
email_address: "",
password: "",
new_password: "",
session_id: ""
}
};
},
methods: {
resetPassword() {
console.log("testing resetPassword...");
const loginEvent = {
email_address: this.email_address,
password: this.password,
new_password: this.login_details.new_password,
session_id: this.session_id
};
this.$emit("reset:password", loginEvent);
}
}
};
</script>
I'm new to Vue and i'm trying now to do a query update on q-autocomplete component (i have to use Quasar Framework).
This is the FormAdmin component:
<template>
<q-form #submit="submit" #reset="onReset" class="q-gutter-md">
<q-select
filled
v-model="form.UserId"
label="User Email"
use-input
hide-selected
fill-input
input-debounce="0"
:options="options"
#filter="filterFn"
hint="Mininum 2 characters to trigger autocomplete"
style="width: 250px; padding-bottom: 32px"
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
No results
</q-item-section>
</q-item>
</template>
</q-select>
<div>
<q-btn label="Submit" type="submit" color="primary"/>
<q-btn label="Reset" type="reset" color="primary" flat class="q-ml-sm" />
</div>
</q-form>
</template>
This is the basic code for the update function into the filterFn:
<script>
export default {
data () {
return {
model: null,
options: null,
}
},
props: ['form', 'submit'],
methods: {
filterFn (val, update, abort) {
if (val.length < 3) {
abort()
return
}
update(() => {
console.log(val);
})
},
onReset(){
},
}
}
</script>
I tried this code:
<script>
import gql from 'graphql-tag';
const stringOptions = gql`
query {
filterUsersListFirst {
UserEmail
}
}`
export default {
data () {
return {
model: null,
options: Object.values(stringOptions),
}
},
props: ['form', 'submit'],
methods: {
filterFn (val, update, abort) {
if (val.length < 3) {
abort()
return
}
this.$apollo.query({
query: gql`query($email: String!) {
filterUsersListByEmail(
email: $email
) {
UserEmail
}
}`,
variables: {
email: val,
}
}).then(data => {
console.log(JSON.stringyfy(data));
this.options = Object.values(data);
}).catch(error =>{
console.log({error});
});
},
onReset(){
},
}
}
</script>
I tried graphql query server-side and it works.
Also i tried to print data that the Promise returns and it results in:
{"data":{"filterUsersListByEmail":[{"UserEmail":"email1","__typename":"User"},{...}]},"loading":false,"networkStatus":7,"stale":false}
But i don't know how to append the query result in the q-select options.
I found myself the solution and i'll write it:
methods: {
filterFn (val, update, abort) {
if (val.length < 3) {
abort()
return
}
setTimeout(() => {
update(() => {
this.$apollo.query({
query: gql`query($email: String!) {
filterUsersListByEmail(
email: $email
) {
UserId
UserEmail
}
}`,
variables: {
email: val,
}
}).then(data => {
var emailList = [];
for(var i = 0; i < data.data.filterUsersListByEmail.length; i++)
{
emailList[i] = JSON.parse('{"label":"' + data.data.filterUsersListByEmail[i].UserEmail + '", "value":"' + data.data.filterUsersListByEmail[i].UserId + '"}');
}
this.options = usersList;
}).catch(error =>{
console.log({error});
});
})
}, 1000)
},
onReset(){
...
},
}
I am having an issue with calling a parent function:
Error in v-on handler: "TypeError: self.$parent.testAddCompontnet222 is not a function"
So i have setup a test function (method) in the following file called testAddCompontnet222()
parent file: PageAdd.vue
<template>
<b-container>
<b-container>
testVar2: (( {{ testVar2 }} ))
<b-button #click="testAddCompontnet222();">Add Test 2</b-button>
<SingleBlockTemplate v-if="componentTypeSelected == 1"></SingleBlockTemplate>
<TripleBlockTemplate v-if="componentTypeSelected == 2"></TripleBlockTemplate>
</b-container>
</b-container>
</template>
<script>
import axios from 'axios';
import SingleBlockTemplate from './component_templates/SingleBlockTemplate.vue';
import TripleBlockTemplate from './component_templates/TripleBlockTemplate.vue';
import ComponentAddForm from './ComponentAddForm.vue';
export default {
data(){
return {
title: 'Case Studies',
excerpt: 'some text here for reference',
slug: 'unique',
meta_title: 'title for search engines (should be the same as the page title)',
meta_description: 'meta descriptions for search engines',
meta_keywords: 'keywords',
order: '1',
status: '1',
showAddComponentForm: false,
error: false,
errors: {},
testVar2: '2',
newContentData: {},
componentTypeSelected: '2',
componentTypes: {},
componentList: {}
};
},
mounted: function () {
this.getComponentTypes();
//this.componentTypeToCreate =
},
methods: {
testAddCompontnet222(){
this.testVar2 = '222!';
console.log("test 222222!")
},
addPage(){
axios({
method: 'post',
url: this.$appAPI+'/twg-cms/page',
data: {
title: this.title,
excerpt: this.excerpt,
slug: this.slug,
meta_title: this.meta_title,
meta_description: this.meta_description,
meta_keywords: this.meta_keywords,
order: this.order,
status: this.status
}
}).then(response => {
console.log(response.data)
}).catch(e => {
console.log(e)
this.errors.push(e)
});
},
getComponentTypes(){
axios.get(this.$appAPI+`/twg-cms/component_types`)
.then((response) => {
this.componentTypes = response.data.data;
})
.catch(() => {
console.log('handle server error from here');
});
},
componentTypeOnChange(value){
//console.log(this.componentTypeSelected)
}
},
components: {
ComponentAddForm,
SingleBlockTemplate,
TripleBlockTemplate
}
}
</script>
I then attempt to call the function from a child element (imported file): TripleBlockTemplate.vue
I have tried using just this.$parent.testAddCompontnet222(); and as you can see below currently self.$parent.testAddCompontnet222();
But both return the same error. I have this working in exactly the same way on other components
<template>
<form autocomplete="off" #submit.prevent="addComponent" method="post">
<b-button #click="testAddCompontnet();">Add Test</b-button>
<p>This is a triple block component</p>
<ckeditor :editor="editor" v-model="content[0]" :config="editorConfig"></ckeditor>
<ckeditor :editor="editor" v-model="content[1]" :config="editorConfig"></ckeditor>
<ckeditor :editor="editor" v-model="content[2]" :config="editorConfig"></ckeditor>
<b-button #click="addComponent" variant="outline-primary">Save component</b-button>
</form>
</template>
<script>
import axios from 'axios';
import ClassicEditor from '#ckeditor/ckeditor5-build-classic';
export default {
data(){
return {<template>
<form autocomplete="off" #submit.prevent="addComponent" method="post">
<b-button #click="testAddCompontnet();">Add Test</b-button>
<p>This is a triple block component</p>
<ckeditor :editor="editor" v-model="content[0]" :config="editorConfig"></ckeditor>
<ckeditor :editor="editor" v-model="content[1]" :config="editorConfig"></ckeditor>
<ckeditor :editor="editor" v-model="content[2]" :config="editorConfig"></ckeditor>
<b-button #click="addComponent" variant="outline-primary">Save component</b-button>
</form>
</template>
<script>
import axios from 'axios';
import ClassicEditor from '#ckeditor/ckeditor5-build-classic';
export default {
data(){
return {
editor: ClassicEditor,
name: 'Name here',
class: 'Class here',
html_id: 'ID here',
content:[
'<div><h1>Title 1</h1><br /><p>some simple text here</p></div>',
'<div><h1>Title 2</h1><br /><p>some simple text here</p></div>',
'<div><h1>Title 3</h1><br /><p>some simple text here</p></div>'
],
editorConfig: {
// The configuration of the editor.
}
};
},
methods: {
testAddCompontnet(){
var self = this;
self.$parent.testAddCompontnet222();
console.log("test 222!")
},
addComponent(){
axios({
method: 'post',
url: this.$appAPI+'/twg-cms/component',
data: {
name: this.name,
content: JSON.stringify({content: this.content}),
class: this.class,
html_id: this.html_id
}
}).then(response => {
console.log(response.data)
}).catch(e => {
console.log(e)
this.errors.push(e)
});
}
}
}
</script>
editor: ClassicEditor,
name: 'Name here',
class: 'Class here',
html_id: 'ID here',
content:[
'<div><h1>Title 1</h1><br /><p>some simple text here</p></div>',
'<div><h1>Title 2</h1><br /><p>some simple text here</p></div>',
'<div><h1>Title 3</h1><br /><p>some simple text here</p></div>'
],
editorConfig: {
// The configuration of the editor.
}
};
},
methods: {
testAddCompontnet(){
var self = this;
self.$parent.testAddCompontnet222();
console.log("test 222!")
},
addComponent(){
axios({
method: 'post',
url: this.$appAPI+'/twg-cms/component',
data: {
name: this.name,
content: JSON.stringify({content: this.content}),
class: this.class,
html_id: this.html_id
}
}).then(response => {
console.log(response.data)
}).catch(e => {
console.log(e)
this.errors.push(e)
});
}
}
}
</script>
Finally here is a working method which i am currently not using...
The following code, would allow me to use the same/similar code to update/change the parent variable testVar1 to update it's parent: ComponentAddForm.vue below
testAddCompontnet(){
var self = this;
self.$parent.testVar1 = '11111! test;
console.log("test 222!")
},
ComponentAddForm.vue:
<template>
<b-container>
testVar1: (( {{ testVar1 }} ))
<b-button #click="testAddCompontnet222();">Add Test 2</b-button>
<SingleBlockTemplate v-if="this.componentTemplateId == 1"></SingleBlockTemplate>
<TripleBlockTemplate v-if="this.componentTemplateId == 2"></TripleBlockTemplate>
</b-container>
</template>
<script>
import axios from 'axios';
import SingleBlockTemplate from './component_templates/SingleBlockTemplate.vue';
import TripleBlockTemplate from './component_templates/TripleBlockTemplate.vue';
export default {
props: ['componentTemplateId'],
data(){
return {
name: 'Case Studies',
testVar1: '1'
};
},
mounted: function () {
this.showComponentTemplate();
},
methods: {
testAddCompontnet222(){
this.$parent.testVar2 = '222!';
console.log("we made it here <--------");
},
showComponentTemplate(){
if(this.componentTemplateId === '1'){
console.log('test 1')
}
if(this.componentTemplateId === '2'){
console.log('test 2')
}
}
},
components: {
SingleBlockTemplate,
TripleBlockTemplate
}
}
</script>
the model is Entity. No errors are thrown. The form gets submitted and a new Entity is saved. However, the description and title are both recorded as 'nil'. to here is src/components/NewEntity.vue:
<template>
<div class="entities">
<h1>Add Entity</h1>
<div class="form">
<div>
<input type="text" name="title" placeholder="TITLE" v-model="title">
</div>
<div>
<textarea rows="15" cols="15" placeholder="DESCRIPTION" v-model="description"></textarea>
</div>
<div>
<button class="app_entity_btn" #click="addEntity">Add</button>
</div>
</div>
</div>
</template>
<script>
import EntitiesService from '#/services/EntitiesService'
export default {
name: 'NewEntity',
data () {
return {
title: '',
description: ''
}
},
methods: {
async addEntity () {
await EntitiesService.addEntity({
title: this.title,
description: this.description
})
this.$router.push({ name: 'Entities' })
}
}
}
</script>
here is where the script imports from (for some reason SO would not initially allow me to include Services/Api.js):
services/EntitiesServices:
import Api from '#/services/Api'
export default {
fetchEntities () {
return Api().get('/entities')
},
addEntity (params) {
return Api().post('entities', {
title: params.title,
description: this.description
})
}
services/Api.js:
import axios from 'axios'
export default() => {
return axios.create({
baseURL: 'http://localhost:3000',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Access-Control-Allow-Origin': '*'
}
})
}
OG Solution by cperez
Depending on your server, you need to 'stringify' your parameters object within your post function in two possible ways. If your server accepts JSON, then:
return Api().post('entities',
JSON.stringify({
title: params.title,
description: this.description
})
)
If you server doesn't accept JSON, you have to convert the object into encoded URL parameters with the querystring module:
var qs = require('querystring');
return Api().post('entities',
qs.stringify({
title: params.title,
description: this.description
})
)