javascriptcontrollerrenderingsitecore

Sitecore - render code to add value to database if item is NULL


In Sitecore you can easily render a context item's value by using

@RenderingContext.Current.Rendering.Item["itemname"]

However: when I place a Controller Rendering to a placeholder there is no content assigned yet. therefore nothing will be rendered, and therefore I can't check for null.

My specific problem:
I want to add the value of a database item to the parameters of a call.

var options = {{lat: @RenderingContext.Current.Rendering.Item["lat"],
    lng: @RenderingContext.Current.Rendering.Item["lng"]},
    zoom: @RenderingContext.Current.Rendering.Item["zoom"]};

As there is simply NOTHING (yet) the partial view fails to load because there is no associated content (yet) ==> javascript error. If there is content it works fine.

So how can I

Any idea? Anyone who's got my problem?

Cheers!


Solution

  • You have a few options available to you, I would suggest a combination of things depending on your needs but you also want to be defensively coding in all aspects since content authors have the potential to do things that they should not!

    You can set some default values for your templates so that they always have an initial value. With your template selected and the Builder tab highlighted, select the Options tab from the ribbon and then add Standard Values

    Standard Values

    A new item called __Standard Values will be added under the template, you can set default values there. Make sure you have set the Datasource Location and Datasource Template fields on your rendering which will cause the prompt to create/select datasource item.

    You still need to defensively code though. How you do this is up to you. For example, if certain fields are not set correctly then maybe you do not show the component at all or return a different view to show it is incorrect:

    public class WidgetController : GlassController
    {
        public ActionResult Index()
        {
            var configItem = GetDataSourceItem<ILocationConfiguration>();
    
            if (configItem.Longitude == null && configItem.Latitude == null)
                return PartialView("~/Views/Components/Shared/IncorrectSettings.cshtml");
    
            return PartialView("~/Views/Components/Widget/Index.cshtml", configItem);
        }
    }
    

    (The above sample is using Glass Mapper, I know you are not using it but I would highly recommend it or to use strongly types models in any case. The example still stands though.)

    You can also make some checks in the View itself, although I wouldn't put too much code in there myself. Depending on the component, sometimes we do not show the rendered component in Experience Editor mode. The sample below allows the values to be edited in EE mode but renders the script block and component if values have been set:

    @model Sitecore.Mvc.Presentation.RenderingModel
    
    @if (!Model?.Item?.TemplateID=="guid" ?? true)
    {
        @Html.Raw("<div class=\"error\">Incorrect Datasource</div>")
        return;
    }
    
    @if (Sitecore.Context.PageMode.IsExperienceEditor)
    {
        <!-- This allows component settings to be edited in EE mode -->
        <div>
            Longitude: @Html.Sitecore().Field("lng", Model.Item)
            Latitude: @Html.Sitecore().Field("lat", Model.Item)
            Zoon: @Html.Sitecore().Field("zoom", Model.Item)
        </div>
    }
    else
    {
        string lng = Model.Item["lng"],
               lat = Model.Item["lat"],
               zoom = Model.Item["zoom"];
    
        if (!string.IsNullOrEmpty(lng) && !string.IsNullOrEmpty(lat) && !string.IsNullOrEmpty(zoom))
        {
            <script>
                var options = { lat: @lat, lng: @lng, zoom: @zoom }
            </script>
            <div>
                set up the component in normal mode
            </div>
        }
    }
    

    There are lots of different ways to achieve the above including making checks in the JavaScript itself and how you invoke the code for your component, but I've tried to keep it self-contained and simple for example.