Vue2 how to only submit form values? - forms

I have a form page and I use it for both create and update
My form fields are like this;
enter image description here
content: (...)
i18n: (...)
image: (...)
name: (...)
orderIndex: (...)
position: (...)
I can successfully submit a request.
When we come to the update process, I get the data in this way and sync it. I'm getting extra data (this.myForm = response.data)
When I send an update request I just want the form fields to go but it goes like this
I don't want to send createdAt, deleted, updatedAt, _id fields
enter image description here
content: (...)
createdAt: (...)
deleted: (...)
i18n: (...)
image: (...)
isEnabled: (...)
name: (...)
orderIndex: (...)
position: (...)
updatedAt: (...)
_id: (...)
How can I submit only form fields? (I am using element-ui btw)
Is there something like this.$refs.myForm.fields or this.$refs.myForm.values I couldn't find it
For example Angular reactive form has something like this --> this.testimonialForm.patchValue(response.data);
data() {
return {
id: null,
testimonialForm: {
name: '',
position: '',
content: '',
orderIndex: '',
i18n: '',
image: {
path: ''
}
}
}
},
computed: {
...mapState({
testimonialData: state => state.testimonial.testimonial
})
},
created() {
if (this.$route.params.id) {
this.id = this.$route.params.id
this.fnGetTestimonialInfo(this.id)
}
},
methods: {
fnCreateTestimonial() {
this.$store.dispatch('testimonial/create', this.testimonialForm).then(() => {
this.$router.push('/testimonial/list')
})
},
fnUpdateTestimonial() {
const data = { id: this.id, data: this.testimonialForm }
this.$store.dispatch('testimonial/update', data).then(() => {
this.$router.push('/testimonial/list')
})
},
fnGetTestimonialInfo(id) {
this.$store.dispatch('testimonial/get', id).then(() => {
this.testimonialForm = this.testimonialData
})
},
}

Solved like this :
const pick = require('lodash/pick')
const formKeys = Object.keys(this.testimonialForm)
this.testimonialForm = pick(this.testimonialData, formKeys)
Thanks to #gguney for the guidance.

First of all, You have to fetch your object from backend. You do not neet to your store.
Just use axios to fetch your resource.
axios.get('/testimonial/get/' + id)
.then(function (response) {
this.testimonialForm = response.data.testimonial
console.log(response);
})
.catch(function (error) {
console.log(error);
});
You can use your inputs like:
<el-input
v-model="testimonialForm.name"
:placeholder="$t('form.name')"
name="name"
type="text"
/>
Then send your testimonialForm to your backend via axios.
You can add underscorejs to your project and use this function
_.pick(testimonialForm, 'name', 'otherField');

Related

Redux toolkit query. useLazyQuery

Try to understand how to structure queries.
What I have now:
File for CRUD:
export const PromoService = apiClient.injectEndpoints({
endpoints: (build) => ({
fetchPromoById: build.query<
Promotion,
{ ppeType: PpeType; id: string }
>({
query: ({ ppeType, id }) => apiQuery(ppeType, 'fetchPromoById', id),
providesTags: (_result, _err) => [{ type: 'Promo' }],
}),
fetchPromoByCategory: build.mutation<
PromotionData,
{ ppeType: PpeType; type: string; bannerId: string }
>({
query: ({ ppeType, type, bannerId }) => ({
url: apiQuery(ppeType, 'fetchPromoByCategory'),
method: 'POST',
body: fetchPromoByCategoryBody(type, bannerId),
}),
invalidatesTags: ['Promo'],
}),
}),
});
export const { useLazyFetchPromoByIdQuery, useFetchPromoByCategoryMutation } =
PromoService;
File for slices:
const initialState: PromotionState = {
chosenPromotion: {} as Promotion,
promoList: [],
};
const promoSlice = createSlice({
name: 'promo',
initialState,
reducers: {
setChosenPromotion: (state, action: PayloadAction<Promotion>) => {
state.chosenPromotion = action.payload;
},
setPromoList: (state, action: PayloadAction<Promotion[]>) => {
state.promoList = action.payload;
},
},
});
Component:
const [fetchPromoByCategory, { isLoading, data: categoryData }] =
useFetchPromoByCategoryMutation({
fixedCacheKey: 'shared-update-promo',
});
const [trigger, result] = useLazyFetchPromoByIdQuery();
const chosenPromo = result.data;
useEffect(() => {
chosenPromo && dispatch(setChosenPromotion(chosenPromo));
}, [chosenPromo]);
There is no problem get data from useMutation in different components skipping the stage of store data via reducer.
Just use fixedCacheKey and it works fine.
Is it possible to use similar approach for getting data in different components with useLazyQuery?
I use additional dispatch to store data from useLazyQuery but I'm sure it's not appropriate approach.
It is perfectly valid to have multiple different query cache entries at once, so useLazyQuery will not initialize to one of them - it will get it's arguments once you call the trigger function.
It looks like you should use useQuery here, sometimes with the skip parameter when you don't want anything fetched from the start.

How can I submit only form elements in Vue[2].js?

I have a form page and I use it for both create and update
My form fields are like this;
myForm: {
name: (...)
email: (...)
password: (...)
}
I can successfully submit a request.
When we come to the update process, I get the data in this way (this.myForm = response.data)
When I send an update request I just want the form fields to go but it goes like this
myForm: {
name: (...)
email: (...)
password: (...)
createdAt: (...)
updatedAt: (...)
_id: (...)
}
I don't want to send createdAt, updatedAt, _id fields
How can I submit only form fields in Vue.js or Element-ui? (I am using element-ui btw)
Is there something like this.$refs.myForm.fields or this.$refs.myForm.values I couldn't find it
My code: Code picture
<template>
<div class="app-container">
<el-form ref="myForm" label-position="top" :model="myForm">
<el-form-item>
<label>Name</label>
<el-input v-model="myForm.name" />
</el-form-item>
<el-form-item>
<label>Email</label>
<el-input v-model="myForm.email" />
</el-form-item>
<el-form-item>
<label>Password</label>
<el-input v-model="myForm.password" />
</el-form-item>
<el-button type="primary" #click="submitForm('myForm')">Kaydet</el-button>
</el-form>
</div>
</template>
<script>
export default {
name: 'UserForm',
data() {
return {
myForm: {
name: '',
email: '',
password: ''
}
}
},
created() {
if (this.$route.params.id) {
this.getFormData(this.$route.params.id)
}
},
methods: {
submitForm() {
if (!this.$route.params.id) {
this.$store.dispatch('user/create', this.myForm)
} else {
this.$store.dispatch('user/update/', this.myForm)
}
},
getFormData(id) {
this.$store.dispatch('user/get', id).then((response) => {
this.myForm = response.data
})
}
}
}
</script>
Instead of posting the entire 'this.myForm', just specify the fields you want to post in a new object.
submitForm() {
if (!this.$route.params.id) {
this.$store.dispatch('user/create', this.myForm)
} else {
this.$store.dispatch('user/update/', {
name: this.myForm.name,
email: this.myForm.email,
password: this.myForm.password
})
}
}
UPDATE: Following comments from OP, if you're expecting more that 'name', 'email', and 'password', you can just delete the properties you don't want to send.
submitForm() {
if (!this.$route.params.id) {
this.$store.dispatch('user/create', this.myForm)
} else {
delete this.myForm.createdAt,
delete this.myForm.updatedAt,
delete this.myForm._id
this.$store.dispatch('user/update/', this.myForm)
}
}

Why mockReturnValueOnce seems not to work?

I'm trying to use Jest along Meteor, but I'm getting the following problem while trying to implement tests using Collection.find().fetch().
I'm mocking the function find and fetch, as you can see below. However, the value return by fetch is always the first one.
Shouldn't the value be different every time, since I'm using mockReturnValueOnce?
import { describe, test } from "#jest/globals";
import { Users } from "../../../collections"; // a Mongo collection
describe("#Users test suite", () => {
const mock1 = {
userId: "111aaa",
email: "user1#test.com",
};
const mock2 = {
userId: "222bbb",
email: "user1#test.com",
};
const mock3 = {
userId: "333ccc",
email: "user1#test.com",
};
test("Fetch test", () => {
Users.find.mockImplementation(() => ({
fetch: jest
.fn()
.mockReturnValueOnce(mock1)
.mockReturnValueOnce(mock2)
.mockReturnValueOnce(mock3),
}));
// getting same result in every fetch call
console.log(Users.find().fetch()); // { userId: '111aaa', email: 'user1#test.com' }
console.log(Users.find().fetch()); // { userId: '111aaa', email: 'user1#test.com' }
console.log(Users.find().fetch()); // { userId: '111aaa', email: 'user1#test.com' }
});
});
Thanks in advance!

Copy nested objects from Axios response to my React-native hook?

Im simply trying to copy the Nested objects i get back from the axios GET request to my react-native hook. Not straightforward it seems. Data would look something like this for example:
[
{
_id: 61242b08013a5f26bd1b2d47,
user: '6110675d65e1528d03a8bce6',
totalCalories: 7,
totalProtein: 7,
createdAt: 2021-08-23T23:11:04.076Z,
updatedAt: 2021-08-24T00:53:38.621Z,
__v: 0
},
{
_id: 6125990e9669cc6b466c37b5,
user: '6110675d65e1528d03a8bce6',
__v: 0,
createdAt: 2021-08-25T01:12:44.343Z,
totalCalories: 2,
totalProtein: 2,
updatedAt: 2021-08-25T01:14:01.439Z
}
]
However, i get a component exception: undefined is not an object error, as well as a 404 error when trying to access it via historyData in my frontend. Here is my component which renders the history screen in my iOS app:
Frontend:
const History = () => {
const [currentUsersID, setCurrentUsersID] = React.useState("");
const [historyData, setHistoryData] = React.useState();
// Gets the current user's ID from local storage
const getData = async () => {
try {
const value = await AsyncStorage.getItem("#storage_Key");
if (value !== null) {
setCurrentUsersID(value);
}
} catch (error) {
console.log("Error reading AsyncStorage value -> " + error);
}
};
getData();
async function getHistory() {
try {
const response = await axios.get("http://localhost:5000/daysLog/getLog/" + currentUsersID);
setHistoryData(() => {
return response.data;
});
} catch (error) {
console.log("ERROR (getHistory) -> " + error);
}
}
useFocusEffect(
React.useCallback(() => {
getHistory();
})
);
return (
<SafeAreaView style={styles.container}>
<StatusBar barStyle="light-content" />
<Text style={{ color: "white" }}>
History: {historyData[0].totalCalories} // ERROR HERE
</Text>
</SafeAreaView>
);
};
Backend:
const router = require("express").Router();
let daysLog = require("../models/daysLog.model");
// getting the user's existing daysLogs
router.route("/getLog/:userID").get((req, res) => {
daysLog
.find({
user: req.params.userID,
})
.then((logs) => res.json(logs))
.catch((error) =>
res.status(400).json("Error (dayLog/GET) -> " + error)
);
});
historyData[0].totalCalories is throwing that because it will take time for it to get fetched while you're waiting for a response. You should have a block to test if historyData is not nul before you render the result.
Also get history focus effect relies on currentUser being valid but there's no expression that ensures it the way you wrote it. At best it's a race condition. Consider changing your focus effect to be a regulaf effect and make the currentUserId it's dependency.
Then inside of it to you can check if currentUserId is not null and start fetching get history accordingly.

Mongoose - pushing refs - cannot read property "push" of undefined

I would like to add a category and then if successed, push it's ref to user' collection. That's how I'm doing this:
That's mine "dashboard.js" file which contains categories schema.
var users = require('./users');
var category = mongoose.model('categories', new mongoose.Schema({
_id: String,
name: String,
ownerId: { type: String, ref: 'users' }
}));
router.post('/settings/addCategory', function(req, res, next) {
console.log(req.body);
var category_toAdd = new category();
category_toAdd._id = mongoose.Types.ObjectId();
category_toAdd.name = req.body.categoryName;
category_toAdd.ownerId = req.body.ownerId;
category.findOne({
name: req.body.categoryName,
ownerId: req.body.ownerId
}, function(error, result) {
if(error) console.log(error);
else {
if(result === null) {
category_toAdd.save(function(error) {
if(error) console.log(error);
else {
console.log("Added category: " + category_toAdd);
<<<<<<<<<<<<<<<<<<<THE CONSOLE LOG WORKS GOOD
users.categories.push(category_toAdd);
}
});
}
}
});
Here is my "users.js" file which contains "users" schema.
var categories = require('./dashboard');
var user = mongoose.model('users', new mongoose.Schema({
_id: String,
login: String,
password: String,
email: String,
categories: [{ type: String, ref: 'categories' }]
}));
So, the category add proccess works well and I can find the category in database. The problem is when I'm trying to push the category to user.
This line:
users.categories.push(category_toAdd);
I get this error:
Cannot read property "push" of undefined.
I need to admit once more that before that pushing there is console.log where the category is printed properly.
Thanks for your time.
The users object is a Mongoose model and not an instance of it. You need the correct instance of the users model to add the category to.
dashboard.js
...
category_toAdd = {
_id: mongoose.Types.ObjectId(),
name: req.body.categoryName,
ownerId: req.body.ownerId
};
// Create the category here. `category` is the saved category.
category.create(category_toAdd, function (err, category) {
if (err) console.log(err);
// Find the `user` that owns the category.
users.findOne(category.ownerId, function (err, user) {
if (err) console.log(err);
// Add the category to the user's `categories` array.
user.categories.push(category);
});
});