How to access an object property inside a function that's inside a class - class

I was trying to fetch the ID that has been created from a new class to use it as a data key, but I can't seem to be able to access it. How can be able to do so, kindly help.
My code has a class and a function that uses the class to create a new item and append it onto a main container in my html file.
I want to use the setAttribute method to add a data-key and link the ID that has been created by the function createProjectItem() in the class but it says that the new class(newProject) has not been defined.
class NewProject {
constructor(title) {
this.title = title;
}
createProjectItem() {
const projectArray = {
title: this.title,
id: Date.now(),
//ID TO BE ACCESSED ↑↑
};
projectArrayList.push(projectArray)
console.log(projectArrayList);
}
}
const createProjectList = document.querySelector(".create-projectList");
export default function createProjectFromClass() {
createProjectList.addEventListener("click",() => {
//Creates new class
const Titleinput = document.getElementById("project-title");
const titleText = Titleinput.value.trim();
if (titleText !== "") {
const newProject = new NewProject(titleText);
newProject.createProjectItem()
console.log(newProject.id);
Titleinput.value = "";
}
//Append new class to projects list
function appendProject() {
const container = document.querySelector(".projects");
const createProject = document.querySelector(".create-project")
const projectList = document.createElement("div");
projectList.setAttribute("class","project-list project-dynamic");
projectList.setAttribute("data-key",newProject.id)
//DATA KEY TO FETCH ID FROM NEW CLASS ↑↑
projectList.innerHTML = `
<p>Project name</p>
<i class="fa-solid fa-trash-can"></i>
`
container.insertBefore(projectList,createProject);
}
appendProject()
})
}
I access the property
let projectArrayList = [];
class NewProject {
constructor(title) {
this.title = title;
}
createProjectItem() {
const projectArray = {
title: this.title,
id: Date.now(),
};
projectArrayList.push(projectArray)
console.log(projectArrayList);
}
}
export default function createProjectFromClass() {
createProjectList.addEventListener("click",() => {
// Create a new project from project class
const Titleinput = document.getElementById("project-title");
const titleText = Titleinput.value.trim();
if (titleText !== "") {
const newProject = new NewProject(titleText);
newProject.createProjectItem()
console.log(newProject.id);
Titleinput.value = "";
}
//Append newProject to projects list
function appendProject() {
const container = document.querySelector(".projects");
const createProject = document.querySelector(".create-project")
const projectList = document.createElement("div");
projectList.setAttribute("class","project-list project-dynamic");
projectList.setAttribute("data-key","?????")
projectList.innerHTML = `
<p>Project name</p>
<i class="fa-solid fa-trash-can"></i>
`
container.insertBefore(projectList,createProject);
}
appendProject()
})
}

Related

React Query hook call from orval

I use orval to create interfaces, services and it also create React Query hooks. I have a hook that I cant figur out how to use. It wants some UseMutationOptions togheter with my data.
export const useGetUserContext = <TError = ErrorType<unknown>, TContext = unknown>(options?: {
mutation?: UseMutationOptions<
Awaited<ReturnType<typeof getUserContext>>,
TError,
{ data: UserContextRequest },
TContext
>;
request?: SecondParameter<typeof customInstance>;
}) => {
const { mutation: mutationOptions, request: requestOptions } = options ?? {};
const mutationFn: MutationFunction<Awaited<ReturnType<typeof getUserContext>>, { data: UserContextRequest }> = (
props,
) => {
const { data } = props ?? {};
return getUserContext(data, requestOptions);
};
return useMutation<Awaited<ReturnType<typeof getUserContext>>, TError, { data: UserContextRequest }, TContext>(
mutationFn,
mutationOptions,
);
};

Uncaught (in promise) TypeError: hobbies is not iterable at createHobby when using Prisma and Postgresql

So I'm very new to Prisma, and actually also to React. My Postgresql database works, but I'm trying to show the stored data in my application. My very simple table in the schema file looks like this:
model Hobby {
id Int #id #default(autoincrement())
title String
}
I'm using useContext to distribute my createHobby functionality, this is what the context file looks like.
export async function getServerSideProps() {
const hobbies: Prisma.HobbyUncheckedCreateInput[] = await prisma.hobby.findMany();
return {
props: {initialHobbies: hobbies},
};
}
export const HobbyContext = createContext({})
function Provider({ children, initialHobbies }){
const [hobbies, setHobbies] = useState<Prisma.HobbyUncheckedCreateInput[]>(initialHobbies);
const createHobby = async (title) => {
const body: Prisma.HobbyCreateInput = {
title,
};
await fetcher("/api/create-hobby", {hobby : body});
console.log(hobbies);
const updatedHobbies = [
...hobbies,
body
];
setHobbies(updatedHobbies);
const contextData = {
hobbies,
createHobby,
}
return (
<HobbyContext.Provider value={contextData}>
{children}
</HobbyContext.Provider>
);
};
export default HobbyContext;
export {Provider};
Here I get the following error Uncaught (in promise) TypeError: hobbies is not iterable at createHobby. Which refers to the const updatedHobbies = [...hobbies, body];
For more context, I have a HobbyCreate.tsx which creates a little hobby card that renders the title of the hobby, which is submitted with a form.
function HobbyCreate({updateModalState}) {
const [title, setTitle] = useState('');
const {createHobby} = useHobbiesContext();
const handleChange = (event) => {
setTitle(event.target.value)
};
const handleSubmit = (event) => {
event.preventDefault();
createHobby(title);
};
return (
...
<form onSubmit={handleSubmit}></form>
...
)
I can't really figure out what is going wrong, I assume somewhere when creating the const [hobbies, setHobbies] and using the initialHobbies.
I don't think you're using the Context API correctly. I've written working code to try and show you how to use it.
Fully typed hobby provider implementation
This is a fully typed implementation of your Provider:
import { createContext, useState } from 'react';
import type { Prisma } from '#prisma/client';
import fetcher from 'path/to/fetcher';
export type HobbyContextData = {
hobbies: Prisma.HobbyCreateInput[]
createHobby: (title: string) => void
};
// you could provide a meaningful default value here (instead of {})
const HobbyContext = createContext<HobbyContextData>({} as any);
export type HobbyProviderProps = React.PropsWithChildren<{
initialHobbies: Prisma.HobbyCreateInput[]
}>;
function HobbyProvider({ initialHobbies, children }: HobbyProviderProps) {
const [hobbies, setHobbies] = useState<Prisma.HobbyCreateInput[]>(initialHobbies);
const createHobby = async (title: string) => {
const newHobby: Prisma.HobbyCreateInput = {
title,
};
await fetcher("/api/create-hobby", { hobby: newHobby });
console.log(hobbies);
setHobbies((hobbies) => ([
...hobbies,
newHobby,
]));
};
const contextData: HobbyContextData = {
hobbies,
createHobby,
};
return (
<HobbyContext.Provider value={contextData}>
{children}
</HobbyContext.Provider>
);
}
export default HobbyContext;
export { HobbyProvider };
Using HobbyProvider
You can use HobbyProvider to provide access to HobbyContext for every component wrapped inside it.
For example, to use it in every component on /pages/hobbies your implementation would look like:
// /pages/hobbies.tsx
import { useContext, useState } from 'react';
import HobbyContext, { HobbyProvider } from 'path/to/hobbycontext';
export default function HobbiesPage() {
// wrapping the entire page in the `HobbyProvider`
return (
<HobbyProvider initialHobbies={[{ title: 'example hobby' }]}>
<ExampleComponent />
{/* page content */}
</HobbyProvider>
);
}
function ExampleComponent() {
const { hobbies, createHobby } = useContext(HobbyContext);
const [title, setTitle] = useState('');
return (
<div>
hobbies: {JSON.stringify(hobbies)}
<div>
<input
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<button onClick={() => createHobby(title)}>Create hobby</button>
</div>
</div>
);
}
Similarly, to make the context available throughout your entire website, you can use HobbyProvider in
/pages/_app.tsx.
Using getServerSideProps
To retrieve the initialHobbies from the database, your getServerSideProps would look something like this:
// /pages/hobbies.tsx
import type { Hobby } from '#prisma/client';
export async function getServerSideProps() {
// note: there is no need to use `Hobby[]` as prisma will automatically give you the correct return
// type depending on your query
const initialHobbies: Hobby[] = await prisma.hobby.findMany();
return {
props: {
initialHobbies,
},
};
}
You would have to update your page component to receive the props from getServerSideProps and set initialHobbies on HobbyProvider:
// /pages/hobbies.tsx
import type { InferGetServerSidePropsType } from 'next';
export default function HobbiesPage({ initialHobbies }: InferGetServerSidePropsType<typeof getServerSideProps>) {
return (
<HobbyProvider initialHobbies={initialHobbies}>
<ExampleComponent />
</HobbyProvider>
);
}
Note your page component and getServerSideProps function have to be exported from the same file

How to insert a draft-js custom component/block

I'm trying to insert my custom block to the editorState of draft-js's editor. I can't seem to find any detailed information on how to accomplish this.
Block Renderer:
const blockRendererFn = (contentBlock) => {
const type = contentBlock.getType();
if (type === 'CustomTestChipBlock') {
return {
component: CustomTestChipBlock,
editable: false,
props: {
foo: 'bar',
},
};
}
}
Block Render Map:
import { DefaultDraftBlockRenderMap } from "draft-js";
import { Map } from 'immutable';
const blockRenderMap = Map({
CustomTestChipBlock: {
element: 'div',
}
}).merge(DefaultDraftBlockRenderMap);
My custom block (material ui chip):
import { Chip } from "#mui/material";
const CustomTestChipBlock = (props) => {
const { block, contentState } = props;
const { foo } = props.blockProps;
const data = contentState.getEntity(block.getEntityAt(0)).getData();
console.log("foo: "+foo)
console.log("data: "+data)
return (
<Chip label="test" size="small"/>
)
}
Now my problem is when I try to insert my custom block. I assume my method of insertion must be wrong. I tried multiple insertion methods but due to lack of any detailed information on the subject, all of them ended up not even running the console.log inside my custom component.
Insertion:
const addChip = () => {
setEditorState(insertBlock("CustomTestChipBlock"));
}
const insertBlock = (type) => {
// This is where I can't find any detailed info at all
const newBlock = new ContentBlock({
key: genKey(),
type: type,
text: "",
characterList: List(),
});
const contentState = editorState.getCurrentContent();
const newBlockMap = contentState.getBlockMap().set(newBlock.key, newBlock);
const newEditorState = ContentState.createFromBlockArray(
newBlockMap.toArray()
)
.set("selectionBefore", contentState.getSelectionBefore())
.set("selectionAfter", contentState.getSelectionAfter());
return EditorState.push(editorState, newEditorState, "add-chip");
};

Trying to redirect user on valid contact form submission

Hi so I'm trying to make my page redirect to 'confirmationpage.html' only when all the fields are correctly entered. This is my Javascript, how would I go about doing this?
const form = document.getElementById('form');
const name = document.getElementById('name');
const email = document.getElementById('email');
const subject = document.getElementById('subject');
const text = document.getElementById('text');
form.addEventListener('submit', function(e) {
e.preventDefault();
checkInputs();
});
function checkInputs() {
// get values from the inputs
const nameValue = name.value.trim();
const emailValue = email.value.trim();
const subjectValue = subject.value.trim();
const textValue = text.value.trim();
if(nameValue === '') {
// show error message
// add error class
setErrorFor(name, 'Name cannot be blank');
} else {
// add success class
setSuccessFor(name);
}
if(emailValue === '') {
setErrorFor(email, 'Email cannot be blank');
} else if(!isEmail(emailValue)) {
setErrorFor(email, 'Please enter a valid email address');
} else {
setSuccessFor(email);
}
if(subjectValue === '') {
setErrorFor(subject, 'A subject is required');
} else {
setSuccessFor(subject);
}
if(textValue === '') {
setErrorFor(text, 'Please add some text');
} else {
setSuccessFor(text);
}
}
function setErrorFor(input, message) {
const formControl = input.parentElement; // .form-control
const small = formControl.querySelector('small');
// add error message
small.innerText = message;
// add error class
formControl.className = 'form-control error';
}
function setSuccessFor(input) {
const formControl = input.parentElement;
formControl.className = 'form-control success';
}
function isEmail(email) {
return /^(([^<>()[\]\\.,;:\s#"]+(\.[^<>()[\]\\.,;:\s#"]+)*.test(email);
}
Any help would be very appreciated! I'm very new to webpage design and I've been struggling a lot recently

disabled submit button after submitting form data to server. in react native

I am new to react native. I have created a form from where I am sending some data to server. Now I want that to disabled submit button after user click on submit . once user submit data then after He unable to send data. means I want to avoid duplicate entry. please help. thanks. if possible also tell how to do it with functional component too.
here is my code
export default function Add(props) {
const { navigation } = props
const offset = (Platform.OS === 'android') ? -200 : 0;
const [AmazonError, setAmazonError] = useState([]);
const [Amazon, setAmazon] = useState('');
const [AmazonCNError, setAmazonCNError] = useState([]);
const [AmazonCN, setAmazonCN] = useState('');
const [AEPSError, setAEPSError] = useState([]);
const [AEPS, setAEPS] = useState('');
const [DMTError, setDMTError] = useState([]);
const [DMT, setDMT] = useState('');
const [BBPSError, setBBPSError] = useState([]);
const [BBPS, setBBPS] = useState('');
const [leadTagNumber, setLeadTagNumber] = useState([]);
const validateInputs = () => {
if (!Amazon.trim()) {
setAmazonError('Please Fill The Input')
return;
}
if (!AmazonCN.trim()) {
setAmazonCNError('Please Fill The Input')
return;
}
if (!AEPS.trim()) {
setAEPSError('Please Fill The Input')
return;
}
if (!DMT.trim()) {
setDMTError('Please Fill The Input')
return;
}
if (!BBPS.trim()) {
setBBPSError('Please Fill The Input')
return;
}
else
{
//+++++++++++++++++++++++++++++++++=submitting form data to api start+++++++++++++++++++++++++++++++++++
{
const leadTagNumber = props.route.params.leadTagNumber
AsyncStorage.multiGet(["application_id", "created_by",'leadTagNumber']).then(response => {
// console.log(response[0][0]) // Key1
console.log(response[0][1]) // Value1
// console.log(response[1][0]) // Key2
console.log(response[1][1]) // Value2
console.log(leadTagNumber)
fetch('https://xyxtech/Android_API_CI/uploaddata/tbservice_details', {
method: 'POST',
headers: {'Accept': 'application/json, text/plain, */*', "Content-Type": "application/json" },
// We convert the React state to JSON and send it as the POST body
body: JSON.stringify([{ data}])
})
.then((returnValue) => returnValue.json())
.then(function(response) {
console.log(response)
Alert.alert("File uploaded");
return response.json();
});
});
// event.preventDefault();
}
//+++++++++++++++++++++++++++++++++submitting form data to api end++++++++++++++++++++++++++++++++++++++
Alert.alert("success")
return;
//}
}
};
const handleAmazon = (text) => {
setAmazonError('')
setAmazon(text)
}
const handleAmazonCN= (text) => {
setAmazonCNError('')
setAmazonCN(text)
}
const handleAEPS= (text) => {
setAEPSError('')
setAEPS(text)
}
const handleDMT = (text) => {
setDMTError('')
setDMT(text)
}
const handleBBPS = (text) => {
setBBPSError('')
setBBPS(text)
}
return (
<View style={{flex: 1}}>
<ScrollView style={{flex: 1,}} showsVerticalScrollIndicator={false}>
<TextInput
maxLength={30}
placeholder="AEPS (Adhar enabled payment system) *"
style={styles.inputStyle}
onChangeText={(text)=>handleAEPS(text)}
defaultValue={AEPS}
value = {AEPS} />
<Text>{AEPSError}</Text>
</ScrollView>
<Button
style={styles.inputStyleB}
title="Submit"
color="#FF8C00"
onPress={() => validateInputs()}
/>
</View>
)
}
Set new state property to enable/disable button
const [disableButton, setDisableButton] = useState(false);
Now in your button component, add disabled property with disableButton state.
<Button
style={styles.inputStyleB}
title="Submit"
color="#FF8C00"
onPress={() => validateInputs()}
disabled={disableButton}
/>
Disable you button before fetching data
setDisableButton(true) //Add this
const leadTagNumber = props.route.params.leadTagNumber
Incase of fetch error or after fetching is complete, enable button again
setDisabledButton(false)