coffeescriptpublish-subscribepugsocketstream

How to dynamically update a Jade element from client-side CoffeeScript?


I'm trying to dynamically update a table of values using SocketStream. I have a Jade template defining the table:

app.jade:

table
  thead
    tr
      th key
      th value
    tbody
      - var jadeItems = [{key:'Test',value:'3.1415'}, {key:'Test2',value:'2.1878'}]
      - each item in jadeItems
        tr
          td= item.key
          td= item.value

This works for the static data, and now I need to make it dynamic. I have client-side CoffeeScript that receives a SocketStream message containing the new values for the table in JSON format:

app.coffee:

SS.events.on('message', (message) ->
  jadeItems = JSON.parse(message)
)

I am trying to figure out how to replace the JSON value of items in Jade with with the content of the message, but the 'jadeItems' variable is out of scope in the client-side CoffeeScript.

I am able to stuff the new JSON into a Jade element, but then I'm unsure how to get the values for the element in the 'jadeItems' variable within Jade.

Does anyone know the Jade syntax for getting the value of a Jade element? Or is there a way to assign to the items variable defined in Jade from within the client-side CoffeeScript? Are there any solid references for Jade syntax?


Solution

  • Assuming you're using Jade as a client-side templating library (which is rare, but possible):

    In order to do your Ajax update purely through Jade, you'd have to re-render the template. You must be doing something like (using the example from the docs here)

    fn = jade.compile template, options
    fn locals
    

    What you should be doing is making jadeItems a property of that locals object. So instead of the line

    - var jadeItems = [{key:'Test',value:'3.1415'}, {key:'Test2',value:'2.1878'}]
    

    in your template, you'd instead call the Jade render function with

    locals = {jadeItems: [{key:'Test',value:'3.1415'}, {key:'Test2',value:'2.1878'}]}
    fn locals
    

    Then in your Ajax function, you'd write

    locals.jadeItems = JSON.parse message
    fn locals
    

    to re-render your template with the new data.

    Update: Given the clarification in the comments on the question, the more direct answer is: "Just use jQuery to manipulate the DOM from the Ajax callback." That might look something like

    SS.events.on 'message', (message) ->
      items = JSON.parse message
      html = ''
      for item in items
        html += "<tr><td>#{item.key}</td><td>#{item.value}</td></tr>"
      $('tbody').html html
    

    (note that the above assumes that the server response is sanitized and well-formatted).