Getting the Display() functionality from a content type through a widget

Topics: Writing modules
Oct 11, 2011 at 9:48 AM
Edited Oct 11, 2011 at 10:01 AM

Hi guys,

I have a problem,

I created a module which creates a field called LimitLengthTextField, which allows the user to give a maximum length to a text field and have the content of that text field never exceed the maximum length.

I have added this field to a BlogPost.

Here is the code for the Display function within the LimitedLengthTextField driver. It looks for text in the LimitedLengthTextField and displays, if not found, then it looks to the BlogPost for the description text and displays that.

 

        protected override DriverResult Display(ContentPart part, Fields.LimitLengthTextField field, string displayType, dynamic shapeHelper) {
            var settings = field.PartFieldDefinition.Settings.GetModel<LimitLengthTextFieldSettings>();
            var text = field.Text;

            if (String.IsNullOrWhiteSpace(field.Text)) {
                var blogPostPart = part.Get<BlogPostPart>();
                text = blogPostPart.Text.SafeWholeWordString(140);
            }

            var viewModel = new LimitLengthTextFieldViewModel {
                Title = field.Title,
                Text = text,
                Name = field.Name,
                LimitLength = settings.LimitLength
            };

            return ContentShape("Fields_Contrib_LimitLengthTextField", 
                                () => shapeHelper.Fields_Contrib_LimitLengthTextField(
                                          ContentField: field, Model: viewModel));
        }

 

 

At the moment I am in the process of writing a widget which will display a custom summary of a BlogPost's details.

I have added a Content Part called ShowInWidget to a BlogPost, which when set to true, will identify the BlogPost which will be displayed in the widget.

 

In the summary I want to display the LimitedLengthTextField associated with the BlogPost. I want all the functionality defined in the Display() function to be called aswell.

But I can't seem to understand or get my head around how to do this!

All I can do at the moment is pull out the text from the LimitedLengthTextField field defined within the part, as you can see in the widget driver display function below.

 

        protected override DriverResult Display(WidgetPart part, string displayType, dynamic shapeHelper)
        {          
            var viewModel = new WidgetViewModel();

            var article = _contentManager
                .Query(VersionOptions.Published, "BlogPost")
                .Join<ShowInWidgetRecord>()
                .Where(p => p.ShowInWidget)
                .Join<CommonPartRecord>()
                .OrderByDescending(cr => cr.PublishedUtc)
                .List()
                .Select(ci => ci.As<BlogPostPart>())
                .FirstOrDefault();

           
	    var contentPart = article.ContentItem.Parts.Where(x => x.GetType() == typeof(ContentPart)).SingleOrDefault(x => x.Fields.Where(y => y.GetType() == typeof(LimitLengthTextField)).Count() > 0);
            if (contentPart != null)
            {
                var field = contentPart.Fields.SingleOrDefault(x => x.GetType() == typeof(LimitLengthTextField));

                if (field != null)
                {
                    viewModel.Abstract = (LimitLengthTextField)field.Text;                 
                }
            }	

            viewModel.Author = article.Creator.UserName;
            if (article.PublishedUtc.HasValue) {
                viewModel.DatePosted = article.PublishedUtc.Value;
            }
            viewModel.ErrorMessage = string.Empty;
            viewModel.Title = article.Title;
            viewModel.BlogUrl = article.Get<RoutePart>().Path;

            return ContentShape("Parts_Widget", () => shapeHelper.Parts_Widget(Model: viewModel));
        }

 

Then I display it as so.

 

@using Orchard.Utility.Extensions
@{
    var contentTypeClassName = "BlogPost";
    var item = Model.Model;
}

<article class="clearfix content-item @contentTypeClassName ">

    @if (String.IsNullOrWhiteSpace(item.ErrorMessage)) {
        <header>
            <h1><a href="@item.BlogUrl">@item.Title</a></h1>
            <ul class="meta">
                <li>@((item.DatePosted).ToString("dd MMMM yyyy"))</li>
                <li>By @item.Author</li>
            </ul>
        </header>


        @item.Abstract 

    }
    else {
             <header>
                <h1>@item.ErrorMessage</h1>
             </header>
    }
</article>

 

 

 

I feel like I'm structurally going wrong somewhere with my understanding of orchard. I need to somehow display the LimitLengthTextField by calling it's Display() driver function from within the Widget.

So can anyone help?

Coordinator
Oct 11, 2011 at 7:12 PM

What functionality defined in the Display function?

Oct 11, 2011 at 7:41 PM

Specifically this

            if (String.IsNullOrWhiteSpace(field.Text)) {
                var blogPostPart = part.Get<BlogPostPart>();
                text = blogPostPart.Text.SafeWholeWordString(140);
            }

I don't see why I should duplicate this code within the Widget.

Coordinator
Oct 11, 2011 at 7:44 PM

I'm sorry, you lost me there.

Oct 11, 2011 at 8:05 PM

Hmm

My custom field looks for any content within itself and displays it if found. If none is found it looks to the BlogPostPart.Text and displays that. This is the functionality within the Display function.

I have a Widget where I want to display this custom field. But all I can do is retrieve the content of the custom field by doing this..

var contentPart = article.ContentItem.Parts.Where(x => x.GetType() == typeof(ContentPart)).SingleOrDefault(x => x.Fields.Where(y => y.GetType() == typeof(LimitLengthTextField)).Count() > 0);
if (contentPart != null)
{
     var field = contentPart.Fields.SingleOrDefault(x => x.GetType() == typeof(LimitLengthTextField));

     if (field != null)
     {
           viewModel.Abstract = (LimitLengthTextField)field.Text;                 
     }
}	

 

I do not know how to display the custom field from the Widget so it mimics the Display function of the custom field.

 

 

Coordinator
Oct 11, 2011 at 8:16 PM

Well, if you don't know what part it's on, I don't think you have another choice.

Oct 11, 2011 at 8:22 PM

What if I do know which part it is on?

Coordinator
Oct 11, 2011 at 8:31 PM

Then you can do something like dynamic item = article.ContentItem; item.WhateverPartYourFiledIsOn.NameOfTheField

Oct 11, 2011 at 10:58 PM

So then can I say

@Display(item.WhateverPartYourFieldIsOn.NameOfTheField)

to render the field out on the front end ? (which will call the field drivers Display() function?)

Coordinator
Oct 11, 2011 at 11:12 PM

No because Display takes a shape, not a field or a part. You can just render any property of the field directly. You don't need Display for that.