I've tried a lot of combinations but still getting run time errors:
#{Html.RenderPartial("~/Views/_" + #Model.Id + ".cshtml")};
Is there something obvious I'm getting wrong. I have the Id field in model set correctly but I get syntax errors. Such as:
Compiler Error Message: CS1002: ; expected
You can't have the semi-colon at the end. Edit: You actually need it right after the call of the RenderPartial because you are using curly braces. Also, you do not need the # for the Model. You also do not need the .cshtml.
#{Html.RenderPartial("~/Views/_" + Model.Id);}
I'm also a little worried of how you are using the Model's ID for the name of the partial view. Be sure to check your paths and the names of your partial views.
You may want it to look something like this:
#{ Html.RenderPartial("_AwesomePartialView", Model);}
Check out this too: http://rachelappel.com/razor/partial-views-in-asp-net-mvc-3-w-the-razor-view-engine/
Related
I don't know if the following change is an issue or it is intended.
<g:include view="line.gsp" params="['label':'test', 'progress':false]"/>
Then the expression in line.gsp aways evaluates to true, because the type of the 'progress' param is String, not Boolean.
class is: ${params.progress.getClass()}
<g:if test="${params.progress}">
this should not be displayed
</g:if>
Note that the same is applicable for other types, not just Boolean.
I am using grails 3.3.8
This didn't happen in grails 2.5.2.
I didn't find anything about this online so that's why I am asking here. Thanks.
Edit:
As suggested by Daniel, I've tried with grails 3.3.2 also.
I just created an app with grails create-app and modified the existing index.gsp to include line.gsp, as shown in the code above.
Here is a screenshot:
I realize you have already found a workaround to this, but it was bothering me that your code was not working the same way mine was, so I decided to investigate a bit further in case anyone else runs into this issue.
As other people here have mentioned, params.anything will typically return a String value. This is because params are typically encoded as URI parameters (like ?progress=false) and not autoboxed into any other type. (This is perfectly reasonable; there would be no good way for Grails to know what type they should be.) However, it is possible (and occasionally reasonable) to render your view or template from a controller like render view: whatever, model: [your: model, params: params] where you specifically include params in the model. (Perhaps you have a lot of parameters that you do not need to individually recreate in the model.) In this case, the params map will exist as both URI parameters (?progress=false) and page-scoped model entry (params: [progress: Boolean.FALSE]). Page scope takes priority over URI parameters, and so your types will be preserved.
In my testing, I added your code to an existing page where I was already passing params into the model, and so type was preserved for a newly added parameter as well. (Note that once params are in page scope, they're there for included templates or views as well.) Consequently, I saw progress type of Boolean, while in a basic example it would be type String.
TL/DR: either assume params are strings, or explicitly include params in your page-scoped model when rendering.
Yes, this is true. When you are calling params.something, you are actually accessing GrailsParameterMap which is a Map. So your condition actually evaluates as Map->get() which will be Object->toString() and of course it is true cause it's not null and not empty. So the solution will be the following:
<g:if test="${params.getBoolean("progress")}">
this should not be displayed
</g:if>
You can test this as follows
<g:if test="${params.progress && params.progress == 'false'}">
this should not be displayed
</g:if>
If I have a partial named _string.erb and try to render it with something like:
= render partial: "string", object: "Some string i want to show in some manner"
And then try to reference in my partial with the name string it throws the error
undefined local variable or method 'string'
The only thing I can think of is that the object name is reserved. If something else is going on I would love to hear about it.
Just for clarity, everything works fine for a partial with another name. eg in the partial dog rendered with the following code
= render partial: "dog", object: "Some string i want to show in some manner"
I can reference the variable dog without any issues. I am also NOT using #string.
I realize I may be able to find this out by digging into the actual source code (which I intend to do after posting this), but if anyone has an idea what is going I would love to hear it. If I find a solution I will post it.
EDIT - edited to add the exact error being thrown due to questions about it in the comments.
EDIT - I tried to simplify my example when writing this and ultimately ended up proving that string isn't a reserved keyword, and my code was erroring because the value I was passing was nil in the db.
There is no official definitive list of reserved words. The list found at https://reservedwords.herokuapp.com/ is the best I've come accross. String is included in the list, so very well may be the cause of your issue.
I am 99% sure the source of my error was that my string I was passing in was nil. I expected this to return nil to the partial under that variable name string, but that doesn't appear to be the case and I just missed it.
According to ruby docs, the translate (or t) helper delegates to I18n#translate but also performs several additional functions, among which is: "it’ll mark the translation as safe HTML if the key has the suffix _html".
I would expect that it should work equally in both views and in controllers, but in my experience it doesn't: t(:hello_html) does work as expected in views (marks the translation as html_safe), but it does not mark the result as safe html when invoked from a controller.
To reproduce the problem you could add hello_html: '<i>Hello world</i>' to your locales/en.yml and flash.now[:notice] = t(:hello_html) to any convenient action of any controller. For me that resulted in an escaped html markup in a flash messages area which was an unexpected outcome for me.
My questions are:
is there anyone else who experienced or is able to reproduce this problem?
what is it: a rails bug, a feature, or just my project's unique "oddity"?
is there any easy way to work this around?
(Tested in rails 3.2.11 and 3.2.13)
You are correct about this functionality not being available to controllers given that the overloaded .t method is defined in ActionView::Helpers::TranslationHelper. I think this is probably an oversight as opposed to an actual bug.
Off the top of my head there are 2 ways you can get around this in your project :
Call .html_safe in your controller (this worked for me in a quick test).
flash[:notice] = t(:hello_html).html_safe
Send the translation key as the flash message as opposed to the actual message :
Controller :
flash[:translate_notice] = :hello_html
View :
%div= t flash[:translate_notice]
Granted, the latter option might get a bit messy if you need to pass interpolations, YMMV.
The "_path" route helper returns string not marked as html_safe.
I don't know for sure - maybe it's indeed not html safe, but when I pass something like "foo>bar" to _path helper it generates string like:
/aa/foo%3Ebar/bb
Which looks safe.
However, html_safe? for that string is false and if I pass it to template, expectedly I've got:
/aa/foo%3Ebar/bb
Which looks not so nice.
I can call .html_safe on helper output, but maybe there are some cases when _path helpers emit unsafe characters?
Anyway, I don't like the idea to call html_safe on every helper output, and hope that framework take care of that stuff.
Any thought?
This is quit usefull becaus the client may pass variables to the url and if the path would be marked as html_safe for deafult he could simply write some javascript/html/... to the url and it would be executed. That is called a Cross Site Scripting and one of the most "popular" security holes. Of cause its "only" a client side attack but it might get dangerous for your users so its better to not change this by default!
In one of my templates I want to take a closer look at the controller object using the debug() helper.
It is said to produce YAML suitable for HTML output.
Running <%= debug(controller) %> does, however, not produce anything I call readable.
It begins with:
#<ClubsController:0x104467378 #_request=#<ActionController::Request:0x104467648 #accepts=[#<Mime::Type:0x101f50f30 #synonyms=["application/xhtml+xml"],
and goes on like that...
Any ideas on how to get some info about the object?
The debug helper is primarily intended to be used with objects that provide an implementation of to_yaml (such as ActiveRecord models). If the object passed doesn't respond to to_yaml (as is the case with passing a controller object in your example) then debug gives you the result from calling inspect on that object.
I saw your comment #thenduks answer.
Actually there is a method:
controller.controller_name
that returns the name of the controller.
What's not readable about that? It's the standard ruby inspection syntax... If you really need something 'more readable' then you'll have to write a method on your controller (temporarily, most likely) that simply exposes it's instance variables in another format.
Perhaps it would help if you noted what you want to see in the controller instance.