Jeff-Lewis / nhaml

Automatically exported from code.google.com/p/nhaml
0 stars 0 forks source link

Rendering partial .haml template through RenderPartial does not indent output correctly #18

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago

What steps will reproduce the problem?
1. Call RenderPartial from a .haml template 

Application.haml
- MasterViewData masterData = (MasterViewData)ViewData;
!!!
%html{xmlns="http://www.w3.org/1999/xhtml"}
  %head
    %title= The Title
  %body
    #page
      #header
        #title
          %h1= The Title
        - Html.RenderPartial("_Menu", masterData.MainMenu)
        .clear
      #main
        _
      #footer
        NHaml Powered © Copyright 2008

What is the expected output? What do you see instead?
I would expect the partial indented from the previous node, as it happens 
when the partial is rendered through the _ mechanism. Instead, the partial 
is indented from the beginning of the line.

This is the output:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 
Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-
transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>
      The Title
    </title>
  </head>
  <body>
    <div id="page">
      <div id="header">
        <div id="title">
          <h1>
            The Title
          </h1>
        </div>
<ul id="menu">
  <li>
    <a href="/">
      Inicio
      <br />
      <span>
        Somos especialistas en Grandes Viajes
      </span>
    </a>
  </li>
  <li>
    <a href="/destinos">
      Nuestros viajes
      <br />
      <span>
        Los cinco continentes a tu alcance
      </span>
    </a>
  </li>
  <li>
    <a href="/propuestas">
      Ofertas y propuestas
      <br />
      <span>
        Las mejores propuestas para viajar todo el año
      </span>
    </a>
  </li>
</ul>
        <div class="clear">
        </div>
      </div>
      <div id="main">
        Main content
      </div>
      <div id="footer">
        NHaml Powered &copy; Copyright 2008
      </div>
    </div>
  </body>
</html>

What version of the product are you using? On what operating system?
Latest version

Please provide any additional information below.

Original issue reported on code.google.com by germanft...@gmail.com on 6 Nov 2008 at 10:00

GoogleCodeExporter commented 9 years ago
MVC RenderPartial is evaluated independently at runtime by writing directly to 
the 
underlying output TextWriter and therefore can have no knowledge of the parent 
template's current indent level. Or even that there is a parent template at all!

Use the built-in partial operator '_' to merge the partial at compile time and 
the 
indenting will be correct.

Cheers,

Andrew.

Original comment by andrew.j...@gmail.com on 7 Nov 2008 at 7:30

GoogleCodeExporter commented 9 years ago
@germanftorres: For what you need that indentation? Haml dose not ensure that 
the
output i correct indented. This is only waste product. 

Original comment by lanwin...@gmail.com on 7 Nov 2008 at 8:37

GoogleCodeExporter commented 9 years ago
@andrew: I don't want use the built-in partial operator _ as I can't specify 
wich 
ViewData or Model pass to the partial (In my case I'm passing a Property of the 
parent template's Model). If there was such a mechanism I would surely call the 
built-in partial operator which had knowledge of the parent template's indent 
level.

@lanwin.de: I agree. Indentation isn't strictly needed. But issue #7 is about 
controlling whitespace throgh < and > operators. That isn't needed either but 
is 
implemented in other haml engines and I guess NHaml is considering adding that 
useless, style-centric feature. Anyway, I can live without indentation but I'm 
sure 
devs like to see their html output properly formatted

Anyway, Great, great stuff. Thanks a lot. Germán.

Original comment by germanft...@gmail.com on 7 Nov 2008 at 12:07

GoogleCodeExporter commented 9 years ago
All your view data of the parent are also visible for the partials. So you can 
access
your ViewModel also from the Partial. 

No the < and > are not only for styling, because otherwise if you put 3 images
together there are having a spaces between them, that comes from the whitespace 
which
is elsewhere. 

I talked to Andrew i he pointed me out that i am not right. It is a goal of 
haml to
output better readable and indented code.

Although, i currently only see one way to indent this output correctly. Parse 
the
result of the = operation and re indent it at runtime. But that slowes down the
output generation only for styling.

Original comment by lanwin...@gmail.com on 7 Nov 2008 at 12:56

GoogleCodeExporter commented 9 years ago
Thanks!

I'm aware that it's possible to access the whole parent's ViewModel within a 
partial. The problem I see is that if we wan't a true partial reusability we 
need to 
decouple the partials ViewModel from the parent's ViewModel.
Suppose I want a partial for rendering an IList<Product>. I need to render 
various 
IList<Product> in some places in the same page (e.g. 
IndexViewData.FeaturedProducts, 
IndexViewData.MyViewedProducts). With built-in partial I can not specify in the 
parent that I want same partial applied to different Properties in my 
ViewModel. the 
partial only knows about a type (IndexViewData) and doesn't know wich property 
to 
render. In this scenario with the buil-in partial I would create two partials 
clones 
violating DRY principle.

In this scenario the only thing that is working for me is doing
- RenderPartial("_ProductList", IndexViewData.FeaturedProducts)
- RenderPartial("_ProductList", IndexViewData.MyViewedProducts)

This is good for me. I don't mind calling Mvc to do this stuff. But maybe this 
is 
something to you to consider in the future. Thanks!!

 With the partial soluction I want' to promote template reusability. A partial is a 
small part of the whole. Different controller actions yield diffent 
ViewData<TModel> 
with

Original comment by germanft...@gmail.com on 7 Nov 2008 at 1:58

GoogleCodeExporter commented 9 years ago
Because an NHaml partial is effectively a template merge, you could also do 
this:

- var products = IndexViewData.FeaturedProducts ?? 
IndexViewData.MyViewedProducts
_ ProductList

Now, ProductList must simply refer to the "products" variable.

Original comment by andrew.j...@gmail.com on 7 Nov 2008 at 10:27

GoogleCodeExporter commented 9 years ago
We could even make sugar for this:

_ ProductList, IndexViewData.MyViewedProducts

expands to:

- var productList = IndexViewData.MyViewedProducts
_ ProductList

Original comment by andrew.j...@gmail.com on 7 Nov 2008 at 10:31

GoogleCodeExporter commented 9 years ago
Ok, or something that may pass more named parameters to the partial

_ ProductList{products=IndexViewData.MyViewedProducts, highlightOffers=true}

that expands to a scoped block of code to use it multiple times in the same 
parent 
template without variable name collision:

{
 - var products = IndexViewData.MyViewedProducts
 - var highlightOffers = true
 _ ProductList
}

Regards.

Original comment by germanft...@gmail.com on 8 Nov 2008 at 9:20