【问题标题】:Angular - $routeParams.itemID for loading domain.com/:itemID ALMOST WORKING?Angular - $routeParams.itemID 用于加载 domain.com/:itemID 几乎可以工作?
【发布时间】:2014-05-20 07:14:46
【问题描述】:

我希望在路由中包含参数,方法是在变量名前使用冒号

// dynamic pages for each ITEM, once selected
// from $routeParams.itemID in ItemCtrl
.when('/:itemID', {
        templateUrl: 'views/item.html',
        controller: 'ItemController'
})

当一个 div 框被点击时,Angular 应该路由到特定的项目

<div class="itemBox" ng-click="getItem(item._id)">

现在,对 node/express API 的调用似乎正在运行

[16:36:18.108] GET http://localhost:8080/api/items/534240001d3066cc11000002 [HTTP/1.1 304 Not Modified 4ms]

但是这个错误记录在控制台中:

Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (http.js:691:11)
    ...
    at Promise.<anonymous> (/Users/Username/Downloads/project/v19/app/routes.js:41:8)
    ...

routes.js 中的第 41 行(对于 41:8?)是 res.json(item);

// load the item model
var Item = require('./models/item');

// get One item
app.get('/api/items/:item_id', function(req, res) {

        // use mongoose to get the one item from the database
        Item.findById({
                _id : req.params.item_id
        },

        function(err, item) {

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

                res.json(item); // return the item in JSON format
        });
});

虽然看起来问题可能出在控制器中,因为所有其他 API 调用都有效。所以我尝试在整个地方传递 $routeParams!

angular.module('ItemCtrl', [])

// inject the Item service.factory into our controller
.controller('ItemController', function($scope, $routeParams, $http, Items, isEmptyObjectFilter) {

        // get an Item after clicking it
        $scope.getItem = function(id, $routeParams) {
                Items.getOne(id, $routeParams)
                        // if successful getByID, call our function to get the Item data
                        .success(function(data, $routeParams) {
                                // assign our Item
                                $scope.item = data;
                                // for use with a parameter in appRoutes.js using itemID as the variable
                                $scope.itemID = $routeParams.itemID;
                        })
                        .error(function(data) {
                                console.log('Error: ' + data);
                        });
        };
});

或者也许是服务?这是否需要将 $routeParams 作为 function(id, $routeParams) 传递

angular.module('ItemService', [])

// super simple service
// each function returns a promise object 
.factory('Items', function($http) {
        return {
                get : function() {
                        return $http.get('/api/items');
                },
                getOne : function(id) {
                        return $http.get('/api/items/' + id);
                },
                create : function(itemData) {
                        return $http.post('/api/items', itemData);
                },
                delete : function(id) {
                        return $http.delete('/api/items/' + id);
                }
        }
});

非常感谢一些帮助调试这个..谢谢

【问题讨论】:

    标签: javascript node.js angularjs express mongoose


    【解决方案1】:

    该消息是因为您收到错误并执行 res.send() 方法,然后您有 res.json(),express 试图响应两次。

    尝试改变:

    if (err)
      res.send(err)
    

    收件人:

    if (err) {
      res.json({ error: err }); 
    } else {
      var object = item.toObject();
      res.json(object);
    }
    

    Angular 资源示例:

    angular.module('ItemService')
    .factory('Items', ['$resource', function($resource) {
        return $resource('/api/items/:itemID', {
            itemID: '@_id'
        }, {
            update: {
                method: 'PUT'
            }
        });
    }]);
    

    现在您可以在控制器中执行此操作:

    // Find
    Items.get({
      itemID: $routeParams.itemID
    }, function(item) {
      $scope.item = item;
    });
    
    // Update
    $scope.item.name = 'New name';
    $scope.item.$update();
    
    // Remove
    $scope.item.$remove();
    

    【讨论】:

    • 谢谢,没有错误了.. 但它不会路由到 /:itemID - 是因为 $routeParams 在 Ctrl 中传递的位置,还是我需要 res.json(item) ;还在哪里?
    • 你必须使用角度资源而不是 $http 请求
    • 不太清楚这意味着什么。你有例子吗?
    • 是的,我已经修改了答案
    【解决方案2】:

    看起来您正在正确获取数据。问题是你想在成功获取API调用后改变路由?

    $routeParams 不会为您更改路线。这只是获取数据。使用 $location 更改路线。

    .controller('ItemController', function($scope, $routeParams, $location, $http, Items, isEmptyObjectFilter) {
    $scope.getItem = function(id) {
        Items.getOne(id)
            .success(function(data) {
                  $scope.item = data;
                  $scope.itemID = $routeParams.itemID;
    
                  // redirect
                  $location.path('/' + $routeParams.itemID);
            });
    });
    });
    

    由于您的所有数据似乎都已准备就绪,您只需要 Angular 重定向到路由。 $location 应该是要走的路。

    【讨论】:

    • 谢谢你.. 差不多了.. 它重定向到 item.html 页面,但是控制台在 GET /api/items/534240001d3066cc11000002 之后报告另一个 GET /api/items .. 任何想法为什么它会执行另一个 GetAll?
    • 你有一个在页面被点击时执行获取所有的主控制器吗?或者 ItemController 中还有其他什么可以做的吗?由于您在路由更改时再次调用 ItemController,因此其中的任何内容都会再次运行。
    • 啊,明白了..那里也有一个通用的get..会分开ctrls..再次感谢!
    • 甜蜜!很高兴我能帮上忙。
    • 呃,原来数据也有问题。一直在测试各种东西,但 item.html 没有填充角度绑定,因为返回的数据是 [object Object ] 带有这条消息:"Cast to ObjectId failed for value "[object Object]" at path "_id"" 有什么建议吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-08
    • 2013-08-25
    • 1970-01-01
    相关资源
    最近更新 更多