Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Claushingebjerg 936 posts 2571 karma points
    Apr 10, 2014 @ 12:23
    Claushingebjerg
    0

    Understanding nesting of Razor code

    I have a razor macro where i list sub nodes from a page. I the need to use an image defined on each node as a background. But the macro crashes when i move the razor code to the "logical" place in the code flow.

    I have this:

    @if (CurrentPage.Children.Where("Visible").Any())
    {
     <div class="row">        
            @foreach (var childPage in CurrentPage.Children.Where("Visible"))
            {
      <div style="background-image:url('')">
          @if (string.IsNullOrWhiteSpace(@childPage.ImageId.ToString()) == false){
              var image = Umbraco.Media(@childPage.imageID.ToString());
              var path = image.umbracoFile;
              var theimage = @image.GetCropUrl("umbracoFile", "topbillede");
          }
      </div>
      }
    </div>
    }
    

     

    This code works, but is executed after the div i need to set the background on. So i cant set the background.
    If i move the Media code before the div like this:

    @if (CurrentPage.Children.Where("Visible").Any())
    {
     <div class="row">        
            @foreach (var childPage in CurrentPage.Children.Where("Visible"))
            {
    
        @if (string.IsNullOrWhiteSpace(@childPage.ImageId.ToString()) == false){
              var image = Umbraco.Media(@childPage.imageID.ToString());
              var path = image.umbracoFile;
              var theimage = @image.GetCropUrl("umbracoFile", "topbillede");
          }
    
      <div style="background-image:url('@theimage')">
          Hello world
      </div>
        }
    </div>
    }

    The macro crashes... Why?

  • Dan 1285 posts 3917 karma points c-trib
    Apr 10, 2014 @ 12:27
    Dan
    0

    Hi Claus,

    Does this fix it:

    @if (CurrentPage.Children.Where("Visible").Any())
    {
     <div class="row">        
            @foreach (var childPage in CurrentPage.Children.Where("Visible"))
            {
    
        if (string.IsNullOrWhiteSpace(@childPage.ImageId.ToString()) == false){
              var image = Umbraco.Media(@childPage.imageID.ToString());
              var path = image.umbracoFile;
              var theimage = @image.GetCropUrl("umbracoFile", "topbillede");
          }
    
      <div style="background-image:url('@theimage')">
          Hello world
      </div>
        }
    </div>
    }
    

    If so, it's because you've opened the Razor block with @foreach so you're 'in' razor at that point so there's no need to have the @ in front of the 'if' statement.

    Hope this helps.

  • Claushingebjerg 936 posts 2571 karma points
    Apr 10, 2014 @ 12:43
    Claushingebjerg
    0

    Yeah it does... but i still cant use the variable i set, because its ouside the closing bracket of the if statement..

    And putting the opening div tage inside the if statement causes an error:

    if (string.IsNullOrWhiteSpace(@childPage.imageID.ToString()) == false){
    var image = Umbraco.Media(@childPage.imageID.ToString());
    var path = image.umbracoFile;
    var theimage = image.GetCropUrl("umbracoFile", "topbillede");
    
    <div style="background-image:url('@theimage')">


    <p>Hello World</p>
    </div> 
  • Dan 1285 posts 3917 karma points c-trib
    Apr 10, 2014 @ 12:58
    Dan
    0

    Ah, then you just need to delare your variables outside of the if too, so they're scoped beyond the 'if' statement. Declare them above the if, then set their values inside the if, and see if that works. Something like this (untested):

    @if (CurrentPage.Children.Where("Visible").Any())
    {
        <div class="row">        
            @foreach (var childPage in CurrentPage.Children.Where("Visible"))
            {
                var image;
                var path;
                var theimage;
    
                if (string.IsNullOrWhiteSpace(childPage.ImageId.ToString()) == false){
                    image = Umbraco.Media(childPage.imageID.ToString());
                    path = image.umbracoFile;
                    theimage = image.GetCropUrl("umbracoFile", "topbillede");
                }
    
                <div style="background-image:url('@theimage')">
                    Hello world
                </div>
            }
        </div>
    }
    
  • Claushingebjerg 936 posts 2571 karma points
    Apr 10, 2014 @ 13:07
    Claushingebjerg
    0

    hmmm, ok... Im used to xslt where the macro will crash if the parameter is undefined.

    I guess razor just returns nothing if the parameter is undefined...

  • Dan 1285 posts 3917 karma points c-trib
    Apr 10, 2014 @ 13:12
    Dan
    0

    Yep, totally different kettle of fish. XSLT is declarative and Razor is essentially C#, which is procedural. I'm still moving over from XSLT too - it'll make sense eventually :) The difficulty I'm having personally is getting the separation with Razor so it doesn't turn into spaghetti.

    Hope that sorted your initial problem anyway.

  • Claushingebjerg 936 posts 2571 karma points
    Apr 10, 2014 @ 14:39
    Claushingebjerg
    0

    Ok, im back. I'm not getting it 100%. Now in aother context. On a template...

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    @{
        Layout = "Master.cshtml";
    }
    
    var image = Umbraco.Media(CurrentPage.topbillede.ToString());
    var path = image.umbracoFile;
    
    <div style="background:url('@image.GetCropUrl("umbracoFile", "topbillede")');">
    <p>Hello world</p>
    </div>    

    Could you explaing why this doesnt work?

    And what if i wanted to check if "topbillede" is defined and only render the style tag inside the div if it was true???

  • Dan 1285 posts 3917 karma points c-trib
    Apr 10, 2014 @ 14:57
    Dan
    0

    Hi Claus,

    Firstly, the variables need to be inside the razor context, so this should work:

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    @{
        Layout = "Master.cshtml";
        var image = Umbraco.Media(CurrentPage.topbillede.ToString());
        var path = image.umbracoFile;
    }
    
    <div style="background:url('@image.GetCropUrl("umbracoFile", "topbillede")');">
    <p>Hello world</p>
    </div>
    

    Secondly, I've not used the crop methods yet so not sure what that returns, but the principle would be that you'd make the whole background statement a variable, so something along these lines (note, this obviously doesn't use the cropping stuff but it shows the basic principle):

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    @{
        Layout = "Master.cshtml";
        var image = Umbraco.Media(CurrentPage.topbillede.ToString());
        var path = image.umbracoFile;
    
        // Instantiate background image variable
        string backgroundImage = "";
    
        // If the image path has a value, create background image value
        if(!String.IsNullOrEmpty(path)){
            backgroundImage = "background: url(" + path + ");";
        }
    }
    
    <div style="@backgroundImage">
    <p>Hello world</p>
    </div>
    

    So, you get your path to the image; if it has a value then you use this value and combine it into a variable along with the CSS background property. Then you just call that variable in the style attribute. I think in the later versions of razor it's even smart enough to not render the style attribute if it has an empty value.

  • Dan 1285 posts 3917 karma points c-trib
    Apr 10, 2014 @ 15:04
    Dan
    1

    I found this article helpful at first - it's well worth reading all the way through and trying to understand as it'll save you a lot of time in the long run: http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx.

  • Claushingebjerg 936 posts 2571 karma points
    Apr 10, 2014 @ 15:09
    Claushingebjerg
    0

    First example makes TOTAL sense, and work perfectly! thanks.

    Second one gives an error. Its not very pleased with the

    var backgroundImage;

    Saying:

     Implicitly-typed local variables must be initialized

     

  • Dan 1285 posts 3917 karma points c-trib
    Apr 10, 2014 @ 15:12
    Dan
    0

    I've edited the example above...

  • Claushingebjerg 936 posts 2571 karma points
    Apr 10, 2014 @ 15:28
    Claushingebjerg
    0

    Bookmarked your link for further studies, thanks :)

    I ended up with this which works:

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    @{
        Layout = "Master.cshtml";
    
        var image = Umbraco.Media(CurrentPage.topbillede.ToString());
        string backgroundImage = "";
    
        if(CurrentPage.HasValue("topbillede")){
            backgroundImage = "background: url(" + @image.GetCropUrl("umbracoFile", "topbillede") + ");";
        }
    }

     

Please Sign in or register to post replies

Write your reply to:

Draft