无法在NodeJS / ExpressJS

时间:2016-11-19 13:37:04

标签: mysql angularjs node.js express dom

美好的一天,hoomans!我非常需要你的帮助!

我的问题:有没有办法(在NodeJS / ExpressJS中)动态改变一个元素,例如在POST请求时添加新的li,就像点击提交按钮后一样(不使用jsdom)? < / p>

我正在开发一个非常简单的应用程序,它应该允许客户(学生)通过简单的动态和实时功能跟踪他/她的每个班级的课程,监控他/她的成绩等。我正在使用Node.js EXPRESS,mySQL和AngularJS。

我创建了一个功能,学生可以搜索课程,然后实时收到结果列表,这基本上意味着我想根据请求动态添加 li 元素,而无需重新加载页面或重定向客户到另一页。

过程是:(1)学生在课程名称中输入,(2)请求时传递文本字段的值(帖子)(3)使用该值作为数据库搜索的关键,(4)然后通过填充 ul 元素。

数据库的工作原理。它能够使用在文本字段中输入的值从数据库中检索数据。但是,当我添加代码以动态添加 li 元素时,每次发出请求时都会收到运行时错误。此代码可在 routes / grades.js 中找到。

我得到的错误是:

  抛出错误; //重新抛出非MySQL错误           ^

     

TypeError:req.body.getElementById不是函数

这是由此代码块引起的

  

var ul = req.body.getElementById(&#34; search&#34;);

     

var li = req.body.createElement(&#34; li&#34;);

     

li.appendChild(req.body.createTextNode(reqObj [&#34;的className&#34;]));

我相信 createElement createTextNode 也会导致相同的错误消息。

我认为这可以通过 jsdom 解决,但是当我尝试通过npm安装它时,我只收到很多错误,所以我放弃了。此外,我相信有一个更简单的解决方案,我还不知道。

以下是我上面提到的功能的主要文件。

视图/ grades.ejs

<!DOCTYPE html>
<html ng-app="ClassSaber">
<head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
    <script src="javascripts/app.js" type="text/javascript"></script>
</head>

<body ng-controller="classController">
<% include template/header2.ejs %>

<div class="lessons" id="homebranding_top">
    <section>
        <h1>Grades</h1>
        <hr>
    </section>

    <section>
        <p>
            Keeping track of your progress eh? That's great! Search your class and we'll show your grade.
        </p>
    </section>

    <form>
        <section id="class_search">
            <input type="text" id="search" ng-model="data.className" placeholder="Enter your class here...">
            <input type="submit" value="Search" ng-click="classFun()">

            <ul id="class_list">
              <li ng-repeat="item in list | filter: data.className">
                  {{item.Class_Name}}
              </li>
            </ul>
        </section>
    </form>
</div>
</body>
</html>

routes / grades.js

    var express = require('express');
var router = express.Router();
var path = require('path');

/* GET lessons page. */
router.get('/grades', function(req, res, next) {
    res.render('grades', { title: 'Class Saber | Grades' });
});

module.exports = router;

//search class in the database
router.post('/grades', function(req, res, next){
    try{
        var reqObj = req.body;
        console.log("Request Object: " + reqObj["className"]);
        req.getConnection(function(err, conn){
            if(err){
                console.error('SQL Connection error: ', err);
                return next(err);
            }
            else{
                var insertSql = "SELECT Class_Name FROM classes WHERE Class_Name LIKE ?";
                var insertValues = [
                    '%' + reqObj["className"] + '%'
                ];
                var query = conn.query(insertSql, insertValues, function(err, result){
                    if(err){
                        console.error('SQL error: ', err);
                        return next(err);
                    }
                    var ul = req.body.getElementById("search");
                    var li = req.body.createElement("li");
                    li.appendChild(req.body.createTextNode(reqObj["className"]));
                });
            }
        });
    }
    catch(ex){
        console.err("Internal error: " + ex);
        return next(ex);
    }
});

公开/ Javascript角/ app.js

var app = angular.module('ClassSaber', []);

app.controller('classController', function($scope, $http){
    $scope.data = {};

    $scope.list = [
        {Class_Name: 'Math 101'},
        {Class_Name: 'Physics 101'},
        {Class_Name: 'Major Elective: Quantum Mechanics'}
    ];

    $scope.classFun = function(){
        console.log('Client triggered class search function...');
        $http({
            url: 'http://localhost:3000/grades',
            method: 'POST',
            data: $scope.data
        }).then(function (httpResponse){
            console.log('response', httpResponse);
        })
    }
});

2 个答案:

答案 0 :(得分:0)

req.body包含请求的正文(您通过$http调用传递的数据),而不是DOM的body元素。您无法从服务器端环境(如nodejs)访问客户端元素(如DOM),反之亦然。如果您想对DOM进行更改,请返回必须使用您的响应更改的说明以及浏览器中的相应更改。

我不使用角度,所以我不能直接告诉你如何做到这一点。但总的来说,它会是这样的:

var query = conn.query(insertSql, insertValues, function(err, result) {
  if (err) {
    console.error('SQL error: ', err);
    return next(err);
  }

  // response with a list of action to be applied
  res.send([{
     action : 'append-to-dom',
     info : {
       /* all informations you need for this e.g. reqObj["className"] */
     }
  }]);
});

在您的客户端代码中,您将检查您必须执行的操作:

$http({
  url: 'http://localhost:3000/grades',
  method: 'POST',
  data: $scope.data
}).then(function(httpResponse) {
   // check the content of your response if it contains actions
   /*
    var ul = req.body.getElementById("search");
    var li = req.body.createElement("li");
    li.appendChild(req.body.createTextNode( .. the data from your response ...  ))
   */
})

如何构建响应取决于您并且取决于环境。 Angular可能已经有一个特定的模式如何做到这一点,但正如我所说,我不使用角度所以我不能告诉你。

答案 1 :(得分:0)

t.niese 给我的概念非常有用,我能解决问题。

以下是我根据建议的答案所做的更改:

在我的路线中

var query = conn.query(insertSql, insertValues, function(err, result){
    if(err){
          console.error('SQL error: ', err);
          return next(err);
    }
    var class_array = [];
    for(var i=0; i<result.length; i++){
          class_array.push(result[i]);
    }
    console.log(class_array.valueOf());
    res.send([{
        info: class_array.valueOf()
    }])
});

以及我的客户端代码

$scope.classFun = function(){
    console.log('Client triggered class search function...');
    $http({
        url: 'http://localhost:3000/grades',
        method: 'POST',
        data: $scope.data
    }).then(function (httpResponse){
        console.log('response', httpResponse);
        var tbody = document.getElementById("class_list_data");
        while(tbody.firstElementChild){
            tbody.removeChild(tbody.firstChild);
        }
        for(var i=0; i<httpResponse.data.length; i++){
            for(var j=0; j<httpResponse.data[i].info.length; j++){
                var tr = document.createElement("tr");
                var td = document.createElement("td");
                td.appendChild(document.createTextNode(httpResponse.data[i].info[j].Class_Name.toString()));
                tr.appendChild(td);
                tbody.appendChild(tr);
            }
        }
    })
}

另外,我对模板进行了一些修改。我使用表格

代替列表
<div id="homebranding_middle">
    <table id="class_list">
        <thead>
            <th>CLASS DESCRIPTION</th>
            <th>SCHEDULE</th>
            <th>CLASSROOM ASSIGNMENT</th>
            <th>INSTRUCTOR</th>
        </thead>

        <tbody id="class_list_data">
            <tr id="class_list_row" ng-repeat="item in list | filter: {Class_Name: data.className}">
                <td><a href="">{{item.Class_Name}}</a></td>
                <td>{{item.Class_Code}}</td>
                <td>{{item.Class_Room}}</td>
                <td>{{item.Class_Instructor}}</td>
                <dynamic></dynamic>
            </tr>
        </tbody>
    </table>
</div>

总而言之,我的 / grade 页面现在可以实际执行某些操作。我得到状态代码200,并且可以播放来自DB的所有检索数据。

localhost:3000/grades

Going pretty well.

非常感谢 t.niese !干杯!