How to update mongoDB with custom component in list
vadymfrlv opened this issue · comments
Contact Details
No response
What happened?
In the list I created a custom component (checkbox). When I checked it or unchecked must be a record to DB to change status like false or true.
Could not understand what is wrong while trying to update a param of an object in DB through custom component in adminjs.
Receiving
Failed to load resource: the server responded with a status of 500 (Internal Server Error)
`
`
TypeError: Cannot read properties of undefined (reading 'params')
at handler (file:///Users/vadym.f/Documents/dev/admin-test/offerStatus.js:66:36)
at file:///Users/vadym.f/Documents/dev/admin-test/node_modules/adminjs/lib/backend/decorators/action/action-decorator.js:98:90
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
Bug prevalence
Every time I try to make a check
AdminJS dependencies version
{
"name": "admin-test",
"version": "1.0.0",
"description": "Admin test",
"main": "index.js",
"type": "module",
"scripts": {
"start": "nodemon index.js"
},
"author": "frlv",
"license": "ISC",
"dependencies": {
"@adminjs/design-system": "^4.1.0",
"@adminjs/express": "^6.1.0",
"@adminjs/mongoose": "^4.1.0",
"@babel/register": "^7.23.7",
"adminjs": "^7.7.0",
"express": "^4.18.3",
"express-formidable": "^1.2.0",
"mongoose": "^8.2.1"
},
"devDependencies": {
"@babel/cli": "^7.23.9",
"@babel/core": "^7.24.0",
"@babel/preset-env": "^7.24.0",
"@babel/preset-react": "^7.23.3",
"nodemon": "^3.1.0"
}
}
What browsers do you see the problem on?
No response
Relevant log output
No response
Relevant code that's giving you issues
//
index.js
//
import AdminJS from "adminjs"
import { buildRouter as AdminJSExpress } from "@adminjs/express"
import express from "express"
import mongoose from "mongoose"
import * as AdminJSMongoose from "@adminjs/mongoose"
import { componentLoader } from "./componentLoader.js"
import { OfferStatus } from "./offerStatus.js"
const PORT = 3000
const DB =
"mongodb+srv:/..."
AdminJS.registerAdapter({
Resource: AdminJSMongoose.Resource,
Database: AdminJSMongoose.Database,
})
const startAdminJS = async () => {
try {
await mongoose.connect(DB, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
console.log("Connected to MongoDB")
const app = express()
const admin = new AdminJS({
resources: [OfferStatus],
componentLoader: componentLoader,
})
const adminRouter = AdminJSExpress(admin)
app.use(admin.options.rootPath, adminRouter)
admin.watch()
app.listen(PORT, () => {
console.log(
`Listening on port ${PORT}, AdminJS server started on URL: http://localhost:${PORT}${admin.options.rootPath}`
)
})
} catch (error) {
console.error("Error starting AdminJS", error)
}
}
startAdminJS()
//
order.entity.js
//
import mongoose from "mongoose"
const orderSchema = new mongoose.Schema({
network_id: {
type: Number,
required: true,
},
offer_status: { type: Boolean, required: true },
})
export const Order = mongoose.model("Order", orderSchema)
//
offerStatus.js
//
import { Order } from "./order.entity.js"
import { Components } from "./componentLoader.js"
export const OfferStatus = {
resource: Order,
options: {
properties: {
_id: {
type: "string",
isVisible: {
edit: false,
show: false,
list: false,
filter: false,
},
},
offer_status: {
type: "boolean",
components: {
list: Components.CustomCheckbox,
},
},
},
actions: {
toggleStatus: {
actionType: "record",
handler: async (request, context) => {
const { record, resource } = context
const newValue = !record.params.offer_status
const updatedRecord = await resource.update(request.params.recordId, {
offer_status: newValue,
})
if (!updatedRecord) {
throw new Error("Record could not be updated")
}
return {
record: updatedRecord.toJSON(),
notice: {
message: "Status successfully toggled",
type: "success",
},
}
},
},
},
},
}
//
CustomCheckbox.jsx
//
import { useState } from "react"
import { CheckBox } from "@adminjs/design-system"
const CustomCheckbox = ({ record, property }) => {
const [checked, setChecked] = useState(record.params[property.name])
const handleChange = async () => {
const newValue = !checked
setChecked(newValue)
try {
await fetch(
`/admin/api/resources/Order/records/${record.id}/toggleStatus`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ offer_status: newValue }),
}
)
console.log("1")
} catch (error) {
console.error("Error to change status", error)
setChecked(!newValue)
}
}
return <CheckBox checked={checked} onChange={handleChange} />
}
export default CustomCheckbox
I'd honestly suggest using ApiClient
to send requests to the backend:
import { ApiClient } from 'adminjs'
const api = new ApiClient()
await api.recordAction({
recordId: record.id,
resourceId: 'Order',
actionName: 'toggleStatus',
method: 'post',
data: {
offer_status: newValue
}
})
TypeError: Cannot read properties of undefined (reading 'params')
doesn't really tell much except that it couldn't find a record with given id in the database. All record actions have a record set in context
even before before
hooks are run unless it cannot find that record.