Shape Editor Template on Front End?

Topics: Administration, Customizing Orchard, Writing modules, Writing themes
Developer
Jan 17, 2012 at 10:25 AM

I am writing a personalized section of a website where the loggedin user will be able to update his profile. The profile is stored using a custom CustomerPart. This CustomerPart is attached to a content type called MyProfile, from which I created a content item that is displayed in the front-end

I would like the customer to be able to edit his own information as stored by the CustomerPart.
Currently, I use the driver's Display method to create a shape that renders an edit form. The form is posted to the UpdateProfile action of a CustomerController.

Now I could mark that action with the [Themed] attribute and return a shape that redisplays the CustomerPart; however, all other parts of the MyProfile content item will then not get rendered.
I could also store the current url in a hidden field, and redirect to it. But then I would loose all ModelState Errors (unless I store them in TempData).

So I am looking for a way in which I can somehow integrate into the shape building process of the page and invoke the Update driver method of the CustomerPart when the user hits a "Save Changes" button.

Any pointers into the right direction would be greatly appreciated.

Jan 17, 2012 at 10:36 AM

You can use IContentManager and call the BuildEditor and UpdateEditor methods to build an entire content item editor which is what I think you're after?

Developer
Jan 17, 2012 at 10:40 AM
sfmskywalker wrote:

So I am looking for a way in which I can somehow integrate into the shape building process of the page and invoke the Update driver method of the CustomerPart when the user hits a "Save Changes" button.


Aha, I can easily rebuild the entire shape using IContentManager.BuildDisplay, which works great.

The only problem I am facing now is that the url has changed to that of my controller's action (/MyModule/Profile/Update).
Which causes all the sub menu items to dissapear, since the current menu items is based on the current url, from which the sub menu items are selected.

So ideally, I would be able to post back to the exact same url in which the form is being displayd (e.g. /myprofile/edit), which invokes either my controller's action, or the Update method on the CustomerPart's driver.

Or is there another way?

Developer
Jan 17, 2012 at 10:42 AM
randompete wrote:

You can use IContentManager and call the BuildEditor and UpdateEditor methods to build an entire content item editor which is what I think you're after?

That sounds about right. Question is, once I have built the editor shape, how do I submit the form? Do I create the form element myself? And will Orchard know how to process the posted values if that form is posted back to the current url?

Jan 17, 2012 at 10:53 AM

Look at Orchard.Core\Contents\Controllers\AdminController to see how it's done by default. You need an additional action (called EditPOST in that example) which receives the post and uses UpdateEditor. By defining the routes you should be able to override the urls, or you could use Alias.

Developer
Jan 17, 2012 at 11:11 AM

If I understand correctly, BuildEditor and UpdateEditor call into the drivers of the parts, invoking the corresponding methods, just like BuildDisplay does? Makes sense!
In my particular case I can manage with BuildDisplay just fine. The only missing piece was overriding the route, which I will look into next.

Thanks!

Jan 17, 2012 at 11:43 AM

Yep, which IContentManager method you call will affect whether you get Display() Update() or Editor() functions called on your driver. If you don't call UpdateEditor then you won't get your driver's Update() method, so you can't collect the form values without manually inspecting the post data.

Developer
Jan 17, 2012 at 11:45 AM

Makes perfect sense, thanks!