if/else in layout.cshtml

Topics: Writing themes
Jan 23, 2012 at 9:08 PM

I'm working on a theme and have a question regarding if/else logic in layout.cshtml

I've taken the Theme Machine as the basis for my development.

I'm trying to wrap the layout-content div with another div if the aside-first div is not null. The div I'm trying to wrap around the layout-content div basically pushes the contents to the right to make room for the aside-first div. I know that normally I could simply take care of this in the .css, but I'm attempting to use a standard css framework and therefore don't want to modify it.

I tried simply opening a <div> in the code block for @if (Model.AsideFirst != null) and then adding another @if (Model.AsideFirst != null) block at the end of layout-content with a </div> in it, but that doesn't seem to work.

Instead I added the new <div> wrapper to the @if (Model.AsideFirst != null) block and then created an else{} block without the <div> wrapper.

I don't really like doing it this way because I'm duplicating all of the layout-content code.

Do you have any other suggestions on how I could accomplish this? Thanks.

Jan 23, 2012 at 9:40 PM

There's no reason your first attempt wouldn't work. Can you show the code, might be something obvious you did wrong?

Jan 23, 2012 at 10:33 PM

Sure thing...here's the error message I'm getting

<!--StartFragment--> The if block is missing a closing "}" character.  Make sure you have a matching "}" character for all the "{" characters within this block, and that none of the "}" characters are being interpreted as markup.

here is the pertinent code block (sorry...it wouldn't let me paste it into a code block for some reason)

@tag.StartElement

@if (Model.Header != null)

{

<header id="layout-header" class="group topbar">

    <div id="header" class="topbar-inner">

        <div class="container-fluid">

            @Zone(Model.Header)

            @if (Model.Navigation != null)

            {

                @Zone(Model.Navigation)

            }

        </div>

    </div>

</header>

}

<div id="layout-main-container">

    <div id="layout-main" class="group container-fluid">

        @if (Model.AsideFirst != null)

        {

        <aside id="aside-first" class="aside-first group sidebar">

            <div class="well">

                @Zone(Model.AsideFirst)

            </div>

        </aside>

        <div class="content">

        }

            <div id="layout-content" class="group">

                @if (Model.Messages != null)

                {

                <div id="messages">

                    @Zone(Model.Messages)

                </div>

                }

                @if (Model.BeforeContent != null)

                {

                <div id="before-content">

                    <div class="hero-unit">

                        @Zone(Model.BeforeContent)

                    </div>

                </div>

                }

                @* the model content for the page is in the Content zone @ the default position (nothing, zero, zilch) *@

                @if (Model.Content != null)

                {

                <div id="content" class="group">

                    @Zone(Model.Content)

                </div>

                }

                @if (Model.AfterContent != null)

                {

                <div id="after-content">

                    @Zone(Model.AfterContent)

                </div>

                }

            </div>

            @if (Model.AfterMain != null)

            {

            <div id="layout-after-main" class="group">

                @Zone(Model.AfterMain)

            </div>

            }

            @if (Model.TripelFirst != null || Model.TripelSecond != null || Model.TripelThird != null)

            {

            <div id="layout-tripel-container">

                <div id="layout-tripel" class="group row">@* as in beer *@

                    @if (Model.TripelFirst != null)

                    {

                    <div id="tripel-first" class="span6">

                        @Zone(Model.TripelFirst)

                    </div>

                    }

                    @if (Model.TripelSecond != null)

                    {

                    <div id="tripel-second" class="span5">

                        @Zone(Model.TripelSecond)

                    </div>

                    }

                    @if (Model.TripelThird != null)

                    {

                    <div id="tripel-third" class="span5">

                        @Zone(Model.TripelThird)

                    </div>

                    }

                </div>

            </div>

            }

            <div id="layout-footer">

                <footer id="footer">

                    @if (Model.Footer != null)

                    {

                    <div id="footer-sig" class="group">

                        @Zone(Model.Footer)

                    </div>

                    }

                </footer>

            </div>

        @if (Model.AsideFirst != null)

        {

        </div>

        }

    </div>

</div>

@tag.EndElement

 

Jan 23, 2012 at 11:15 PM

Sometimes Razor objects to the @ sign if it already knows that it's looking at a code block.

As to where and when it decides that this is the case, I find it somewhat persnickety and random :) but this might be one of those cases because your 'if' comes immediately after an @Zone. So just try removing the @ from it. 

Jan 23, 2012 at 11:42 PM

Unfortunately, that wasn't it. It seems to be complaining that I'm opening up that <div class="content"> tag in the code block, but not closing it before I close the code block...which doesn't really make sense to me. I wouldn't think it  would care at this point and would try to render the page before it looks at opening/closing tags.

Jan 23, 2012 at 11:54 PM

Oh right I see :)

Yes it wouldn't like that, because it can potentially produce broken markup. You don't actually know if the value Model.AsideFirst might change before the second if...

There are probably better ways to achieve this layout; but if you want to stick with what you've got you could try just writing a string to emit that wrapping div?

Jan 24, 2012 at 12:24 AM

I'll keep playing around with it to see if I can come up with some sort of better logic. For now, the duplicate code in an else {} statement works so I can continue.

Thanks for the help

Jan 24, 2012 at 1:32 PM

It's pretty simple just to write a string:

@{

  var openDiv = "<div class=\"content\">";

  var closeDiv = "</div>";

}

if (...) {

  @openDiv

}

if (...) {

  @closeDiv

}

 

(You could always use a TagBuilder if you really don't like the above)

Jan 24, 2012 at 4:37 PM

Thanks so much...your reply gave me an even better idea. I used a string variable to hold the class name that is empty by default or "content" when AsideFirst is not null. I render the <div> as <div class="@divClass"> and it either picks up "content" or "". Works perfectly...thanks for the idea!