1

I am a newbee to the express nodejs applications. I want to make a todo list. This is how it looks so far. My question is when I add a todo, it takes some time to show the change since it reloads the page. How can I see the change in realtime without reloading the page. Thanks in advance.

in tasks.jade

 h1= title

  .list
    .item.add-task
      div.action
        form(action='/tasks', method='post', id='12345')
          input(type='hidden', value='true', name='all_done')
          input(type='hidden', value=locals._csrf, name='_csrf')
          input(type='submit', class='btn btn-success btn-xs', value='all done')
      form(action='/tasks', method='post')
        input(type='hidden', value=locals._csrf, name='_csrf')
        div.name
          input(type='text', name='name', placeholder='Add a new task')
        div.delete
          input.btn.btn-primary.btn-sm(type="submit", value='add')
    if (tasks.length === 0)
      | No tasks.
    each task, index in tasks
      .item
        div.action
          form(action='/tasks/#{task._id}', method='post')
            input(type='hidden', value=task._id.toString(), name='id')
            input(type='hidden', value='true', name='completed')
            input(type='hidden', value=locals._csrf, name='_csrf')
            input(type='submit', class='btn btn-success btn-xs task-done', value='done')
        div.num
          span=index+1
            |. 
        div.name
          span.name=task.name + ' (Created at: ' + moment(task.createTime).format("YYYY/MM/DD") + ')'
          //- no support for DELETE method in forms
          //- http://amundsen.com/examples/put-delete-forms/
          //- so do XHR request instead from public/javascripts/main.js
        div.delete
          a(class='btn btn-danger btn-xs task-delete', data-task-id=task._id.toString(), data-csrf=locals._csrf) delete

in app.js

app.get('/', routes.index);
app.get('/tasks', tasks.list);
app.post('/tasks', tasks.markAllCompleted)
app.post('/tasks', tasks.add);
app.post('/tasks/:task_id', tasks.markCompleted);
app.delete('/tasks/:task_id', tasks.del);
app.get('/tasks/completed', tasks.completed);

in tasks.js

exports.add = function(req, res, next){
  if (!req.body || !req.body.name) return next(new Error('No data provided.'));
  req.db.tasks.save({
    name: req.body.name,
    createTime: new Date(),
    completed: false
  }, function(error, task){
    if (error) return next(error);
    if (!task) return next(new Error('Failed to save.'));
    console.info('Added %s with id=%s', task.name, task._id);
    res.redirect('/tasks');
  })
};
Alex Stack
  • 15
  • 1
  • 1
  • 3

2 Answers2

5

ExpressJS is a server-side framework. That means it serves up views when a browser makes requests for them. In order to prevent the browser from making a full page refresh when interacting with the page you need to look into a client-side framework.

I highly recommend taking a look at AngularJS, but that can be a daunting framework for a beginner. I would definitely first learn JQuery if you haven't already. Many other frameworks either build on top of JQuery directly or mimic some of the patterns employed by JQuery. I would focus on JQuery first and then graduate to a higher-level framework like AngularJS or something similar.

Here is an example of hijacking a form submit with JQuery:

<script type="text/javascript">
  $('#myForm').on('submit', function (event) {
    event.preventDefault(); // Stop the form from causing a page refresh.
    var data = {
      username: $('#username').val(),
      password: $('#password').val()
    };
    $.ajax({
      url: 'http://localhost/my/url',
      data: data,
      method: 'POST'
    }).then(function (response) {
      // Do stuff with the response, like add it to the page dynamically.
      $('body').append(response);
    }).catch(function (err) {
      console.error(err);
    });
  });
</script>

If you put that script tag at the bottom of a page, just before the closing </body> tag, it will hijack a form with the ID myForm and attach an event handler for the submit event. When the form is submitted the event handler will fire first. The first line of the handler event.preventDefault() tells the browser not to perform the default submit behavior and refresh the page. Then after that we create a data object to store the values of the form fields that we are interested in. In this example I use a text input with the ID "username" and a password input with the ID "password". Notice how the string you pass to $() looks a lot like a CSS selector, that's the idea :)

Once we have the data we want to post to the server, we make an AJAX request with the data and we handle the response, or catch any errors if they occur. This AJAX request happens without refreshing the page :)

The reason this script has to be at the bottom of a page is because the elements need to be loaded before it runs. JQuery makes it possible to ensure that the entire document is ready before running scripts.

$(document).on('ready', function (event) {
  // This code won't run until the whole page is ready.
});

If you place your code in that event handler then you can put the script tag anywhere on the page, even in the <head>. JQuery offers a shortcut for that event handler because it's used a lot.

$(function (event) {
  // This is sugar for $(document).on('ready', function () { ... });
});
Chev
  • 54,842
  • 60
  • 203
  • 309
  • This works for me. To be confirm, I guess I should send some key with "data" to the "http://localhost/my/url", so that in server side I respond only it matches with my key to be secured of fraud calls, is it? :) – Alex Stack Jun 04 '15 at 15:18
  • I'm not sure what you mean. An AJAX request (from the server's perspective) isn't really any different than a classical form submission. The only difference is that the browser doesn't make a full request to the server but instead makes an AJAX request in the background. – Chev Jun 04 '15 at 15:23
  • Thanks. I meant, I think some people can also save data to the database with our submission url without going to the website if I got it correct. Do we have to avoid it or is it handled automatically? – Alex Stack Jun 04 '15 at 15:34
  • Web security is a whole different topic XD. The short answer is "No, AJAX won't introduce any security holes that weren't already present with the classical form submit style you have working." The long answer is "Yes, anyone could make requests to your endpoints and you'll want to learn all about [web authentication](http://stackoverflow.com/questions/549/the-definitive-guide-to-form-based-website-authentication)." – Chev Jun 04 '15 at 15:36
  • 3
    Thanks for the great answer and resources. – Alex Stack Jun 04 '15 at 15:58
  • No problem. Good luck! Keep asking questions and learning and you'll be a web guru before you know it ;) – Chev Jun 04 '15 at 15:58
0

Your server should return JSON instead of rendered HTML. On the front end you should use JavaScript (jQuery and method $.getJSON() for example) to query your server for the updated task list. jQuery will use AJAX to send and receive data from your server without the need to refresh your page. There are many good tutorials online on how to make REST API using Node.js.

IvanJ
  • 473
  • 4
  • 16
  • Is it a good idea to use web-sockets over ajax for this kind of application? – Alex Stack Jun 04 '15 at 15:21
  • @AlexStack You could absolutely use websockets instead of classical AJAX requests, but as a beginner I highly suggest learning all about AJAX/XHR before diving into websockets. – Chev Jun 04 '15 at 15:25
  • Thanks @IvanJ. Make sense. For my info does it give a performance gain if we do it with websockets? – Alex Stack Jun 04 '15 at 15:36
  • Not really, no. If you're doing something in realtime, like a chat application, then it would matter. – Chev Jun 04 '15 at 15:37
  • 1
    @Ivan Make sense. Thank you for the answers. – Alex Stack Jun 04 '15 at 15:58