Grails display gsp inside div - grails

Hey. Imagine i have two separate gsp pages with diferent css formatting (with name conflicts between two). And i want to "display" or render one page with its ows formatation inside a div in the other page. Imagining this scenario:
page1.gsp
...
...
<div id="here"></div>
...
...
page2.gsp
Hello there!
I want my final page to be:
...
...
Hello there!
...
...
Is it possible to do that?

Yes use the g:render tag and create a "fragment" page to contain your content.
then use the g:render tag to pull it in.
Refer to the documentation or tutorials for more detail on this.

This is very similar to a question I posted a couple of days ago:
Can I display an inner dive with an independent stylesheet?

Is this something you want to work for every page? (Like a layout?)
If that is the case, use SiteMesh (built in already)
{app}/grails-app/views/layouts/mylayout.gsp
<html>
<head>
<g:layoutTitle default="My Application" />
<link rel="stylesheet" href="${resource(dir:'css',file:'layout.css')}" />
<g:layoutHead />
</head>
<body>
<div id="here"><g:layoutBody /></div>
</body>
</html>
{app}/grails-app/views/{somefolder}/page1.gsp
<html>
<head>
<meta name="layout" content="mylayout" />
<link rel="stylesheet" href="${resource(dir:'css',file:'page1.css')}" />
</head>
<body>
Hello There!!!!
</body>
</html>
If you already have that, and are just looking at breaking up you pages and keeping them DRY..
{app}/grails-app/views/{somefolder}/page1.gsp
<html>
<head>
<meta name="layout" content="yourLayout" />
<link rel="stylesheet" href="${resource(dir:'css',file:'page1.css')}" />
</head>
<body>
<div id="here2"><g:render template="page2" model="[foo:'bar']"/></div>
</body>
</html>
* The Model property of render is optional, but works for passing data to the template to be rendered
{app}/grails-app/views/{somefolder}/_page2.gsp
* Notice the "_" before the gsp name. (Convention for Template pages)
Hello There
Checkout the documentation for render and templating

Related

Problem in sending session to view at Asp.Net MVC

I want to prevent clients to access route Home/Index when they are not logged in. So the code in my view is here:
#{
Layout = null;
if (Session["userId"]==null)
{
Response.Redirect(Url.Action("Index","Login"));
}
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>QIndex</title>
</head>
<body>
<div>
<h1>Profile</h1>
<h2>Hello #Session["userName"].ToString() </h2>
<a href=#Url.Action("LogOut","Login")>خروج</a>
</div>
</body>
</html>
Problem is that when i eliminate #Session["userName"].ToString() everything is alright. But when this is not eliminated, an error occurs on this line System.NullReferenceException: 'Object reference not set to an instance of an object.'.
I set a break point on if (Session["userId"]==null). I realized that compiler goes to <h2>Hello #Session["userName"].ToString() </h2> before it checks the if statement and then returns to if.
Just remove .ToString(). It should render the string properly without it.

Rails - failing to set open graph url correctly

I am developing a Rails application and I wish to use the open graph protocol so that on the "articles" page perople can link to social media (facebook, twitter, and google+) to recommend/like etc the article.
As part of the this I endevour, unsuccessfully to set og metatags for the url, within the head section of the page. From the code partial ogmeta.html.erb
<meta property="og:title" content='<%= meta[:title] || "DrillInvestor" %>'>
<meta property="og:type" content='<%= meta[:type] || "website" %>'>
<meta property="og:image" content='<%= meta[:image] || "http://www.whatever.com/image.jpg" %>'>
<meta property="og:url" content='<%= meta[:url] || "post_url(#post)" %>'>
Which when I view the page source I see
<html>
<head>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<meta property="og:title" content='DrillInvestor'>
<meta property="og:type" content='website'>
<meta property="og:image" content='http://www.whatever.com/image.jpg'>
<meta property="og:url" content='post_url(#post)'>
What I am trying to pass as the url I can see from a print statement in the posts controller
puts "==================="
puts "url = " + post_url(#post).to_s
I see url = http://quiet-fortress-3338.herokuapp.com/posts/drill-01-more-updates which is what I am want, in this case, to see as the og:url.
I am a recovering COBOL pogrammer and sometimes (well perhaps more than that) lose my way with this sort of stuff.
If I hardcode the og:url I get the appropriate page. I have tried a numer of dfferent things including#{} enclosing the post_url(#post) etc.
Thanks in advance and any help welcome
Pierre
You need to get rid of the quotes around "post_url(#post)". Just change it to post_url(#post). Note that in your print statement you don't have it enclosed in quotes and it works.
As an aside, you don't need to call to_s in either case - post_url(#post) returns a string.

RenderSection Scripts not showing in Head Tag

I have a problem with the following. I have a masterpage which contains the main layout of the site. Then I have a specific view which uses the masterpage as a layout but adds additional scripts like the following:
_Masterpage.cshtml
<html lang="en">
<head>
<meta charset="utf-8" />
<title>#ViewBag.Title - My ASP.NET MVC Application</title>
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<meta name="viewport" content="width=device-width" />
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
#RenderSection("head", required: false)
</head>
<body>
<header> ....
_Register.cshtml
#{
Layout = "_Master.cshtml";
}
#section head
{
#Scripts.Render("~/bundles/jqueryval");
#Styles.Render("~/Content/themes/base/css");
}
<div id="body">
<div data-role="page">
#RenderBody()
</div>
</div>
Now my view which contains the form data makes use of the _Register.cshtml, however when the Index in the RegisterController returns the view (like below), the scripts and styles in the _Register.cshtml are not found anywhere in the Head tag.
public ActionResult Index()
{
return View();
}
Can anyone help me please? What am I missing in order to get these scripts/styles in the head tag please?
Thanks
Sections don't work in partial views and that's by design. You may use some custom helpers - Using sections in Editor/Display templates - to achieve similar behavior, but honestly it's the view's responsibility to include the necessary scripts, not the partial's responsibility. I would recommend you using the #scripts section of the main view to do that and not have the partials worry about scripts

Grails g:include can it be done?

Im wondering if it is possible to use g:include to include only the body contents of a given page.
Say i have a main layout page as follows:
<html>
<head>
<title>My start page</title>
<g:layoutHead>
</head>
<body>
<g:layoutBody>
</body>
</html>
Then a main page (index.gsp)
<html>
<head>
<!-- main layout reference -->
<meta name="layout" content="main"/>
</head>
<body>
THIS IS MY INDEX BODY CONTENT WITH AN INCLUDE
<g:include controller="book" action="list"/>
<g:link controller="book" action="list">See the full list!</g:link>
</body>
</html>
And finally the book/list page
<html>
<head>
<!-- main layout reference -->
<meta name="layout" content="main"/>
</head>
<body>
<table>
<g:each in="${books}">
<tr>
<td>${it.author}</td>
<td>${it.title}</td>
<td>${it.price}</td>
</tr>
</g:each>
</table>
</body>
</html>
So what i want to achieve is that the main page (index.gsp) only includes the table defined in the book/list page. However, when i try this it includes the entire html defined (<html> tags and all).
is it possible to do this somehow? i've tried things like <g:include controller="book" action="list" view="someView.gsp"/> however this doesn't work. I really want to avoid having to add a book list logic to the "index controller" i want to reuse my existing controller.
I can't be the first person out there having this usecase, what solutions have you guys come up with?
You can use the applyLayout tag. Simply create an empty.gsp layout with only:
<g:layoutBody/>
And then decorate your include tag with applyLayout:
<g:applyLayout name="empty">
<g:include controller="book" action="list"/>
</g:applyLayout>
See the entry on the Grails guide for further reference.
This is IMHO directly not possible. An idea would be to create a custom tag based on g:include, that strips out parts of the code by e.g. an xpath expression. I'm not aware that this already exists somewhere.
An alternative would be to refactor the body part of book's list.gsp into a template and reference that template from index.gsp using g:render. But this means that the data model has to be available in index.gsp context since g:render does not invoke a controller.
Side note: when using g:include it's a good idea to use the springcache plugin for page fragment caching.
Yes, but you need you need one more level in there. Look at Grails templates. Essentially, you'd have a template: _books.gsp containing:
<table>
<g:each in="${books}">
<tr>
<td>${it.author}</td>
<td>${it.title}</td>
<td>${it.price}</td>
</tr>
</g:each>
</table>
Then your index would be:
<html>
<head>
<!-- main layout reference -->
<meta name="layout" content="main"/>
</head>
<body>
THIS IS MY INDEX BODY CONTENT WITH AN INCLUDE
<g:render template="books">
<g:link controller="book" action="list">See the full list!</g:link>
</body>
</html>
And your list would be:
<html>
<head>
<!-- main layout reference -->
<meta name="layout" content="main"/>
</head>
<body>
<g:render template="books" />
</body>
</html>
(My syntax may not be 100% right, since it's been a couple months since I've done this, but the idea behind templates are short, reusable pieces of GSP code that aren't meant to be displayed on their own.

ASP.NET MVC - Executing Code everytime the Site.Master is processed

I'd like to add a little variablility onto the path of my css link everytime my Site.Master view is processed. What is the correct way to do this? My code currently breaks on the Default.aspx saying I have not defined cssLink. Site.Master code below:
<script runat="server">
void Page_Load(object sender, EventArgs e)
{
string cssLoc = "../../Content/css/expect.css?t=" + DateTime.Now.Ticks.ToString();
string cssLink = String.Format(#"<link rel=""stylesheet"" type=""text/css"" href=""{0}"" />", cssLoc);
}
</script>
<!DOCTYPE html>
<html>
<head id="Head1" runat="server">
<asp:ContentPlaceHolder ID="head" runat="server">
<title></title>
</asp:ContentPlaceHolder>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<%= cssLink %>
<script type="text/javascript" src="../../Scripts/jquery.js"></script>
</head>
Also, is there anyway to fix the "XHTML transitional, Title occurs too few times" message?
UPDATE:
Please ignoring the scoping issue. See Richard's answer. I should note however that fixing this does not solve the issue.
I think because of the Inherits="System.Web.Mvc.ViewMasterPage" declaration the entire
<script runat="server"> block does not get processed.
Just define your css link like you typically would and add some inline processing. You are attempting to do a Page_Load within a MVC view which is not a workable solution...
<link href="../../Content/css/expect.css?t=<%=DateTime.Now()%>" type="text/css" rel="Stylesheet" />
Consider writing a helper to link that CSS file.
public static string DatedStylesheet(this HtmlHelper Html, string url, DateTime date)
{
UrlHelper Url = new UrlHelper(new RequestContext(Html.ViewContext.HttpContext, Html.ViewContext.RouteData));
string html = "<link type=\"text/css\" rel=\"stylesheet\" href=\"{0}?t={1}\"/>";
return string.Format(html, Url.Content(url), date.Ticks.ToString());
}
<%= Html.DatedStylesheet("~/Content/css/expect.css", DateTime.Now);
On an unrelated note, does anyone know a cleaner way to do use UrlHelper outside of a view page?
You have declared cssLink as a local variable in Page_Load. As such, it will not be available to your page.
This should fix the issue for you:
<script runat="server">
private string cssLoc;
private string cssLink;
void Page_Load(object sender, EventArgs e)
{
cssLoc = "../../Content/css/expect.css?t=" + DateTime.Now.Ticks.ToString();
cssLink = String.Format(#"<link rel=""stylesheet"" type=""text/css"" href=""{0}"" />", cssLoc);
}
</script>
<!DOCTYPE html>
<html>
<head id="Head1" runat="server">
<asp:ContentPlaceHolder ID="head" runat="server">
<title></title>
</asp:ContentPlaceHolder>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<%= cssLink %>
<script type="text/javascript" src="../../Scripts/jquery.js"></script>
</head>
Edit: Aside from answering your direct question, I would recommend finding a more MVC-friendly solution (rather than putting code in your master page). For example, you could include the css location as ViewData["Stylesheet"] or use a different mechanism to update the css (I'm not up to date on the RC of MVC)
<head runat="server">
<title>Some Title</title> -- WILL FIX YOUR ISSUE
...
<%= Helper.CustomStyle() %>
...
</head>
This Helper.CustomStyle will have the logic inside that varies based on a DateTime.Now call as seen above.
A very good tutorial that will help you to understand the Custom Helpers can be found here: http://www.asp.net/learn/mvc/tutorial-09-cs.aspx
REMEMBER -- ASP.NET MVC does away with Page_Load type calls. It's a distinct design pattern!

Resources