Just say my state was repeatitive as such:
state = {
customer: {
name: {
elementType: "input",
elementConfig: {
type: "text",
placeholder: "Your Name"
},
value: ""
},
street: {
elementType: "input",
elementConfig: {
type: "text",
placeholder: "Street"
},
value: ""
},
And I wanted to store the object data into a helper function so that I could add zip code, country, and so on so forth and not have my state be cluttered. Would your helper Function look like this? I am having trouble figuring out how to write such a function
const helperFunction = function({elementType, ElementConfig, type, placeholder, value}){
setState({elementType: 'some value', ElementConfig: {type: "", placeholder: ""}})
}
so I can call state = {
name: helperFunction()
}
I guess I really don't know how to write it but I want to show my thought process. I am sure it is easier than this. I am just new to coding. If someone could help me or link me to an article that would be awesome. Thanks.
If I understand your question and what you want behavior to be then I think you could either use a reference object with the shape you want and "default" values and copy, or create the utility function which would do the same but allow for some "configurability". If you are setting your initial state, either in a constructor or in the body, you can't call this.setState.
const referenceObject = {
elementType: "input",
elementConfig: {
type: "text",
placeholder: "",
},
value: "",
};
Then when you are declaring state shallow copy the reference object
state = {
name: { ...referenceObject },
};
If you are looking for a utility function to do this and set some values then one example could look as such.
const helperFunction = ({ elementConfig, ...config }) => ({
...referenceObject,
...config,
elementConfig: {
...referenceObject.elementConfig,
...elementConfig,
}
});
The idea being you shallow copy each level of nesting and apply the override/new value.
Initialize state with what you want to override
state = {
name: helperFunction({
elementConfig: { placeholder: 'Placeholder' },
}),
};
const referenceObject = {
elementType: "input",
elementConfig: {
type: "text",
placeholder: "",
},
value: "",
};
const helperFunction = ({
elementConfig,
...config
}) => ({
...referenceObject,
...config,
elementConfig: {
...referenceObject.elementConfig,
...elementConfig,
}
});
const state1 = {
name: { ...referenceObject
},
};
console.log(state1);
const state2 = {
name: helperFunction({
elementConfig: {
placeholder: 'My Custom Placeholder'
}
}),
};
console.log(state2);
Related
Using react multi select to choose a users interests that is saved in mongoDB. The issue is that I want the users already selected choices to be reflected within the multi-select even if i refresh. As currently if you refresh the page it clears the selections and if you submit changes with a blank interest spot, it creates an empty interest array.
user model
const model = mongoose.Schema(
{
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
role: {
type: String,
enum: [roles.ADMIN, roles.STUDENT, roles.ALUMNI],
},
name: {
type: String,
required: true,
},
major: {
type: String,
required: true,
},
minor: {
type: String,
required: false,
},
interests: {
type: Array ,
required: false,
default : []
},
profilePic: {
type: String,
required: false,
default : "/images/default.png"
}
},
{ timestamps: true }
);
module.exports = new mongoose.model("User", model);
How its stored in mongo
Code for multi-select and things involved with it
<Form.Group className="mb-3" controlId="formBasicPassword">
<Form.Label>Interests</Form.Label>
<Select
isMulti
name="colors"
options={colourOptions}
className="basic-multi-select"
classNamePrefix="select"
styles={customStyles}
value={colourOptions.filter(obj => selectedValue.includes(obj.value))} // set selected values
onChange={handleChange}
/>
</Form.Group>
const [selectedValue, setSelectedValue] = useState([]);
const handleChange = (e) => {
setSelectedValue(Array.isArray(e) ? e.map(x => x.value) : []);
}
const customStyles = {
option: (provided, state) => ({
...provided,
color: state.isSelected ? 'red' : 'black',
padding: 5,
})
}
const colourOptions = [
{ value: "Artificial Intelligence", label: "Artificial Intelligence" },
{ value: "Product Management", label: "Product Management" },
{ value: "Mental Health", label: "Mental Health" },
{ value: "Physics", label: "Physics" },
{ value: "Statistics", label: "Statistics" },
{ value: "Technology", label: "Technology" },
{ value: "Finance", label: "Finance" },
];
const handleSubmit = (e) => {
e.preventDefault();
const form = e.currentTarget;
e.stopPropagation();
setValidated(true);
if (form.checkValidity() === false) {
return;
}
const user = {
name: nameRef.current.value,
email: emailRef.current.value,
role: roleRef.current.value,
major: majorRef.current.value,
minor: minorRef.current.value,
interests: selectedValue,
profilePic: profilePicRef.current.value,
};
onSubmit(user);
};
visual representation of multi-select
Everything is working except loading the users already selected interests into the drop down multi select so that it doesn't clear a users interest if they don't re-choose their interests while changing something else and submitting it. Tried to do something with default values but the code value={colourOptions.filter(obj => selectedValue.includes(obj.value))} // set selected values is kind of messing with doing it that way.
I'm using NestJS in the vanillaJS way (because I can't write typescript) and I have a many-to-many relation from user to bubble.
I want to write a updateUser-Route in which I also want to be able to update the bubble-affiliation.
But when I do so like this:
user.controller.js:
#Patch(':id')
#Bind(Param('id'), Body())
async updateUser(id, body) {
if (Object.keys(body).length !== 0) {
return await this.userService.updateUser(id, body);
}
throw new BadRequestException('Missing Body');
}
user.service.js:
async updateUser(id, user) {
return await this.userRepository.update(id, user);
}
I get this error:
Cannot query across many-to-many for property bubble
This is my user.entity.js:
var EntitySchema = require('typeorm').EntitySchema;
var User = require('./user.model').User;
var Bubble = require('../bubble/bubble.model').Bubble;
module.exports = new EntitySchema({
name: 'User',
target: User,
columns: {
id: {
primary: true,
type: 'int',
},
handle: {
type: 'varchar',
},
lastCheck: {
type: 'datetime',
default: () => 'NOW()',
},
rating: {
type: 'int',
},
},
relations: {
bubble: {
type: 'many-to-many',
target: 'Bubble',
joinTable: true,
cascade: true,
},
},
});
in postman I try to call it like this:
{
"rating": 10,
"bubble": [{
"id": "1234"
}]
}
if I leave bubble out it works and rating gets updated. with bubble I get the error described above
I'm learning React and trying to make a small project by myself for the first time, but I'm having trouble with useEffect.
I'm trying to autofill a form with information from my backend. I can get it to autofill, but it continuously sends GET requests. This is what I have:
useEffect(() => {
axios
.get('/admin/edit-product' + location.search)
.then((res) => {
const updatedControls = {
...controlsState,
title: {
...controlsState.title,
value: res.data.title,
},
image: {
...controlsState.image,
value: res.data.image,
},
price: {
...controlsState.price,
value: res.data.price,
},
description: {
...controlsState.description,
value: res.data.description,
},
};
setControlsState(updatedControls);
})
.catch((err) => console.error(err));
}, [controlsState, location.search]);
I thought that the dependency array was supposed to stop it from running continuously, but I guess I'm missing something else.
Not sure if it's needed, but this is what my original state looks like:
const [controlsState, setControlsState] = useState({
title: {
elementType: 'input',
elementConfig: {
type: 'text',
},
label: 'Product Title: ',
value: '',
},
image: {
elementType: 'input',
elementConfig: {
type: 'url',
},
label: 'Image URL: ',
value: '',
},
price: {
elementType: 'input',
elementConfig: {
type: 'number',
},
label: 'Price: ',
value: '',
},
description: {
elementType: 'textarea',
elementConfig: {
name: 'description',
htmlFor: 'description',
},
label: 'Description: ',
value: '',
},
});
and location is from react-router-dom useLocation
You have given controlsState as a dependency for useEffect. But inside your useEffect you are using setControlsState which changes the value of controlsState. And since you have given controlsState as a dependency, useEffect will occur everytime any of its dependency changes. Hence it is repeatedly happening
If you want useEffect to run only once, give [] as second parameter:
useEffect(() => {
...your code...
}, [])
I've been trying to get it so I can put multiple "trainings" within the training type if since they would merge into each other once the user has both. However I can't seem to get it working and I'm stumped as to how to go about it.
Here is my trainingmodel:
const mongoose = require('mongoose')
const Schema = mongoose.Schema
let trainingSchema = new Schema({
name: {
type: String,
required: true,
unique: true
},
shortHand: {
type: String,
required: true,
unqiue: true
},
desc: { type: String },
office: {
type: Schema.Types.ObjectId,
ref: "Office"
},
isMerge: { type: Boolean, default: false},
mergeInto: [{
type: Schema.Types.ObjectId,
ref: "Training"
}]
})
module.exports = mongoose.model('Training', trainingSchema)
and here is my training object
/**
* Defines Training Type
*/
const TrainingType = new GraphQLObjectType({
name: "Training",
fields: {
id: { type: GraphQLID },
name: { type: GraphQLString },
shortHand: { type: GraphQLString },
desc: { type: GraphQLString },
office: {
type: require('./office').OfficeType,
resolve: async (office) => {
return await Office.findById(office.office)
}
},
isMerge: { type: GraphQLBoolean },
mergeInto: {
type: new GraphQLList(TrainingType), // This is the error line
resolve: async (training) => {
return await Training.find({id: training.id})
}
}
}
})
module.exports.TrainingType = TrainingType
Now obviously the error I get back is TrainingType is not defined, since I'm trying use something that hasn't fully been defined yet. But I've tried other ways like making a different objectType called MergesInto and then use it in the other. But that doesn't work either as one requires the other and one has to be defined before the other which will give me the error Is Not Defined. I can't seem to figure out how to get it working. Is this even possible?
fields can be either an object or a function that returns one. Making it a function will delay the execution of the code inside the function, so you can reference the TrainingType variable without an error.
const TrainingType = new GraphQLObjectType({
name: "Training",
fields: () => ({
...
mergeInto: {
type: new GraphQLList(TrainingType),
...
},
})
})
Basically i've made proyxy-component which renders different components based on what the :type is and it works great. The point is that I create a schema of the form controls and a separate data object where the data from the form controls is stored. Everything is working good but i have a problem when formData object contains nested objects.
In my example test.test1
How can i make the v-model value dynamic which is generated based on what the string is.
My Compoennt
<proxy-component
v-for="(scheme, index) in personSchema.list"
:key="index"
:type="scheme.type"
:props="scheme.props"
v-model="formData[personSchema.prefix][scheme.model]"
v-validate="'required'"
data-vv-value-path="innerValue"
:data-vv-name="scheme.model"
:error-txt="errors.first(scheme.model)"
></proxy-component>
Data
data() {
return {
selectOptions,
formData: {
person: {
given_names: '',
surname: '',
sex: '',
title: '',
date_of_birth: '',
place_of_birth: '',
nationality: '',
country_of_residence: '',
acting_as: '',
test: {
test1: 'test',
},
},
},
personSchema: {
prefix: 'person',
list: [
{
model: 'given_names',
type: 'custom-input-component',
props: {
title: 'Name',
},
},
{
model: 'surname',
type: 'custom-input-componentt',
props: {
title: 'Surname',
},
},
{
model: 'test.test1',
type: 'custom-input-component',
props: {
title: 'test 1',
},
},
{
model: 'sex',
type: 'custom-select-component',
props: {
title: 'Sex',
options: selectOptions.SEX_TYPES,
trackBy: 'value',
label: 'name',
},
},
],
},
};
},
I would recomment you to write a vue-method (under the data section) that returns the object for v-model
v-model="resolveObject(formData[personSchema.prefix][scheme.model])"
or
v-model="resolveObject([personSchema.prefix] , [scheme.model])"
There you can do handle the dot-notation and return the proper nested property.
I don't think it's possible directly with v-model, you can take a look at:
https://v2.vuejs.org/v2/guide/reactivity.html
Maybe the best solution would be use a watch (deep: true) as a workaround.
(I would try first to use watch properties inside formData[personSchema.prefix][scheme.model].)