使用 AngularJS 跟踪和计算点击次数并发布到 MongoDB

Posted

技术标签:

【中文标题】使用 AngularJS 跟踪和计算点击次数并发布到 MongoDB【英文标题】:Track and count clicks with AngularJS and post to MongoDB 【发布时间】:2014-09-03 02:39:54 【问题描述】:

我希望能够跟踪用户对某个项目的点击,并让它更新与之关联的 JSON 对象并显示所有点击的次数。我知道如何创建和删除对象,但是当用户单击和适当的投票按钮时,如何添加新名称和值并更新对象?任何帮助将不胜感激,我提前感谢您。

html

<body ng-controller="mainController">
<div class="table-responsive">
          <table class="table">
            <tr>
                <td>Vote</td>
                <td>Song</td>
                <td>Edit</td>
            </tr>
            <tr ng-repeat="todo in todos">
                <td><button class="btn btn-success icon-thumbs-up" >Vote</button></td>
                <td> todo.text </td>
                <td><button class="btn btn-danger fa fa-times" ng-click="deleteTodo(todo._id)" ></button></td>
            </tr>
          </table>
        </div>
</body>

模型

var mongoose = require('mongoose');

module.exports = mongoose.model('Todo', 
text : String,
done : Boolean
);

服务

angular.module('todoService', [])

// super simple service
// each function returns a promise object 
.factory('Todos', function($http) 
    return 
        get : function() 
            return $http.get('/api/todos');
        ,
        create : function(todoData) 
            return $http.post('/api/todos', todoData);
        ,
        delete : function(id) 
            return $http.delete('/api/todos/' + id);
        
    
);

服务器端 Angular

var Todo = require('./models/todo');

module.exports = function(app) 

// api ---------------------------------------------------------------------
// get all todos
app.get('/api/todos', function(req, res) 

    // use mongoose to get all todos in the database
    Todo.find(function(err, todos) 

        // if there is an error retrieving, send the error. nothing after res.send(err) will execute
        if (err)
            res.send(err)

        res.json(todos); // return all todos in JSON format
    );
);

// create todo and send back all todos after creation
app.post('/api/todos', function(req, res) 

    // create a todo, information comes from AJAX request from Angular
    Todo.create(
        text : req.body.text,
        done : false
    , function(err, todo) 
        if (err)
            res.send(err);

        // get and return all the todos after you create another
        Todo.find(function(err, todos) 
            if (err)
                res.send(err)
            res.json(todos);
        );
    );

);

// delete a todo
app.delete('/api/todos/:todo_id', function(req, res) 
    Todo.remove(
        _id : req.params.todo_id
    , function(err, todo) 
        if (err)
            res.send(err);

        // get and return all the todos after you create another
        Todo.find(function(err, todos) 
            if (err)
                res.send(err)
            res.json(todos);
        );
    );
);

// application -------------------------------------------------------------
app.get('*', function(req, res) 
    res.sendfile('./public/index.html'); // load the single view file (angular will handle the page changes on the front-end)
);

;

客户端角度

angular.module('todoController', [])

// inject the Todo service factory into our controller
.controller('mainController', function($scope, $http, Todos) 
    $scope.formData = ;
    $scope.loading = true;

    // GET =====================================================================
    // when landing on the page, get all todos and show them
    // use the service to get all the todos
    Todos.get()
        .success(function(data) 
            $scope.todos = data;
            $scope.loading = false;
        );

    // CREATE ==================================================================
    // when submitting the add form, send the text to the node API
    $scope.createTodo = function() 
        $scope.loading = true;

        if ($scope.formData.text != undefined) 

            // call the create function from our service (returns a promise object)
        Todos.create($scope.formData)

            // if successful creation, call our get function to get all the new todos
            .success(function(data) 
                $scope.loading = false;
                $scope.formData = ; // clear the form so our user is ready to enter another
                $scope.todos.unshift(data); // assign our new list of todos
                );
            
        ;

    // DELETE ==================================================================
    // delete a todo after checking it
    $scope.deleteTodo = function(id) 
        $scope.loading = true;

        Todos.delete(id)
            // if successful creation, call our get function to get all the new todos
            .success(function(data) 
                $scope.loading = false;
                $scope.todos = data; // assign our new list of todos
            );
    ;

);

【问题讨论】:

你的意思是如何在数据库中“添加新的名称和值并更新对象”? @AsyaKamsky 是的,基本上这就是我想要做的,但我也希望它为每个对象添加所有点击次数。 您可以使用更新 $inc 运算符: db.coll.update(criteria:here,$inc:counter:1) 将计数器加 1,如果它存在并且如果它不存在,则将其设置为 1(即,当它不存在时,将其从隐式值 0 递增)。这听起来就像你描述的那样就足够了,然后你不需要在事后做任何添加。 @AsyaKamsky 谢谢。我会把它放在一个函数中,然后点击调用该函数的按钮吗? 我不能说,因为我不确定您的应用程序究竟需要如何做到这一点。当一个按钮被点击某个对象时,你的意图是增加一个特定的字段吗?有多个按钮吗?您将跟踪计数器的多项内容? 【参考方案1】:

这就是你要做的。

向架构添加一个新字段以存储投票:

votes: type: Number, default: 0

在服务器端添加一个新的处理程序以在收到请求时增加vote

app.get('/api/todos/:todo_id/vote', function(req, res) 
    Todo.update(_id: req.params.todo_id,  $inc: votes: 1  ), function(err,doc)
    ...
    

向 AngularJS 服务添加一个新函数来调用这个新的 API 处理程序:

vote: function(id) 
    return $http.get('/api/todos/' + id + '/vote');

连接 ngClick ngRepeated 元素以调用新的 Svc 函数。 注意: 您需要在您的作用域中使用Todos svc 来执行以下操作,否则就像您所做的那样在作用域中创建一个包装器函数。

<td>
  <button data-ng-click="Todos.vote(todo._id)" 
    class="btn.." >Vote
  </button>
</td>

然后以某种方式在您的视图中显示返回的 ToDo 模型的新“投票”字段。

看看这个:http://meanjs.org/ 你可以得到很多使用 Angular、node 和 Mongo 的好例子,看看它附带的“文章”模块。

我没有尝试任何这些,但它应该可以让您大致了解该怎么做。此外,请意识到这里没有什么可以阻止用户多次投票。希望能帮助到你!

【讨论】:

似乎没有添加点击投票。包装函数是什么意思?你是说$scope.deleteTodo等函数吗? 是的,比如 deleteTodo。上面的 shld 工作,你看到了什么错误? 我在控制台中没有收到上述代码和包装器的错误。 $scope.updateTodo = function(id) $scope.loading = true; Todos.vote(id) // 如果创建成功,调用我们的 get 函数来获取所有新的 todos .success(function(data) $scope.loading = false; $scope.todos = data; // 分配我们的新列表待办事项 ); ; @aaronsil 实际上看起来我得到了这个。 GET somedomain.com/api/todos/undefined/vote500(内部服务器错误) 嗯,todoID 为空,但信息太少,无法说明原因。

以上是关于使用 AngularJS 跟踪和计算点击次数并发布到 MongoDB的主要内容,如果未能解决你的问题,请参考以下文章

使用 click jquery 函数来跟踪我在网页上的点击次数

自定义子域设置后,Branch.io 链接不跟踪点击次数

如何跟踪嵌入视频(youtube、vimeo 等)的点击事件? (跟踪播放次数)

跟踪 Alfresco 点击

Firebase 不跟踪动态链接的点击次数

javascript 使用Google Analytics事件跟踪跟踪您网站上的出站链接的点击次数