I want to use BuildDisplay using a ContentField, is this possible?

Topics: Writing modules
Apr 30, 2012 at 12:49 PM
Edited Apr 30, 2012 at 12:51 PM

Hi,

If I have a part, ExamplePart, with a Html field attached to it via the migrations file

 

            ContentDefinitionManager.AlterPartDefinition("ExamplePart",
                cfg => cfg
                .WithField("ExampleField", field => field.OfType("HtmlField")));

 

How do I within a Filter, or Controller, using ContentManager, build the display shape of this ExampleField and pass it on to my view.

 

            dynamic htmlField = example.ExamplePart.ExampleField;
            var buildDisplayExampleFieldShape = _contentManager.BuildDisplay(htmlField);

I have been trying the above, but it doesnt work as passing the HtmlField ContentField into BuildDisplay doesnt work, so any ideas?

Developer
Apr 30, 2012 at 3:41 PM

This is what I have been trying to do as well. The key thing to understand here is that in order to render a single content field, you need to invoke the field driver for just that field. Invoking IContentManager.BuildDisplay will invoke ALL of the part drivers and field drivers of the specified content item.

So the first step would be to find the drivers for the specified content field type.
Then for each found driver, you invoke its BuildDisplayShape method, which will return a shape.


Apr 30, 2012 at 5:39 PM

Can you give me some example code of the two steps you mention at the end of your post?

Because I know where the content driver for the HtmlField is, but the BuildDisplayShape needs an IContent type, which HtmlField (or ContentFields in general?) do not inherit from. So I do not understand how to use BuildDisplayShape to my advantage and code examples of this would help greatly.

 

Developer
Apr 30, 2012 at 6:16 PM
Edited Apr 30, 2012 at 6:17 PM

Sure, finding the drivers could be done like this:

 private IEnumerable<IContentFieldDriver> FindFieldDrivers(ContentPart contentPart, string fieldName) {
            var fieldTypeName = contentPart.PartDefinition.Fields.Where(x => x.Name == fieldName).Select(x => x.FieldDefinition.Name).FirstOrDefault();
            return from driver in _fieldDrivers
                   let fieldInfos = driver.GetFieldInfo()
                   let fieldInfo = fieldInfos.FirstOrDefault(x =>  x.FieldTypeName == fieldTypeName)
                   where fieldInfo != null
                   select driver;
        }

Notice, however, that this function does not find the individual field driver by field name; instead it finds all the drivers for a specific field type.
That means we need to apply another filter, and that's where I'm stuck at the moment.

I found that I first need to actually invoke the drivers, and then from their DriverResult I can find out what the actual name of the field is. I am still working out the details, so I'm afraid I can't show you the exact code. Your best bet would probably be to step through the debugger.
I have some code here: http://orchardinlineediting.codeplex.com/SourceControl/list/changesets, you may find some clues.