scaffolding withFormat views is not working - grails

I would like to use withFormat within my scaffolding controller and added a scaffolding view 'list.csv.gsp'. But without generating my list.csv.gsp view, grails doesn't use the scaffolding list.csv.gsp view.
After generating de list.csv.gsp view it works fine. But I won't create all these views, because they are all the same.
My scaffolding controller list action ends with the code below:
withFormat {
html {
[${propertyName}List: ${propertyName}List, ${propertyName}Total: ${propertyName}List.getTotalCount(), params: cleanParams(params)]
}
csv {
response.setContentType('text/csv')
response.setHeader('Content-Disposition', "attachment; filename=\${message(code: '${domainClass.propertyName}.label')}.csv")
[${propertyName}List: ${propertyName}List]
}
}

I don't know if you still have a problem with this but the grails docs for with format have this quote:
Grails ignores the HTTP Accept header unless you add a grails.mime.use.accept.header = true setting to your Config.groovy file. In other words, withFormat() will be completely unaffected by the Accept header without that setting.
See withFormat in the grails docs.

On your view you might need to write it generic and put in a common directory and refer your controller template to use it. Maybe make it as a _template and render it.
hope this helps.

Related

Grails Resources Plugin encoding issue with code = html

According to Marc Palmer
Preventing XSS attacks
In a nutshell, to protect your app from code injection XSS exploits
you must:
Set the default grails.views.default.codec in config to "HTML"
OK.
So if I have this below in my Config.groovy
grails.views.default.codec = "none"
And in my Controller, I add:
def afterInterceptor = { model ->
model.headerJs = "alert('bingo for '+[$params.unitId]);"
}
And in my GSP:
<r:script disposition="head">${headerJs}</r:script>
It works. I see the expected javascript alert when I do View Source and I get my alert when the page serves.
But, if in Config.groovy I apply the recommended change:
grails.views.default.codec = "html"
My GSP renders
<script type="text/javascript">alert('halooba for '+[1]);</script>
which I can see is very secure.
My goal with this app is to have custom JS snippets, various properties and other values stored for the customer in the Domain. These values would be entered by our Admins (not the customer). Based on who invokes the page with an HTTP request, such as www.mydomain.com/ThisApp/?customerId=13423 (but an encoded customerId) I'd make calls to Services from my Controller to fetch the associated settings for the customer from the Domain and inject them into the GSP.
I know that I can put JS and CSS into files and then use the Resources Plugin to bring them in properly, but I'm also looking at this method for specific customizations.
So, to follow this security method, I either need to be able to unencode this, or I need to determine another method for including javascript into the GSP that does not encode it.
Any suggestions?
THANKS!
You can suggest Grails not to escape by using raw() available in GSP as:
<r:script disposition="head">${raw(headerJs)}</r:script>
For Grails 2.2.x and below, you can put the recommended encoding in your Config.groovy:
grails.views.default.codec = "html"
and use a Taglib to bring in values that are SAFE and should not be HTML encoded:
<r:script><com_myapp:getJSDeferred unitId="${params.unitId}" /></r:script>
and it will be rendered raw.
FYI: Above solution will not allow for JSON output to assign to javascript variable.
My workaround, say you have model.data defined as hashmap:
var someVar= ${raw(data as JSON).toString())};

How to use a gsp template to create a text file?

I have used the Grails Rendering Plugin in the past with much success in creating PDFs. Throw now I would like to create a simple text file, using a gsp. I loved the ease of using a model to define how to insert information into the template. I realize I don't need to render a text file, but is there a similar way to use a template to just create an ordinary text file?
Example from how to render a jpg using the Grails Render Plugin: (notice the model use)
def bytes = gifRenderingService.render(template: '/images/coupon', model: [serial: 12345])
// Render to a file
new File("coupon.jpg").withOutputStream { outputStream ->
jpegRenderingService.render(template: '/images/coupon', model: [serial: 12345])
}
If there isn't an easy way like the above example, since my information is coming from multiple domain classes should I just create <g> tags in my gsp template that pulls based on conditions needed? If that is the case.. how would I insert a variable into my gsp template from my service?
You might take a look at the grails.gsp.PageRenderer utility class. It allows you to render .gsp templates as a String:
String gspOutput = groovyPageRenderer.render(view: '<your view>.gsp', model: [ modelObj1: ... ])
... or directly to a Writer or OutputStream:
groovyPageRenderer.renderTo(view: '<your view>.gsp', model: [ modelObj1: ... ], <writer or OS>)
Much more detail can be found here: http://mrhaki.blogspot.com/2012/03/grails-goodness-render-gsp-views-and.html
To render the template as text file you should set the content type of the response to text/plain
I'd think you just create your text template as standard, with <g> tags etc..., then call the standard grails render() function on the template with a contentType of 'text/plain'. No plugin necessary?
Add the following code to the GSP file
<%#page contentType="text/plain"%>

Approach for AngularJS template translations with Rails server

I need to implement an application with multi-language support using an AngularJS front-end and a Ruby on Rails server.
I am looking for a reasonable approach to render translated templates in multiple languages. I have come up with an approach I would like feedback on.
In the Angular routes definitions, set the template property to an html partial that just has an ng-include with the src attribute value set by the controller. This approach is needed to dynamically modify the path to the template to be fetched from the server; it is described here:
AngularJS - How to use $routeParams in generating the templateUrl?
So the Angular route config would look like:
angular.module('myApp', []).
config(function ($routeProvider) {
$routeProvider.when('/sites/new', {
template: '<div ng-include src="templateUrl"></div>',
controller: 'RouteController'
});
});
And the controller would look like:
// Set a prefix on the URL path, something like “es”
function RouteController($scope, $routeParams) {
$scope.templateUrl = $routeParams.locale + "/template/sites/site";
}
Here $routeParams.locale is used to set the locale, but could be a variable set by user action. The approach for dynamically modifying the template URL path to add a locale prefix seems a bit convoluted, but I know of no other way.
On the Rails side, in routes.rb, add a route:
match '/:locale/template/*template' => 'template#get'
The route uses route globbing so the params[:template] value can be a multi-level path.
The TemplateController#get action just renders the partial determined by params[:template]
The Template controller code is something like:
class TemplateController < ApplicationController
layout false
caches_page :get
def get
render(template: "template/#{params[:template]}")
end
end
The Rails I18n support for translations is used in the erb templates, translating according to the locale parameter.
In production, caching would be turned on. This would avoid incurring translation overhead. The locale prefix of the URL path would result in a per language set of translated templates to be cached.
This approach pushes translations processing to the server side as much as possible.
Is there any fundamental problems with this approach?
Could it be done better?
You may be interested in the angular-translate module.
We achieved client side internationalization in AngularJS with the i18next JQuery plugin http://i18next.com/ and created a filter called i18n.
When you initialize the Angular Application, you initialize the i18n plugin where you can provide a pattern to locate the file containing labels, and in the template use this as an example for binding labels and values.
{{'mynamespace:labels.firstname' | i18n}}
where "mynamespace" is used to separate your labels logically and used to locate JSON files with the labels. Within json files you can have one or more JSON objects with labels as properties. In the above example, the file called mynamespace-i18n-en-US.js if you provided a pattern __ns-i18n-__lng__.js
Is there a reason why the translation has to happen on the server?
Do you really need to translate the entire template?

how do i dynamically change my format rendering engine in rails?

My default templating engine is haml, but I would to sometimes change it to erb if i specify a specific parameter?
For example, I am pasting in some html code and would just like to test the code without HAML complaining about its format.
Any idea how to do this?
do something like:
if params[:render_erb]
render 'file.html.erb'
else
render 'file.html.haml'
end
and call the action with ?render_erb=true
or
render "file.html.#{params[:render]}" ir params[:render]
and call it ?render=haml or ?render=erb (or nothing and it will use the default
at the end of the controller's action that you are using
Am I wrong that you simply need to save file as your_file.html.erb instead of your_file.html.haml?
You can use different templates in the same application, and you can use different template engines for views, partials, and layouts, but as far as I know you can't duck in and out of multiple template engines within the same template file.
If you just want to drop some code in using a different template language, then I'd put it in a separate partial. That certainly seems easiest in this particular case.

I can't get the grails controller "render" method to work with an explicit template

I'm just getting started with grails, and I'm having an issue.
I have a "controller" and "view" for the projects home page (there's no model for the home page)
I called the view "index.gsp", and put it in a directory views/home
However, no matter what I do, grails is trying to read the page "home.gsp" (and then home.jsp), despite me having explicitly specified the index with the "template" attribute in the render call.
class HomeController {
String someparameter = "xyzzy"
def index = {
render(view:"home", template:"index") // I also tried "index.gsp" and "home/index.gsp"
}
}
I think I may be using the "template" attribute wrong, because I only see it used in examples for view-less template rendering. However the documentation gives no such limitation.
Is there any way to explicitly specify the name of a template? I just caved in and renamed it "home.gsp", but I'd like to understand what's going wrong.
(The home page in this application has no "model". Grails will use the controller has the model. In this example, you can access "someparameter" in the gsp template as ${someparameter}.)
I think you may be misunderstanding what a Grails template is. Think of a template as a reusable fragment. A template is a GSP that starts with an underscore like _menu.gsp that you would typically render from within another GSP with the a tag like <g:render template="menu"/>.
It doesn't make sense to render both a view and a template at the same time. They are mutually exclusive at this point.
Are you looking to implement a Layout? If so, see the docs or the grails.org explaination.
Basically, your view you would have a <meta name="layout" content="main"> tag in the <head/> tag of your view -- which indicates that the view will be meshed together with the main layout located in grails-app/views/layouts/main.gsp

Resources