emadalam / atvjs

Blazing fast Apple TV application development using pure JavaScript
https://emadalam.github.io/atvjs
MIT License
311 stars 49 forks source link

Re-render a template? #4

Open hamishtaplin opened 8 years ago

hamishtaplin commented 8 years ago

Use-case

Using a listTemplate, I would like to make the relatedContent area dynamic, populating it with content when a listItemLockup is highlighted by the user.

Consider the following (simplified) page:

import ATV from 'atvjs';
import template from './template.hbs';

const APIURL = 'http://myapi/shows';

let Page = ATV.Page.create({
  name: 'shows',
  template: template,
  events: {
    select(e) {
      console.log(e);
    },
    highlight(e) {
      // RE-RENDER
    }
  },
  ready(options, resolve, reject) {
    ATV.Ajax
      .get(APIURL)
      .then((xhr) => {
        let response = xhr.response;
        resolve(response);
      }, (xhr) => {
        let response = xhr.response;
        reject({
          status: xhr.status,
          message: response.message
        });
      });
  }
});

export default Page;

Using the ReactJS model as an analogy, I would like to be able to do something like:

I tried to do this by storing a reference to the resolve method passed into ready and giving that fresh data but, although I can see output in the console that this has done something with the data, the page doesn't re-render.

I'm assuming this is possible somehow, I'm probably missing something really obvious...

EDIT:

Having played around, it seems you can do some old-fashioned DOM traversal/manipulation using the reference to doc that the afterReady method receives. Although this is a passable way of doing things, I would be interested to know if there scope for something more aligned with the way modern SPA's are built, rather than hunting down nodes and injecting content in to them.

emadalam commented 8 years ago

@hamishtaplin The whole emphasis of this framework is to provide a high level TVJS app architecture with a very thin layer on top of the existing TVJS framework and streamline any mundane tasks that we as developers may need to do while using the TVML templates alongside TVJS framework. As a result there are no models or model-to-view data bindings available in the whole framework as such. If we need to implement it, this is something that needs to be carefully thought of at the whole framework architecture level. On a side note, you may check out this project, https://github.com/ramitos/react-tvml that implements react bindings for TVML app.

Having said that, you brought a very good point of refreshing the current state of the document with the updated data, that is a feature I believe, is worth having. Something like this.refresh(data) makes a lot of sense to me, which can be called from within the event handlers of the Page objects. I can take this as a feature request and work towards implementing it.

PS: Even the latest and the greatest frameworks (like ReactJS in your example), also relies on the "old-fashioned DOM traversal/manipulation" at their core :wink:

spunkedy commented 8 years ago

I solved this via something simple like:

  var getData = function(callback){
      ATV
          .Ajax
          .get(url)
          .then(function(xhr) {
              // xhr succeeded
              var response = xhr.response;
              console.log("Response");
              console.log(response);
              // call resolve with the data that will be applied to the template
              // you can even call resolve with false to skip navigation
              callback(response);
          }, function(xhr) {
              // xhr failed
              var response = xhr.response;

              console.log("Rejected");
              console.log(response);
          });
    }
    getData(function(currentResponse){
      if(!(JSON.stringify(getProp(lastData)) === JSON.stringify(getProp(currentResponse)))){
        ATV.Navigation.navigate(currentPage,ATV._.extend(currentResponse,currentOptions), true);
      }
    });

This is just a quick example of how I query the backend data system. This is until I can get websockets implemented.

The true in navigate tells it to refresh not re navigate.

spunkedy commented 8 years ago

It would be nice to see some handlebar reactive data binding though.

KevinBeckers commented 7 years ago

Whats the status of the websockets/handlebar enhancements?

spunkedy commented 7 years ago

@KevinBeckers as far as I know, you cannot use web sockets still. This is a limitation from the tvOS and js client.

I got it to work doing longpolling and having a socket.js connection.

KevinBeckers commented 7 years ago

Can you show how you solved it? Thank you

spunkedy commented 7 years ago

I don't have the code around anymore. If I get a chance later I might pop it back in here. The server side has to be able to support it.

KevinBeckers commented 7 years ago

That would be great!

spunkedy commented 7 years ago

I found some of the code. I haven't tested this in a while however, here it is.

https://gist.github.com/spunkedy/27aa9d3db6abdcb401f75c67da8be8e3

Hope this helps. I didn't include the server side that creates the channel that accepts a longpolling mechanism.

The server side is a web socket supporting longpolling which was good enough for what I was doing.

KevinBeckers commented 7 years ago

Thanks, I will try to get it working. If I find anything useful I will get back.

spunkedy commented 7 years ago

Here is the updated gist. I was kinda driven crazy by it. I use elixir / phoenix on the backend, and you are able to use long polling on it.

I am on phoenix 1.2 with this project example.

https://gist.github.com/spunkedy/c8f476a0c5daf417a7b17083a7ced55e

Basically you have to take care of references to location and window. So I was a little misleading, however it does work well, but if you are using something else like socket.io you will have to adapt it.

KevinBeckers commented 7 years ago

Super! I don't have a phoenix project to test it on. But I will try to work it out.

It would be pretty awesome to incorporate this in the framework! Thanks for the help.