3

I'm new to Play (and to MVC to be honest). And I'm having an issue with something that doesn't seem like it should be so hard.

I just found this identically named post: Rendering a portion of a Play framework 2.0 template

But I can't seem to get this working.

I have a template (index) containing another template (rows) which I want to render when a button is clicked. This is the form in my index template:

@form(routes.Application.getNextRows()) {<input type="submit" value="Next Rows!">}

This is getNextRows:

public static Result getNextRows() {
    return ok(views.html.tags.rows.render(rowsIterator.next()));
}

That is where I think i have my problem, but I have no idea how i should be making that call, or what I should be returning (without getting some NullPointerException).

Here is the bit that needs to be re-rendered (in index):

<table cellspacing="0"  style="table-layout:fixed"  border="2">
    <col width="50%">
    <col width="45%">
    <col width="5%">
    @tags.rows(rowsIterator.first())
</table>

So when I click the button, I need to pass in a new rows element, instead of "rowsIterator.first()" Presumably I'm doing something very wrong, or missing some obvious call that sorts this out.

Thanks for any help (and if it is obvious that I am missing some bigger concept, please feel free to educate me).


Looking through the Zentasks sample, I see code like this, which appears to make a section of the page reload. Any idea how this works?

<a class="name" href="#@routes.Tasks.index(project.id)">@project.name</a>
Community
  • 1
  • 1
Sam
  • 3,453
  • 1
  • 33
  • 57
  • What is that mean: *another template (rows) which I want to render when a button is clicked* ? – biesior Aug 24 '12 at 18:56
  • sorry, I have 2 templates, one called index and one called rows. rows is rendered inside index, and i wish to update this rendering – Sam Aug 24 '12 at 19:21
  • 1
    You have two ways to do that: common - just reload the whole page with new set of *rows* or use AJAX to add only new items without reloading – biesior Aug 24 '12 at 19:25
  • thanks, i think im leaning toward the first solution. I would only need ajax to completely replace all my rows though, so thought it might be easy(ish). – Sam Aug 24 '12 at 19:27

2 Answers2

3

Sorry for not providing you with a complete solution, but IMHO you should dive a little more into the basics first.

Your action method returns an entire page, not just a part of it, because it's a full HTTP response. That means whatever you call in that action is what your browser will render. getNextRows needs a parameter to find the next rows. To change only a part of the page, you need AJAX.

The button click should re-render the index page with the next set of rows. Add rows as a parameter to the index template. Call your rows template with these rows.

Marius Soutier
  • 11,184
  • 1
  • 38
  • 48
  • 1
    Thank-you for your reply. Don't worry, I didn't really expect quoted code or anything, but a point in the right direction. I have been doing a lot of reading on the play documentation, but its pretty hard, as half the time I end up reading things for 1.x and the documentation can also be a bit thin in places (I find). Add into that, that this is my first realy go at MVC means I'm struggling to see the correct use for alot of the features described there. – Sam Aug 24 '12 at 19:05
  • I think my getNextRows iterator is working. Is it bad that I have implemented one (it's in models and is loaded from a YAML document)? If re-rendering the page is what play wants, then that's what it'll get... – Sam Aug 24 '12 at 19:06
  • Furthermore, what does it mean to say 'Play is stateless'? I can certainly create static fields in my controllers, and store state in those, or refer to models etc and have state stored in those. – Sam Aug 24 '12 at 19:08
  • Well since I don't know what your iterator exactly does, I can't tell you if is right or not. What happens if multiple users click the button? Have you done the official tutorial? There's also a good book: http://www.manning.com/leroux/ – Marius Soutier Aug 24 '12 at 19:08
  • Exactly, state is only in the model. Static fields won't help you if your app is deployed on multiple machines. – Marius Soutier Aug 24 '12 at 19:11
  • yes, presumably in that case you use some kind of sessioning to look up that users iterator and increment it (I'm v new to all this though so it's a guess :) ). This app needs to run locally on a users machine for simple testing and making calls into a Java library. ie. one user at a time only. I think I have been confused by the post i linked to. To me, that implied there was a way of using AJAX to return rendered template of only a portion of the larger template. The method "createFromTag" is where I think I'm getting confused (this returns a full HTTP response no?) – Sam Aug 24 '12 at 19:20
1

A few possibilities to get that state out of your static field (which definitely won't work well):

  • Give all the rows back to the client and let it do the rest in JavaScript (does not work well if there's too much data)
  • Store the number of the latest row in the session (which is in a cookie)
  • Handle the row number explicitly and let the client return it when it wants the next ones
  • Do RESTful paging (see Paging in a Rest Collection and Pagination in a REST web application)
  • Try to leverage a distributed cache
Community
  • 1
  • 1
hiltym
  • 146
  • 3
  • Thank's very much for this reply. I went and read up on sessions here: http://www.playframework.org/documentation/2.0.2/JavaSessionFlash and it doesn't look too bad, so I think I'll be making use of it (even though I only have one user) – Sam Aug 26 '12 at 09:09
  • i think a combination of yours and Marius' solution covers what i need. although his technically directly addresses how to get the rows to change. sorry! – Sam Aug 27 '12 at 10:28