如何将按钮选中值添加到文章对象的category字段中?
文章分类选择功能实现问题及解决方案
问题背景
我正在搭建一个支持用户撰写文章的网站,用户提交表单就能保存文章。目前表单里的输入字段都能正常保存,但在做分类/标签系统时卡壳了。我想让用户能按分类(电视、电影、音乐等)筛选文章,这需要给文章加上分类属性。
当前代码情况
文章Schema
const ArticleSchema = new Schema({ title: { type: String, required: true }, content: { type: String, required: true }, author: { type: String }, createdAt: { type: Date, default: Date.now }, category: { type: String, enum: ["Television", "Movie"], }, });
表单代码
<form action="" method="POST"> <p class="main__article-p">Select Tags</p> <div class="main__article-category"> <button class="main__article-button">Television</button> <button class="main__article-button">Movie</button> <button class="main__article-button">Music</button> </div> <div class="form-group"> <label for="title">Write Your Title</label> <input name="title" required /> </div> <div class="form-group"> <label for="content">Write Your Content</label> <textarea name="content" required ></textarea> </div> <div class="form-group"> <label for="author"></label> <input name="author" value="<%= author.username %>" hidden /> </div> <button type="submit">Submit</button> </form>
POST请求处理代码
exports.article_create_post = [ // Validate and sanitize fields. body("title", "Title must not be empty.") .trim() .isLength({ min: 1 }) .escape(), body("content", "Content must not be empty.") .trim() .isLength({ min: 1 }) .escape(), body("author").trim().escape(), body("category").trim().escape(), // Process request after validation and sanitization. (req, res, next) => { // Extract the validation errors from a request. const errors = validationResult(req); // Create a Book object with escaped and trimmed data. const article = new Article({ title: req.body.title, content: req.body.content, author: req.body.author, category: req.body.category, }); if (!errors.isEmpty()) { // There are errors. Render form again with sanitized values/error messages. // Get all authors and genres for form. async.parallel((err, results) => { if (err) { return next(err); } res.render("article_form", { title: "Create Article", author: author.username, content: content, category: category, article, errors: errors.array(), }); }); return; } // Data from form is valid. Save article. article.save((err) => { if (err) { return next(err); } // Successful: redirect to new article record. res.redirect(article.url); }); }, ];
核心问题
表单顶部的分类按钮,点击后无法将对应值传递给文章的category属性,不知道如何实现选择分类并提交的功能。
解决方案
1. 修正Schema的枚举值
当前Schema的category枚举只包含Television和Movie,但表单里有Music选项,必须更新枚举列表,否则保存Music分类会报错:
category: { type: String, enum: ["Television", "Movie", "Music"], // 添加Music },
2. 两种表单分类选择实现方案
方案一:使用单选框(推荐,符合表单语义)
把原有的按钮改成单选框,再通过CSS样式模拟按钮外观,既保留表单原生的提交逻辑,又满足视觉需求。
修改表单的分类部分:
<div class="main__article-category"> <label class="category-label"> <input type="radio" name="category" value="Television" required> Television </label> <label class="category-label"> <input type="radio" name="category" value="Movie" required> Movie </label> <label class="category-label"> <input type="radio" name="category" value="Music" required> Music </label> </div>
添加CSS样式模拟按钮:
/* 隐藏原生单选框 */ .category-label input[type="radio"] { display: none; } /* 标签样式模拟按钮 */ .category-label { display: inline-block; padding: 8px 16px; margin: 0 8px; border: 1px solid #ccc; border-radius: 4px; cursor: pointer; } /* 选中状态样式 */ .category-label input[type="radio"]:checked + span { background-color: #007bff; color: white; }
方案二:使用隐藏字段+JavaScript处理按钮点击
如果必须保留原有的按钮结构,通过隐藏字段存储分类值,用JS监听按钮点击事件赋值:
修改表单,添加隐藏字段并给按钮加类型和数据属性:
<form action="" method="POST"> <p class="main__article-p">Select Tags</p> <!-- 添加隐藏字段存储分类值 --> <input type="hidden" name="category" id="categoryInput" required> <div class="main__article-category"> <!-- 把按钮类型设为button,避免点击直接提交表单 --> <button type="button" class="main__article-button" data-category="Television">Television</button> <button type="button" class="main__article-button" data-category="Movie">Movie</button> <button type="button" class="main__article-button" data-category="Music">Music</button> </div> <!-- 其他表单字段不变 --> </form>
添加JavaScript处理逻辑:
// 获取所有分类按钮和隐藏字段 const categoryButtons = document.querySelectorAll('.main__article-button'); const categoryInput = document.getElementById('categoryInput'); categoryButtons.forEach(button => { button.addEventListener('click', function() { // 移除所有按钮的选中样式 categoryButtons.forEach(btn => btn.classList.remove('selected')); // 给当前点击的按钮添加选中样式 this.classList.add('selected'); // 将当前按钮的分类值赋值给隐藏字段 categoryInput.value = this.dataset.category; }); });
添加选中状态的CSS样式:
.main__article-button.selected { background-color: #007bff; color: white; border-color: #007bff; }
3. 完善表单验证
在POST处理的验证规则里,添加category的必填和枚举校验:
body("category", "Category is required.") .trim() .isIn(["Television", "Movie", "Music"]) .escape(),
内容的提问来源于stack exchange,提问作者Dagger
相关产品推荐
相关产品推荐

