0

I'm following this tutorial on building a Single Page Application with express and AngularJS on nodejs.

I'm Trying to call the web api from the angular module, but I keep receiving the entire page html content, instead of the actual value

<!-- index.html -->
<!doctype html>

<!-- ASSIGN OUR ANGULAR MODULE -->
<html ng-app="scotchTodo">
<head>
    <!-- META -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1"><!-- Optimize mobile viewport -->

    <title>Node/Angular Todo App</title>

    <!-- SCROLLS -->
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"><!-- load bootstrap -->
    <style>
        html                    { overflow-y:scroll; }
        body                    { padding-top:50px; }
        #todo-list              { margin-bottom:30px; }
    </style>

    <!-- SPELLS -->
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script><!-- load jquery -->
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script><!-- load angular -->
    <script src="core.js"></script>

</head>
<!-- SET THE CONTROLLER AND GET ALL TODOS -->
<body ng-controller="mainController">
<div class="container">

    <!-- HEADER AND TODO COUNT -->
    <div class="jumbotron text-center">
        <h1>I'm a Todo-aholic <span class="label label-info">{{ todos.length }}</span></h1>
    </div>

    <!-- TODO LIST -->
    <div id="todo-list" class="row">
        <div class="col-sm-4 col-sm-offset-4">

            <!-- LOOP OVER THE TODOS IN $scope.todos -->
            <div class="checkbox" ng-repeat="todo in todos">
                <label>
                    <input type="checkbox" ng-click="deleteTodo(todo._id)"> {{ todo.text }}
                </label>
            </div>

        </div>
    </div>

    <!-- FORM TO CREATE TODOS -->
    <div id="todo-form" class="row">
        <div class="col-sm-8 col-sm-offset-2 text-center">
            <form>
                <div class="form-group">

                    <!-- BIND THIS VALUE TO formData.text IN ANGULAR -->
                    <input type="text" class="form-control input-lg text-center" placeholder="I want to buy a puppy that will love me forever" ng-model="formData.text">
                </div>

                <!-- createToDo() WILL CREATE NEW TODOS -->
                <button type="submit" class="btn btn-primary btn-lg" ng-click="createTodo()">Add</button>
            </form>
        </div>
    </div>

</div>

</body>
</html>

--

// public/core.js
var scotchTodo = angular.module('scotchTodo', []);

function mainController($scope, $http) {
    $scope.formData = {};

    // when landing on the page, get all todos and show them
    $http.get('/api/something')
        .success(function(data) {
            $scope.todos = data;
            console.log(data);
            alert(data)
        })
        .error(function(data) {
            console.log('Error: ' + data);
        });

    // when submitting the add form, send the text to the node API
    $scope.createTodo = function() {
        $http.post('/api/todos', $scope.formData)
            .success(function(data) {
                $scope.formData = {}; // clear the form so our user is ready to enter another
                $scope.todos = data;
                console.log(data);
            })
            .error(function(data) {
                console.log('Error: ' + data);
            });
    };

    // delete a todo after checking it
    $scope.deleteTodo = function(id) {
        $http.delete('/api/todos/' + id)
            .success(function(data) {
                $scope.todos = data;
                console.log(data);
            })
            .error(function(data) {
                console.log('Error: ' + data);
            });
    };
}

--

//server.js
// set up ========================
var express = require('express');
var app = express();                                // create our app w/ express

// configuration =================

app.configure(function () {
    app.use(express.static(__dirname + '/public'));         // set the static files location /public/img will be /img for users
    app.use(express.logger('dev'));                         // log every request to the console
    app.use(express.bodyParser());                          // pull information from html in POST
    app.use(express.methodOverride());                      // simulate DELETE and PUT
});

// listen (start app with node server.js) ======================================
app.listen(8080);
console.log("App listening on port 8080");

// 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)
});

// api routes

app.get('/api/something',function(req,res){
    res.json({text: "1"});
});

// get all todos
app.get('/api/todos', function (req, res) {
    console.log("api/todos")
    var todos = [];
    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);
        });
    });
});

But all I get instead of the value I tried to pass is the full html: chrome dev console

2 Answers 2

6

This route...

// 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)
});

... is responding to all GET requests because it comes before the /api/something route. Either swap it with the /api/something route...

app.get('/api/something',function(req,res){
    res.json({text: "1"});
});

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)
});

Or don't use a wildcard...

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)
});
Sign up to request clarification or add additional context in comments.

Comments

3

You just need to change your server code so that index.html is only returned when a get request is sent to '/'. You currently have it set up to return index.html on any get request that matches '*'...so everything.

app.get('/', function (req, res) {
    res.sendfile('./public/index.html');
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.