Access view contenttype field from widget?

Topics: General
Apr 26, 2012 at 12:33 AM

Hi All, I have a view displaying a contenttype, which also has a widget on the page in another zone. How can I access some of the contenttype's fields for use in the widget. I have looked at shape tracing and found the value I wish to use at:

@Model.ContentPart.ProjectNumber.Value

But when I try to reference this in the widget, it has its own model, so therefore the above doesn’t exist? So how does one go about this? Thanking you. Pg

Coordinator
Apr 26, 2012 at 12:50 AM

That's not the right way of thinking about it: shapes are just there to dumbly render the data that is handed to them. Any coordination you do should be done before that, in a controller action or driver's display method, or in a handler, etc. Surely what is displayed in that widget is data that would be accessible directly from there.

Apr 26, 2012 at 12:53 AM

I believe the following discussion maybe the key:

http://orchard.codeplex.com/discussions/245971

it talks of a blog by pszmyd that has a solution, so I went to:

http://www.szmyd.com.pl/blog

but can't find it [...it is an old discussion], does anyone have any idea where I could find it - or another solution entirely? Cheers Pg

Apr 26, 2012 at 12:58 AM
Edited Apr 26, 2012 at 1:02 AM

@bertrandleroy, was typing when you replied mate. The widget is basically a PayPal donate button. So what i'm trying to achieve is a way to access the current cause's id so I can know what 'cause' people are donating to.  The contenttype was created through the UI so I have no driver/handler etc.  Any thoughts?

Developer
Apr 26, 2012 at 1:10 AM
Edited Apr 26, 2012 at 1:10 AM

@pubgrub I'm pretty sure it's this one http://szmyd.com.pl/blog/accessing-currently-displayed-content-parts-in-orchard#.T5iOLKt1Dng

Basically, from what I understand you need to get some data from a widget that is displayed on a current page from somewhere outside (other part, widget, driver, etc.). The article itself is about RoutePart (nonexistent in since Orchard 1.4) only, but the idea stays the same. Basically, you need to

  1. Create a service (it's the IPartWatcher in the article) that tracks content items being currently displayed. It's basically a wrapper around a dictionary that just allows you to keep track of the content items displayed.
  2. Create a handler in your module
  3. Use OnDisplaying<WidgetPart> method of the handler above to add the part being displayed to the tracking service.
  4. Use the IPartWatcher service from 1. wherever you want, like any other service. This way you can access the previously registered objects.
Coordinator
Apr 26, 2012 at 1:10 AM

You can have a handler for a content type that was created through the UI.

Apr 26, 2012 at 2:05 AM
Edited Apr 26, 2012 at 2:10 AM

@pszmyd, thanks for your thorough and immediate response […I hope I don’t frustrate you with my novice ability, but here goes].

You basically get what I’m aiming to do, but instead of pulling data from a widget to a part, it’s the other way around. I wish to pull the project number field from my contenttype and utilize it in a PayPal donation widget […so I can send that value to PP]. I believe this doesn’t change your suggested approach, but to amend:

OnGetDisplayShape<WidgetPart>

to

OnGetDisplayShape<Project> //Project is the Part that contains the field.

So,

SERVICE: PartWatcher.cs

 

using System.Collections.Generic;
using System.Linq;
using Orchard;
using Orchard.ContentManagement;

/*
 * CODE BY: Piotr Szmyd [ + PartWatcherHandler.cs]
 http://szmyd.com.pl/blog/accessing-currently-displayed-content-parts-in-orchard#.T5iTEMWZjwl
 * 
 */

namespace PP.Donations.Services
{
    public interface IPartWatcher : IDependency
    {
        void Watch<T>(T part) where T : IContent;
        IEnumerable<T> Get<T>() where T : IContent;
    }

    public class PartWatcher : IPartWatcher
    {
        readonly HashSet<IContent> _parts = new HashSet<IContent>();

        public void Watch<T>(T part) where T : IContent
        {
            _parts.Add(part);
        }

        public IEnumerable<T> Get<T>() where T : IContent
        {
            return _parts.Where(p => p.Is<T>()).Select(p => p.As<T>());
        }

    }
}

 

HANDLER: PartWatcherHandler.cs

 

using PP.Donations.Services;
using JetBrains.Annotations;
using Orchard.ContentManagement.Handlers;

/*
 * CODE BY: Piotr Szmyd [ + PartWatcher.cs]
 http://szmyd.com.pl/blog/accessing-currently-displayed-content-parts-in-orchard#.T5iTEMWZjwl
 * 
 */

namespace PP.Donations.Handlers
{
    [UsedImplicitly]
    public class PartWatcherHandler : ContentHandler
    {
        public PartWatcherHandler(IPartWatcher service)
        {
            OnGetDisplayShape<Project>((ctx, part) => service.Watch(part));
        }
    }
}

 

with this done, I can then use this service from my widget's view? If this is the case, what using directive do I use for 'Project', as I did it through the UI? Thanking you for your clarification, cheers Pg.