Dynamic fields on a part

Topics: Writing modules
Sep 13, 2011 at 4:02 PM
Edited Sep 13, 2011 at 4:05 PM

I have the need for a user to enter some information about their education. When the part gets rendered, they click a link that says "add education," and two form fields (school, degree name) dynamically get rendered (via jquery) to the screen. The user can opt to add as many of these as they desire.

Rather than build the two fields from scratch dynamically using the createelement (or whatever the jquery function is, I can't remember off the top of my head), is there a way for me to make an ajax call to pull in some kind of a partial view that I can use as a template for each new education history they add? Preferably it'd be nice to be able to use that same template to render out my items if you leave and later edit the part where it shows items you previously entered in.

I was thinking I could store the fields in a related table called EducationRecord that would have a Id, SchoolName, Degree, and MyPartRecord_Id (a foreign key back to my original part that "contains" these fields)

I'm sure I'm over complicating it, but I wondered if there was an "Orchardy" type way to do this sort of thing.  Perhaps there's a module that does something similar to this I could look at...I'd be interested to see how the posting of these dynamic fields would work under the Orchard Framework.  This has been a question in the back of my mind for some time now, and I knew the day would come for me to have to implement something like this, and now it has.

** I should clarify that by "fields" I don't mean Orchard fields, just fields in general.

Sep 13, 2011 at 8:12 PM

Just a quick update, I ended up building the dynamic fields using something that didn't have anything to do with Orchard (jquery templates: http://api.jquery.com/category/plugins/templates/). 

So now I just need to find out how to pass that information from the view back to the editor method on the driver...

Sep 14, 2011 at 1:08 AM
Edited Sep 14, 2011 at 1:10 AM

 So now I just need to find out how to pass that information from the view back to the editor method on the driver...

Build the name attributes of your elements so they can be picked up by ASP.NET MVC's model binder on post back and use the IUpdater passed to the method to call TryUpdateModel method on a view model.

But from the sound's of it you're editor is on a forward facing page, not in the dashboard. It's my understanding the drivers editor methods are for editing parts in the dashboard.

In that case you'll need a controller to post your data to.

 

I was thinking I could store the fields in a related table called EducationRecord that would have a Id, SchoolName, Degree, and MyPartRecord_Id (a foreign key back to my original part that "contains" these fields)

You actually can do this. You can get IRepository<T> objects injected into your constructors. So if you had say a EducationRecord (deriving from ContentRecord) containing your foreign key you could get a repository injected and CRUD those records.

 

The Comments module would be an all around good place for you to see this kinda thing in action. Except it creates related ContentItems not just records. I have been building a attachment part that can store multiple attachments and that's where I got my best look at how to do it. except my editor is in the dashboard.

Sep 14, 2011 at 1:19 AM

Thanks rev for the response.  I've used dependency injection extensively, so I know how to do that. I think I was just thinking out loud with that statement.

As for the model binder stuff, I had actually found some stuff on that in my internet searches regarding this issue.  It seems like if I have a property on my model called "EducationRecords" I should be able to name my dynamic fields apprpriately EducationRecords[0].SchoolName and Education[0].Degree (incrementing the counter for each field).  I have it setup that way, but I'm not naming something correctly because it's not filling that property on my model appropriately.

I'll give it another go tomorrow after a night's sleep and a new day ahead of me :)

Thanks again for your response.

Sep 14, 2011 at 2:32 AM

For anyone reading along at home: :)

http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx

You may also want to look at knockout . It excels at building bound list editors. (get the 1.3 beta, it has some great new features)

Sep 14, 2011 at 1:30 PM

Since this is orchard, it's taking in a part on the Editor method, and on that part is where my IEnumerable<EducationRecord> EducationRecords {get;set;} property is.  I assume the binder should still be able to spin that up like it would in MVC...a lot of the examples seem to take in the collection on the controller action.  I can't imagine you're locked into that, right? I might have to post my code, but I'm going to take another crack at it first...

Sep 14, 2011 at 1:48 PM

I'm a FIRM believer in walking away and coming back after a good night's sleep.  It was all in my naming convention.  I looked at the post data in FireBug, and I noticed that my other fields were getting set as MyCompany.MyPartName.FirstName.  So, I set my dynamic fields as MyCompany.MyPartName.EducationRecords[index].SchoolName, and it worked.

Very cool...

Sep 14, 2011 at 2:13 PM

I had a feeling that's what your issue was.

Now let me ask you a question, is your editor on a user facing page and your using the drivers editor methods?

If so I didn't know you could do that, do you just post back to the same url?

Sep 14, 2011 at 2:30 PM

Oh yes, I completely forgot to mention that.  No, this is on the back-end in the admin section, so it's using editor methods in the standard way...we'll eventually need to write a search form on the front-end that will search the info entered in the backend, but for now it's strictly back-end stuff.

Another side-note, and again I know this isn't Orchard related, but I might as well post it anyways, I need to allow users to remove items before they post it back, and I'm using the hidden input field method from this page:

http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

I'm not sure why that works, and I wonder if there's a better way to allow for a non sequential set of properties to be found... 

Sep 14, 2011 at 2:40 PM
Edited Sep 14, 2011 at 3:31 PM

Or, so it seems, it doesn't work...I'm probably doing something wrong, but since that post is from 2008, I wonder if that's outdated and there's a better method...

Naming issue again :) It works. Not quite sure why, but I'll live with it for now.