tuplejump / play-yeoman

Play + Yeoman integration sbt and play plugins
Apache License 2.0
237 stars 58 forks source link

Using Yeoman templates as Play scala templates #12

Closed kompot closed 10 years ago

kompot commented 11 years ago

Hi, first of all thank you for this wonderful plugin as a beginning of frontend optimizations on my current project.

I'm trying to integrate it into my current workflow and got the following problem. I'd like to have server side templating in Scala provided by Play in play-yeoman *.html files.

I see it as:

Could not find solution to either of these problems.

Maybe you've got it?

Thanks in advance, Anton.

kompot commented 11 years ago

Answering to myself. Found an easier (and probably more customizable) way to do that.

I've added tasks to Grunt that watch *.scala.html in ui/{app|dist}/views folders and copy them to Play! app/views folder.

So all templates reside in ./ui folder and dev versions are copied to app/views on run and production versions on grunt.

Closing issue.

milliondreams commented 11 years ago

I good way to get that working :)

But I think it would be a good feature to support... native play templating support for UI files. Will reopen this ticket.

jtammen commented 11 years ago

Don't know whether I am talking about the same topic here, but I'd find it very useful to have an option to put some server-rendered data (e.g. JS objects) into the views. For example, when I need data regarding the currently logged in user on the client, I'd like to avoid making an additional Ajax call and have it instead rendered directly into the template by the server.

Any ideas on how to do that?

Thanks!

PS: Thank you for play-yeoman!

milliondreams commented 11 years ago

Yes, That is the same issue here. I experimented with a couple of ideas to do that, but they didn't work. I will need to explore play internals further for getting out a seamless solutions. In the meanwhile you can get this done using the method mentioned by kompot in his comment above.

samzilverberg commented 10 years ago

@jtammen : I recently had the same prob and solved it, not really elegantly, like so: pass the user, preferably as json, to the scala html template:

@(userJs : play.api.libs.json.JsObject)
@import play.api.libs.json.Json
my base template includes angular related stuff
@base(){
<script>
var loggedInUser = jQuery.parseJSON('@Html(Json.stringify(userJs))');
</script>
other stuff
}

now you just need to get angular to look for that var. you can use $window.loggedInUser in angular to read it (just make sure you add the $window dependency).

You can also do something like:

<div your-angular-directive user-json='@Html(Json.stringify(userJs))'>

and then in the angular directive read it by

scope: {
  user: '@user-json' OR user: '=user-json' and there are some other options.
}

I'm not sure how safe it is to do this for user logged in data. I did it for some other harmless data.

jtammen commented 10 years ago

Hi @samzilverberg, thanks for your reply and suggestion!

Maybe I am getting you wrong, but for me the main problem is that the views in the play-yeoman folder are not being processed at server-side by Play's template engine at all. Or are you proposing to do something like @kompot has done with copying the templates to Play's view folder, via Grunt, for example?

My current solution is that I have an Angular configuration service that simply fetches the needed data via a separate call to the server. Which is not really that elegant and efficient as I'd like it to be...

kompot commented 10 years ago

Also would be nice to have Play process not only views but customizable file tree. E. g. before play-yeoman came along I used some Scala templates logic in JS (injected enum constants into JS from Scala server code, removed some duplication that was not easy in JS by just calling some function returning plain string).

samzilverberg commented 10 years ago

@jtammen : The templates will only be processed by play if they are play templates in the play views dir. So if you want to return the template from the server with some stuff already rendered into you have to make it a play template that takes arguments (userJs in my example) and use this argument in the page.

My solution was like my example, just imagine that "other stuff" is where your angular view or template is. I turn my angular templates/views into play templates (in the views folder) if I want them to be processed by play (for the purpose of adding some server side stuff into then).

Develop-speed wise It's not as fast as developing with just angular templates because when changes are made play has to compile them. For me it's fine, play compiles these templates fast enough for me.

If you can think of a better solution I'll be happy to hear about it!

@kompot : what's the purpose of naming the angular templates with *.scala.html and using grunt to copy them to the play views folder? how are you using these templates differently when they are in the views folder?

kompot commented 10 years ago

I have each angular template (<script type="text/ng-template" id="ID">) in a separate *.scala.html so that it's more readable and Play template engine concatenates them into one. Or I have root abstract template such as

@(templateId: String, ctrl: Option[String] = None)(content: Html)
<script type="text/ng-template" id="@templateId">
  @ctrl.map { c =>
    <div ng-controller="@c">
  }
  @content
  @ctrl.map { c =>
    </div>
  }
</script>

Having Scala power at hand is an advantage.

jtammen commented 10 years ago

Hi @milliondreams, this enhancement looks quite useful to me–any plans when you are going to release version 0.6.3?

milliondreams commented 10 years ago

@jtammen We released play-yeoman v0.6.3 yesterday! Do check it out!

jtammen commented 10 years ago

Hi @milliondreams, thanks, I already checked it out – works like a charm! Thank you very much (-:

kompot commented 10 years ago

Thanks @milliondreams for implementing this.

Don't know whether I did something wrong or it's not there - when running ~run everything works ok, but after dist I see the same template, without being processed by Grunt.

I mean blocks like

<!-- build:css({.tmp,app}) styles/main.css -->
<link rel="stylesheet" href="/ui/styles/sus.css">
<!-- endbuild -->

are the same in production templates after dist task.

Am I missing anything?

Seems like there is hard coded app dir in this code https://github.com/tuplejump/play-yeoman/blob/develop/sbt-yeoman/app/com/tuplejump/sbt/yeoman/Yeoman.scala#L102-L108 that should be changed to dist when running in production?

kompot commented 10 years ago

Last assumption (replacing app with dist) seems to work fine when defining local withTemplates variable in build.sbt with dist instead of app.

So seems like a bug to me.

jtammen commented 10 years ago

@kompot @milliondreams I am also running into some issues here. Can you confirm that this is a bug or a misuse or misconfiguration on my side?

milliondreams commented 10 years ago

@kompot @jtammen I created a new issue to track this #35

Will be great if you can share an application where I can see this error. Would like to fix this in release v0.6.4 which I am planning this weekend.