My favorites | Sign in
Project Logo
Project hosting will be READ-ONLY Wednesday at 8am PST due to brief network maintenance.
                
New issue | Search
for
| Advanced search | Search tips
Issue 5: Support for multiple "ContentPlaceHolders"
11 people starred this issue and may be notified of changes. Back to list
Status:  Accepted
Owner:  ----
Type-Enhancement
Priority-Medium


Sign in to add a comment
 
Reported by aronne2, Jul 31, 2008
Is there a way to have something like "ContentPlaceholders" in the master
file as in aspx forms, so that I can replace for example the content in the
TitleRegion specified in the master file with content coming from the the
current view?
 
Comment 1 by andrew.john.peters, Jul 31, 2008
Yes, to do this just use the partial operator '_' with no arguments. Take a look at
the Application.haml layout in the MVC sample project.
Comment 4 by aronne2, Jul 31, 2008
I meant multiple "named" placeholders, not just for the main content view, sorry.

So in a .master file I would have for example:
<html>
<head>
  <title><asp:contentplaceholder id="TitleRegion" /></title>
  <script>......</script>
  <style>....</style>
  <link>....</link>
  <asp:contentplaceholder id="AddToHeadRegion" />
</head>
<body>
  ....
  ....
  <asp:contentplaceholder id="MainToolbarButtonsRegion" />
  ....
  ....
  <asp:contentplaceholder id="ContentRegion" />
</body>
</html>

and in each .aspx page I could provide content for any of the above named regions:

// mysampleview.aspx
<asp:content contenteplaceholderid="TitleRegion">This is the title for the current
page</asp:content>

<asp:content contentplaceholderid="AddToHeadRegion">
  <script language="javascript" src="script_for_this_specific_page.js" />
</asp:content>

<asp:content contentplaceholderid="ContentRegion">
  My main content goes here
</asp:content>

// end

I'm looking for a similar thing in nhaml, but until now and unless I'm missing
something, I've only seen being able to define just the "main content" placeholder.

I'm really looking forward to use this great view engine, but this is the only thing
holding me back and forces me to continue writing my views in the webforms view
engine. Again, I might be missing something obvious here.

Thanks for you answer in advance.

Comment 5 by andrew.john.peters, Jul 31, 2008
The Title part can be handled using the preamble operator '^'. E.g.

-- Layout

^ var title = "My Default Title"
!!!
%html{xmlns="http://www.w3.org/1999/xhtml"}
  %head
    %title= title

-- View

^ title = "Add Product"

This operator lets you specify code that should be eval'ed first.


Comment 6 by james.e.welch, Aug 21, 2008
Is it possible to have more than one partials equivalent to aronne2s comment above?

For example, if I have 2 or more ContentPlaceHolders in my master file (one for main
view and one for a sidebar view).

A better example would be

<html>
<head>
  <title>Title</title>
</head>
<body>
  <div class="leftColumn">
     <asp:contentplaceholder id="MainToolbarButtonsRegion" />
  </div>
  <div class="rightColumn">
     <asp:contentplaceholder id="ContentRegion" />
  </div>
</body>
</html>

Comment 7 by lanwin.de, Sep 30, 2008
I think this could be done with RenderAction. Example:

%p 
   = Html.RenderAction("AddMainToolbarButtonsRegion")

The you have to implement AddMainToolbarButtonsRegion as Action in you Controller
which can return a second view or plain content or something else.
Comment 8 by lanwin.de, Oct 23, 2008
(No comment was entered for this change.)
Labels: -Type-Defect Type-Enhancement
Comment 9 by lanwin.de, May 14, 2009
Since there is no feedback i expect 

Html.RenderAction("AddMainToolbarButtonsRegion")

resolves the problem.

Status: WontFix
Comment 10 by yfeldblum, May 14, 2009
Yes, Html.RenderAction would be one way to do this.

But there are other ways to do it which I think are very useful, which are named 
blocks a la Django Templates or content placeholders a la ASP.NET. Ruby Haml does not 
do this, but we are asking kindly for an extension to the Haml language which would 
implement named blocks or content placeholders.

Possible syntax for Application.haml, using '?' not at the top-level.

%html
  %head
    %title
      ?myTitleBlock
        Default Title, In Case Concrete View Page Doesn't Override This Block
  %body
    ?myBodyBlock
      %h1= Default Header, In Case Concrete View Page Doesn't Override This Block

Possible syntax for ConcreteView.haml, using '?' at top level indicating to override 
a named block, and not overriding another named block leaving it as the default 
defined in Application.haml.

?myBodyBlock
  %h1= Overridden Header.
  %p= First paragraph of overriding text.
  %p= Second paragraph of overriding text.
  %ul
    - foreach(var obj in Model.Objects)
      %li= obj.Text


Comment 11 by lanwin.de, May 14, 2009
Hmm i dont think that we need an lang extension here. Better would be an haml
specific helper method in like this:

%p
  - var myBodyBlock = CaptureFor() ()=>
    %h1= Overridden Header.
    ...

and later you do

%html
  %head
    %title
      - myTitleBlock()
  %body
      - myTitleBlock()
 

Comment 12 by lanwin.de, May 14, 2009
(No comment was entered for this change.)
Status: Accepted
Comment 13 by yfeldblum, May 14, 2009
Thank you for considering and reopening the ticket.

You are right that, technically, we can do the same thing without a language 
extension.

However, based on seeing Django Templates and ASP.NET content placeholders, I think 
that a language extension in that spirit would be a much cleaner solution, and is a 
solution that people would want to use. Instead of Application.haml having one 
unnamed hole where concrete view content goes, Application.haml would have multiple 
named holes and the concrete view would have multiple named hole-fillers. People 
would be able to use either strategy, the one-unnamed-hole strategy or the multiple-
named-holes strategy, at their option.


Comment 14 by andrew.john.peters, May 14, 2009
Yeah, we should do something here as it makes sense.

I would suggest something in the spirit of how Rails does it:

http://api.rubyonrails.org/classes/ActionView/Helpers/CaptureHelper.html#M001731
http://www.inthetail.com/2008/4/24/ruby-on-rails-content_for

- Andrew.
Comment 15 by yfeldblum, May 14, 2009
The way Rails does it looks decent. I like the way it treats it as an iterable, 
rather than as a single item, so that (to port this to NHaml) for example 
Application.haml could declare a single hole in the <head /> element and then 
concrete a concrete view could declare multiple hole-fillers that would fill the hole 
- for example, it could declare multiple <script /> or <link rel="stylesheet" /> 
elements in different places as hole-fillers, and they would all be used in order of 
declaration to fill the one hole.

A language extension of one character would be nice, because it would then mesh well 
with the rest of the Haml language.


Comment 16 by tdreyno, May 15, 2009
While I use Rails almost every day, I actually prefer the old ASP.NET approach because it allows a default value 
which can then be overridden. The way I use it, I usually have some kind of sidebar which varies it's content on 
some pages. This sidebar's default value is defined in the MasterPage and overridden in the pages that need it.

If the solution is simply a helper, then there should probably be two. A helper in the Application.haml that takes 
a block and either shows it or shows data passed up from a subview if it exists and the above mentioned helper 
for capturing that data in the subview.
Comment 17 by dnagir, Jul 16, 2009
My input: I think the approach from comment #10 is the best one.
Other suggestions are basically workarounds.

#10 is the real deal.
Comment 18 by Boris.Ca...@gmail.com, Nov 05, 2009
I second #10
Comment 19 by lanwin.de, Nov 06, 2009
Nathan Weizenbaum has answered about this question. He think it is not a good idea to
extend this as language feature and i am still have the same opinion about it.

http://groups.google.com/group/haml/browse_thread/thread/f109a30905ef6f3a?hl=en

The best way is to implement it as helper like this:

%html
 %head
   %title
     =TryRender("myTitleBlock") =>
       Default Title, In Case Concrete View Page Doesn't Override This Block
 %body
   %h1
     -Capture("myBodyBlock") =>
       = Default Header, In Case Concrete View Page Doesn't Override
Sign in to add a comment

Hosted by Google Code