将新的select2选项标签写入express

时间:2019-03-15 17:41:49

标签: javascript jquery ajax express jquery-select2

我正在Express应用程序中使用select2来创建一个输入框,用户可以在其中从列表中选择主题,并可以使用任何新添加的选项来更新此列表

我遇到的麻烦是select2在客户端运行,而我用来植入<option>标签(我想在其中添加新选项)的所有数据都是服务器端

我希望用户能够添加原始列表中不存在的主题,以便将来的用户可以看到新添加的选项(以及原始选项)

这些是我考虑过的实现这些目标的选项(以越来越高的需求):

  • 为每个添加的标签添加新的<option>Subject</option> html标签
  • 将新标签推送到数组中,然后从该数组中植入<option> s
  • <option>对象中获取json,并在标记创建时更新该对象
  • 从外部数据库(例如猫鼬)中植入<option>,并在创建标记时对其进行更新

据我所知,所有这些选项都要求我的客户端代码(select2-js)与服务器端代码(我的数组,.json文件或{{1} }模式),并且我不知道如何执行此操作

在目前的方法中,我尝试在mongoose调用(see here)中指定一个“本地” json文件作为我的数据源。但是,这不会为数据库提供任何选项,因此无法正常工作。

然后,我检查每个新标签是否存在于数组(select2)中,如果不存在,则将其添加到数据库中:

dataBase

但是,这种方法会将新标签添加到一个数组中,一旦刷新页面,该数组将被破坏,并且不会存储新标签。

如何修改此参数以加载服务器端数据(// Data to seed initial tags: var dataBase = [ { id: 0, text: 'Maths'}, { id: 1, text: 'English'}, { id: 2, text: 'Biology'}, { id: 3, text: 'Chemistry'}, { id: 4, text: 'Geography'} ]; $(document).ready(function() { $('.select2-container').select2({ ajax: { url: '../../subjects.json', dataType: 'json', }, width: 'style', multiple: true, tags: true, createTag: function (tag) { var isNew = false; tag.term = tag.term.toLowerCase(); console.log(tag.term); if(!search(tag.term, dataBase)){ if(confirm("Are you sure you want to add this tag:" + tag.term)){ dataBase.push({id:dataBase.length+1, text: tag.term}); isNew = true; } } return { id: tag.term, text: tag.term, isNew : isNew }; }, tokenSeparators: [',', '.'] }) }); // Is tag in database? function search(nameKey, myArray){ for (var i=0; i < myArray.length; i++) { if (myArray[i].text.toLowerCase() === nameKey.toLowerCase()) { return true } } return false }; json文档或任何其他最佳做法),并使用新添加的选项更新该数据(通过我的测试)?

3 个答案:

答案 0 :(得分:5)

您可以为此使用function func02(){ for (i = 1; i <= 5; i++){ document.write("&nbsp;&nbsp;func02 " + i + "<br>"); } } function func01(){ for(i = 1; i <= 3; i++){ document.write("func01 " + i + "<br>"); func02(); } } func01();select2:select事件。

select2:unselect
var dataBase = [{
    id: 0,
    text: 'Maths'
  },
  {
    id: 1,
    text: 'English'
  },
  {
    id: 2,
    text: 'Biology'
  },
  {
    id: 3,
    text: 'Chemistry'
  },
  {
    id: 4,
    text: 'Geography'
  }
];

$(document).ready(function() {
  $('.select2-container').select2({
    data: dataBase,
    placeholder: 'Start typing to add subjects...',
    width: 'style',
    multiple: true,
    tags: true,
    createTag: function(tag) {
      return {
        id: tag.term,
        text: tag.term,
        isNew: true
      };
    },
    tokenSeparators: [',', '.']
  })
  $(document).on("select2:select select2:unselect", '.select2-container', function(e) {
    var allSelected = $('.select2-container').val();
    console.log('All selected ' + allSelected);

    var lastModified = e.params.data.id;
    console.log('Last Modified ' + lastModified);

    var dbIdArray = dataBase.map((i) => i.id.toString());
    var allTagged = $('.select2-container').val().filter((i) => !(dbIdArray.indexOf(i) > -1))
    console.log('All Tagged ' + allTagged);
  });
});
.select2-container {
  width: 200px;
}

答案 1 :(得分:5)

在服务器端,您可以具有一个用于维护并返回标签数组的api。 如果要使该阵列即使在服务器关闭后也能持久存在,则可以将标签阵列存储在数据库中。

服务器端:

let dataBase = [
{ id: 0, text: 'Maths'},
{ id: 1, text: 'English'},
{ id: 2, text: 'Biology'},
{ id: 3, text: 'Chemistry'},
{ id: 4, text: 'Geography'}
];
//Assuming you have a nodejs-express backend
app.get('/tags', (req,res) => {
res.status(200).send({tags: dataBase});
} );

客户端:

$(document).ready(function() {
dataBase=[];
$.get("YOUR_SERVER_ADDRESS/tags", function(data, status){
console.log("Data: " + data + "\nStatus: " + status);
dataBase = data;
});

$('.select2-container').select2({
    data: dataBase,
    placeholder: 'Start typing to add subjects...',
    width: 'style',
    multiple: true,
    tags: true,
    createTag: function (tag) {
        var isNew = false;
        tag.term = tag.term.toLowerCase();
        console.log(tag.term);
        if(!search(tag.term, dataBase)){
            if(confirm("Are you sure you want to add this tag:" + tag.term)){
                dataBase.push({id:dataBase.length+1, text: tag.term});
                isNew = true;
                //Update the tags array server side through a post request
            }
        }
        return {
                    id: tag.term,
                    text: tag.term,
                    isNew : isNew
                };
    },
    tokenSeparators: [',', '.']
})
});

// Is tag in database?
function search(nameKey, myArray){
for (var i=0; i < myArray.length; i++) {
    if (myArray[i].text.toLowerCase() === nameKey.toLowerCase()) {
        return true
    }
}
return false
};

答案 2 :(得分:0)

这就是我最后得到的(感谢两个答案):

1。设置一个Mongoose数据库来容纳主题:

models/subjects.js

var mongoose = require("mongoose");

var SubjectSchema = new mongoose.Schema({
    subject: { type: String },
});

module.exports = mongoose.model("Subjects", SubjectSchema);

2。在Node JS Express后端中设置API路由:
routes/api.js

var express    = require("express");
var router = express.Router();
var Subjects = require("../models/subjects");

// GET route for all subjects in db
router.get("/api/subjects/all", function(req, res){
    Subjects.find().lean().exec(function (err, subjects) {
        return res.send(JSON.stringify(subjects));
    })
});

// POST route for each added subject tag
router.post("/api/subjects/save", function(req, res){
    var newSubject = {};
    newSubject.subject = req.body.subject;

    console.log("Updating db with:" + newSubject);

    var query = {subject: req.body.subject};

    var options = { upsert: true, new: true, setDefaultsOnInsert: true };

    // Find the document
    Subjects.findOneAndUpdate(query, options, function(error, subject) {
        if (error) return;
        console.log("Updated db enry: " + subject);
    });

    return res.send(newSubject);
});

3。设置select2输入字段:
public/js/select2.js

var dataBase=[];
$(document).ready(function() {
    // Get all subjects from api (populated in step 2) and push to dataBase array
    $.getJSON('/api/subjects/all')
    .done(function(response) {
        $.each(response, function(i, subject){
            dataBase.push({id: subject._id, text: subject.subject});
        })
        console.log("dataBase: " + dataBase);
    })
    .fail(function(err){
        console.log("$.getJSON('/api/subjects/all') failed")
    })

    // Get data from api, and on 'selecting' a subject (.on("select2:select"), check if it's in the dataBase. If it is, or the user confirms they want to add it to the database, send it to POST route, and save it to our Subjects db.

    $('.select2-container')
    .select2({
        ajax: {
        url : "/api/subjects/all",
        dataType: 'json',
        processResults: function (data) {
            return {
                results: $.map(data, function(obj) {
                    return { id: obj._id, text: obj.subject };
                    })
                };
            }
        },
        placeholder: 'Start typing to add subjects...',
        width: 'style',
        maximumSelectionLength: 5,
        multiple: true,

        createTag: function(tag) {
            return {
                id: tag.term,
                text: tag.term.toLowerCase(),
                isNew : true
            };
        },

        tags: true,
        tokenSeparators: [',', '.']
    })
    .on("select2:select", function(e) {
        if(addSubject(dataBase, e.params.data.text)){
            console.log(e.params.data.text + " has been approved for POST");
            ajaxPost(e.params.data.text)
        } else {
            console.log(e.params.data.text + " has been rejected");
            var tags = $('#selectSubject select').val();
            var i = tags.indexOf(e.params.data.text);
            console.log("Tags: " + tags);
            if (i >= 0) {
                tags.splice(i, 1);
                console.log("post splice: " + tags);
                $('select').val(tags).trigger('change.select2');
            }
        }
    })

    function ajaxPost(subject){
        console.log("In ajaxPost");
        var formData = {subject : subject}
        $.ajax({
            type : "POST",
            contentType : "application/json",
            url : "/api/subjects/save",
            data : JSON.stringify(formData),
            dataType : 'json'})
            .done(console.log("Done posting " + JSON.stringify(formData)))
            .fail(function(e) {
                alert("Error!")
                console.log("ERROR: ", e);
            });
    }

    function addSubject(subjects, input) {
        if (!input || input.length < 3) return false

        var allSubjects = [];

        $.each(subjects, function(i, subject){
            if(subject.text) allSubjects.push(subject.text.toLowerCase())
        });

        console.log("Here is the entered subject: " + input);

        if(allSubjects.includes(input)){
            console.log(input + " already exists")
            return true
        }

        if(confirm("Are you sure you want to add this new subject " + input + "?")){
            console.log(input + " is going to be added to the database");
            return true
        } 
        console.log(input + " will NOT to added to the database");
        return false
    }

});

这可行,但是我很想听听对此方法的反馈!