0

I am using websockets within my Quart app in place of ajax. The aim is to be able to post a comment. A Quart websocket endpoint handles the backend side of things, and then I would like to append the comment to the page instantly from the data received from the websocket. This all working fine until I want to use either a template filter or utility context processor. I think some code will people to understand, so here is my websocket method in JavaScript/jQuery:

  $(function() {
    $('.comment_form').submit(function (e) {
      var add_comment_ws = $.simpleWebSocket({
        url: 'wss://' + document.domain + ':' + location.port + '/websockets/_add_comment',
        timeout: 100,
        attempts: 10,
        dataType: 'json'
      });
      if (typeof $(this).data('post_id') !== 'undefined') {
        var post_id = $(this).data('post_id');
      } else {
        var post_id = null;
      }
      if (typeof $(this).data('reply_id') !== 'undefined') {
        var reply_id = $(this).data('reply_id');
      } else {
        var reply_id = null;
      }
      var data = {
        comment_body: $(this).find('textarea').val(),
        post_id: post_id,
        reply_id: reply_id,
        user_id: $(this).data('user_id'),
        complete: false
      };
      console.log('[+] Sending data to websocket: <add_comment_ws>: content: ' +
        $.each(data, function(key, value) {
          console.log(key + ' - ' + value);
        })
      );
      add_comment_ws.send(data);
      $(this).find('textarea').val('')

      add_comment_ws.listen(function(data) {
        console.log('[+] Received data from websocket: <add_comment_ws>: content: ' +
          $.each(data, function(key, value) {
            console.log(key + ' - ' + value);
          })
        );
        var comments_list = $('#comments_list_for_' + data.id);
        var comment_html = '<div class="comment">' +
                            '<p>' + data.comment_body +
                            '<p>' + data.user_display_name +
                            '<hr>' +
                            '</div>';
                            '<div class="comment">' +
                            ' <hr>' +
                            '  <div class="comment-grid-conatiner">' +
                            '    <div class="comment-grid-item-1">' +
                            '      <div class="comment-option-buttons comment-option-buttons-grid-conatiner">' +
                            '        <button class="comment-vote-up-button vote-button pseudo comment-option-buttons-grid-item-1" title="This comment is useful." aria-label="up vote" data-comment_id="' + data.comment_id + '" data-user_id="' + data.user_id + '"><i class="fal fa-thumbs-up"></i></button>' +

                            '        <div class="vote-count comment-option-buttons-grid-item-2 comment-vote-count-' + data.comment_id + '" itemprop="upvoteCount" data-value="' + data.comment_score + '">' + data.comment_score + '</div>' +

                            '        <button class="vote-button pseudo comment-option-buttons-grid-item-3" title="This comment needs to be flagged." aria-label="up vote"><i class="fal fa-flag"></i></button>' +
                            '      </div>' +
                            '    </div>' +
                            '    <div class="comment-grid-item-2">' +
                            '      <p class="comment-body">' + data.comment_body + '</p>' +
                            '    </div>' +
                            '    <div class="comment-grid-item-3">' +
                            '      <span class="comment-display-name comment-grid-item-2">' +
                            '        <a class="comment-display-name-link" href="/users/user/' + data.user_id + '">' +
                                      data.user_display_name +
                            '        </a>' +
                            '      </span>' +
                            '      <span class="comment-date">' +
//This is where the problem is  --->> {{ human_date(data.created_at) }} + //<<--- 
                            '      </span>' +
                            '    </div>' +
                            '  </div>' +
                            '  <hr>';
        comments_list.append(comment_html);

      });
      e.preventDefault();
    });

I have marked where the problem is in the code (it's at close to the bottom).

I receive an exception:

jinja2.exceptions.UndefinedError: 'data' is undefined

Which is expected at this point because within the jinja tag itthinks we are using python variables.

Is there a way to be able to do this?

Jamie Lindsey
  • 928
  • 14
  • 26
  • Let jinja2 render the comment template on the server, then send back the final HTML via the websocket. –  Feb 18 '19 at 14:53
  • I want to do it without refreshing/reloading the page – Jamie Lindsey Feb 18 '19 at 14:56
  • I think maybe I misunderstood you, could you please elaborate a little? – Jamie Lindsey Feb 18 '19 at 14:57
  • 1. have the server-side code that receives the comment object [call jinja2's rendering engine](http://flask.pocoo.org/docs/1.0/api/#flask.render_template) using a comment template and the comment data 2. send the resulting HTML string back to the browser and insert it. This way you're also getting rid of the ugly client-side HTML composition code. –  Feb 18 '19 at 15:03
  • ok I will try that out, it sounds good. If it works I will let you post as an aswer if you like and ill accept – Jamie Lindsey Feb 18 '19 at 15:05
  • @ChrisG, that has worked perfectly, if you want to put in an answer I will accelt so you get a few rep, if not I will be happy to answer my own question. – Jamie Lindsey Feb 18 '19 at 16:33
  • Feel free to add your answer, but this Q is essentially a duplicate of https://stackoverflow.com/questions/13840429/what-is-the-difference-between-client-side-and-server-side-programming –  Feb 18 '19 at 17:53
  • Ok, I don't know how you could possibly think that my question is the same as the one you suggested. My question was actually how to use javascript data objects inside a jinja2 template, I know the difference between server-side and client-side and I wasn't asking what the difference is, I only went with your suggested method because I don't have time to be waiting, I just needed a way to get it to work for now. I am getting pretty fed up with the whole "duplicate" thing on SO, my question and the suggested dupe are not even in the same context and the only relation is javascript! – Jamie Lindsey Feb 18 '19 at 18:50
  • I said it's *essentially* a duplicate, it's obviously not an exact duplicate. However, you *were* trying to use server-side template syntax / variables on the client-side. Since you didn't know how to resolve this, linking you to a question that explains the basic mechanism at length is the obvious thing to do. You'll also note that I didn't in fact mark your question as dupe. And `I don't have time to be waiting, I just needed a way to get it to work for now.` is precisely *not* how this website works. –  Feb 18 '19 at 19:18

1 Answers1

0

Ok so I rectified this by using Chris G's suggestion in the comments. I ended up moving the HTML into a template and using the websocket endpoint to render the data in the HTML and return the HTML as the to the JavaScript.

Jamie Lindsey
  • 928
  • 14
  • 26