-
Notifications
You must be signed in to change notification settings - Fork 90
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Great work #1
Comments
I appreciate your feedback. Lots of good points. I agree functions would be great -- as well as assignments. Master pages -- I personally use the closure syntax -- have you given that a try? You can use any number of other templates and include them. other.template(param1) -> { } Or if you don't need to pass along a block to render you could just do other.template(param1) You're correct that the main issue w/ hot reloading is the strongly typed construction between the controller & view code. A potential compromise is 1) adding a weakly-typed alternative or 2) only hot-reloading the logic, but if you change the template interface then you'd need to restart your app. Maybe with signature-checking magic, a friendly error could be rendered that we detected the interface has changed and you need to restart the app. |
Thanks for your comments. For the second, I was thinkg of option 1, provide a weakly typed method entry to the generated classes, that supports a Map<String,Object> as a unique parameter maybe. This way, we could completely break the dependency between project and generated classes. For the master pages, this is not quite the same, as master page allows to define more than one section, providing a simple way to build complex pages with a lot of holes in it.
and
|
The more I think of it, the more I believe it should be possible to do it, without being to difficult ! index.java
main.java
main.rocker.html
index.rocker.html
Order of @render should not disturb the way it works, I can't remember the rule in .net razor for this, but here we can decide that it does not matter. |
Now with this + another class with hot reloading strategy + a few other minor things to find, and we can have a very very good templating engine :) |
This is my perception of work to do now...
I see here two point of extensions :
See http://rythmengine.org/doc/developer_guide.md#extension for transformers What do you plan for rocker in the future, is it worth to invest time to work on this ? |
https://github.com/jmarranz/relproxy/ for hot-reloading, looks very nice, isn't it ? |
@momiji You'll want to checkout version 0.10.0 which I released a couple hours ago. Hot reloading support in a couple flavors. README is updated with info on it. Regarding sections, did you take a look at content chunks? I use those to build complex pages. Or I simply write another "method" in its own template file and can call it where needed. Anyway, content chunks looks like this in
This can be used like so in
This will result in rendering <html>
<head>
<title>Home</title>
<link rel="stylesheet" href='@N.assetsAt("plugins/bootstrap/css/bootstrap.min.css")' >
<link rel="stylesheet" href='@N.assetsAt("css/main.css")' >
<body>
<h1>Hello!</h1>
<script type="text/javascript" src='@N.assetsAt("js/jquery-1.10.2.min.js")'></script>
</body>
</html> |
Yes, great work!
So that the above statement will invoke the controller I found, that In Play-Framework that is possible in conjunction with rythm-template-engine, as you can read here: https://www.playframework.com/modules/rythm-1.0.0-RC5/user_guide That would be awesome! |
Well, you could make it work. The output of the method you are calling For example, On Sun, Dec 6, 2015 at 1:07 PM, rranke notifications@github.com wrote:
|
My controller-method is not returning a So, i want to have a controllers template rendered (with all @ -parameters) by the template-engine and would like to "include" the html-output of that rendering-process into another template. A short and simple example: My Controller public class ApplicationController {
public Result index() {
return Results.ok().render(
views.index.template("IndexTitle")
);
}
public Result show() {
return Results.ok().render(
views.show.template("ShowName")
);
}
} Template1 @import controllers.ApplicationController
@args (String title)
<html>
Hi, i am @title!
Lets see how the rendered template of "show()" looks like:
@controllers.ApplicationController.show()
</html> Template2 @import controllers.ApplicationController
@args (String name)
<body>
i am the rendered output with name: @name
</body> The result of opening <html>
Hi, i am IndexTitle!
Lets see how the rendered template of "show()" looks like:
<body>
i am the rendered output with name: ShowName
</body>
</html> How to do that? |
A couple thoughts:
@Args (String title) Hi, i am @title! Lets see how the rendered template of "show()" looks like: @views.show.template("ShowName") 1. Maybe your example is too simplified and you really want controller 2. template reuse. While I mentioned you could write a utility to do that and then convert the ninja.Result to a String -- you'd miss out on Ninja's injection of session variables, parameters, etc. that any useful controller method would use. Seems like poor design to try and reuse a controller method in this way. You should probably refactor your controller methods into more generic, non-ninja, reusable methods that you want to access from other controller methods and/or templates.-Joe On Mon, Dec 7, 2015 at 8:25 AM, rranke notifications@github.com wrote:
|
For me, as a backend-developer ("BD"), i have absolutely no idea where exactly the frontend-developer ("FD") wants to place a specific piece of rendered html-code (some java-objects rendered to html-code by the template-engine). Okay, you think, that my example is too simplified? Yes, you are right :) ! Lets take an example out of the ecommerce-world: A shopping-basket (like an amazon-basket, that lists some products a customer wants to buy). Lets say, the "FD"-guy wants to place that basket (the content of the basket-Template) in some different places, such as in the footer (the footer-template), the main-page (the main-template) or anywhere else. For me as a "BD", i have no idea (and i dont care about) where exactly (at which place within the page, the footer or header or...) the basket gets rendered. As a "BD", i only care about that i provide the logic and collect and provide all the data (like user-object, product-objects, basket-object, ...) that is needed ONLY for the purpose to display the shopping-basket. The "FD"-guy has (and should have) absolutely no idea about which potential data (user-object, product-objects, ...) is needed to calculate and render the shopping-basket-html. The BD has luckily only to calculate and only to provide that stuff, which is directly related to the shopping-basket-data. This approach should simplify the interface between FD and BD and would increase encapsulation and increases the ability to reuse code. So that the BD has not to provide the data needed for to render within in controller that is indirectly chosen by the request. What are actually the problems i want so get solved? The first problem is in the controller: Right now, unfortunately for me it seems like, that i have to call in EVERY controller (which get called based on the specification of the routes-file) a method, that returns the calculated and collected data to provide ALL the shopping-basket data that should get rendered SOMEWHERE in the main-template or SOMEWHERE in any of the included templates. As a BD, i actually have no idea where exactly this will be printed out. EVERY controller has then to send this calculated data to the template which gets rendered (which brings us to the second problem...) The second problem is in the templates: And because this template (which gets rendered after the controller has finished) itself is an include of another template, it has to send the shopping-basket data to its super-template ... and so on). Additionally to that, because the other templates would now need a shopping-basket parameter (argument), we'll have to change every action method in our web-application to pass this parameter. This gets tedious quickly. What could be the solution? My Controller ApplicationController: public class ApplicationController {
public Result index() {
return Results.ok().render(
views.index.template("IndexTitle")
);
}
public String renderShoppingBasket() {
//Get the ninja-Session-object to identify the current user (and get other cookie information)
//query the database for user-object, shopping-basket-object, product-objects
//##############################
// i am not quite sure how to realize the following three steps:
//##############################
//1.) set the template that should get rendered
setTemplateToGetRendered("views.shoppingbasket.rocker.html");
//2.) pass the following arguments to the template, that are used in rendering process.
UnknownType2 renderResult = unknownMethodToRenderTheTemplateByRocker(user-object, shopping-basket-object, products-object);
//3.) get the rendered HTML-stuff as String
String renderResultString = unknownMethodToConvertRenderResultIntoString(renderResult);
return renderResultString;
}
} Template1 index.rocker.html: @import controllers.ApplicationController
@args (String title)
<html>
Hi, i am @title!
the shopping-basket looks like:
@controllers.ApplicationController.renderShoppingBasket()
</html> Template2 shoppingbasket.rocker.html: @import controllers.ApplicationController
@args (User user-object, Basket shopping-basket-object, List<Product> products-object)
<body>
This is the cart of: @User.name
These are your products:
//loop over the @products-object...
</body> The result of opening http://localhost:8080/index in a webbrowser should be: <html>
Hi, i am IndexTitle!
the shopping-basket looks like:
<body>
This is the cart of: Michael
These are your products:
TV, iPhone, iPad
</body>
</html> |
Haha omg, one line-of-code did the trick. public String renderShoppingBasket() {
return views.shoppingbasket.template().render().toString();
} Found that by just browsing the doku. Please dont say "rtfm" ;) |
@rranke Glad you figured out a solution, although Cheers, |
Hello, I'm using ninja framwork with rythm engine
I'm a big fan of .net razor syntax, as it is clear and short and very easy to use.
I'm using rythm engine as it is quite the same as razor.
I'm very interested in rocker, except for one thing, I definitely can't miss the hot reloading feature. I understand why you didn't made it, but I'm convinced that this is a must have, especially for our designers.
I'm not an expert in this domain, but I believe that even if the class loader and compile coding is horrible inside rythm code, they have found a good way to do it.
The big plus of your approach, is that everything is compiled into a strongly typed class, which is a very good point.
Maybe a good way to implement hot reloading is to break the strongly typed access to views in the controllers, and fall back to something more classic like.
What I try to mean is that there will be no strong reference to the generated rocker classes from the application, but only in the other way. This allowing to compile generated java classes without recompiling the whole project, which makes UI developping much much faster...
Well I'm sure you understand what I try to (hardly) explain...
Any way, goog work, keep on going !
Note: not everything in rythm is interesting and should be ported, but I think some of them can be usefull, like master pages (I mean the use of @section and @render), and the ability to create functions (see @def, looks like it is the same as calling another template, but with @def one can put all functions in the same file).
If you're interested, I can have a closer look to rythm which I use every day to determine the must have items missing in rocker - I'm sure it's only a very small number of them.
Whatever you decide, bravo
The text was updated successfully, but these errors were encountered: