Guide or best practice for editing many-many relations?

Hello, just started using Radzen and loving the system so far but I am hitting a stumbling block when it comes to what I would think would be pretty simple functionality.

I know how to create and handle things in a pure code wise environment for a many-many. I have Media, Tag and MediaTag tables set up with the proper relationships. Where I'm stumbling though is handling editing them in a 'pretty' way inside radzen.

How I'm configuring things

  • Basic page with an onload event. Loads media items and sets pendingMedia property
  • DataList referencing pendingMedia as its data source
  • Template for the DataList uses TemplateForm to edit each item
  • Template includes a categories dropdown
  • I want a that dropdown to give a list of all categories and handle adding/removing MediaCategory records when the TemplateFrom is submitted.
  • A 'nice to have' would be the ability to type a new value into the dropdown to create a new Category without having to change pages/use a modal.

Where I'm stuck

So I've got the basic structure in place which based on some reading and sample projects seems like it should be the right direction. The issue is now I'm comparing two different value types (Category and MediaCategory).

My first through was to populate a categoryTypes property on the main page load. This would just be a list of all categories to choose from and use it as the Data source for the drop down. I was hoping to then use the selection event from the dropdown to handle adding/removing MediaCategory entries in code. The stumbling block here was that I still want to have it initially showing what categories already exist when editing existing media. This then lead me to look at how AspNetRoles are handled as it's the same type of relationship.

So I then went back and set up a non mapped field under Medium.Custom.cs: [NotMapped] public IEnumerable CategoryTypes { get; set; }

I also created MediaDbService.Custom.cs and used the OnMediaRead hook to populate the CategoryTypes when media is loaded from the DB.

At this point I can display everything just fine but I'm still stuck at how on earth I am supposed to handle initializing what items in the dropdown are selected as well as updating the database when items are selected. Is this a matter of going back to code and using the Change event to compare current records vs new ones for the create/delete logic?

Basically I can see lots of ways it COULD be done but given the simplicity of how lots of stuff in Radzen works, and given how common a feature I would imagine many-many relationships to be I feel like I must be missing something here... Any guidance or examples would be greatly appreciated!

just to clarify I do see there is many-many crud style options and examples but the complexity from a user standpoint of having multiple datagrids vs a single clean dropdown is what I'm trying to avoid.

OK so I took a step back and had another stab at this. I think I have a better understanding of how Radzen wants things to be done but there seemed to be a lot of caveats while I implemented it and a relatively large amount of backend code required. I suppose I'm just looking for confirmation that I approached this the right way vs using a "I have hammer, everything is a nail" mentality.

My Implementation

Essentially all I needed was a list of all categories and then a non mapped property in my Movies model containing a list of currently applied category names. Little awkward as the data is already there if the designer would let me drill down a few object levels but not a deal breaker by any means!

On page load I either get an individual movie by ID or I pull all movies to use in a data list. I also pull all categories and save as a property.

My dropdown is then configured with...

  • Data: ${categories}
  • Value {movie.CategoryNames}
  • TextProperty: Name
  • ValueProperty: Name

So I jumped into EditMovie.razor.cs and set up a GetMovie and SaveMovie function.

  • GetMovie was because the designer would not let me specify include values for getMovieById and using the database service's OnGetMovie did not pass by ref so I couldn't assign values before the client received the data (still not sure If I did it wrong cause it works fine for OnMoviesRead....)

  • Save movie just takes the returned value but then I must of course do all the add/remove comparisons myself to update database. Not a big deal just still felt like I was missing something. My solution was to query the Categories table to turn my list of category names into a list of 'newCategoryTypes'. I then loop the old vs current and current vs new to add/remove values, run Context.Movies.Update(movie) and Context.SaveChanges() and i'm up and running!

My Stumbling Blocks

So I definitely encountered some inconsistency or confusions.

The biggest being why when using the services partial class I can customize data in OnMoviesRead but there's no similar pass by reference option for OnMovieGet... It was confusing to the point I felt I must be just using the wrong function or missing something obvious. In the perfect world I would just hook the load/update function of the service and handle whatever custom logic is needed.

The whole parameters working fine on a popup but being parsed to string when loading a new page was also something quite frustrating that I felt could have been made more clear in the IDE. It makes perfect sense but a warning, or even a mouseover tooltip when viewing the Page parameters explaining to parse the value would be nice.

They have this page with a sample

I agree it's not ideal for your case but this is what they seem to suggest OOB

Yah it seems like anything besides nested datagrids is not really supported out of the box. Not the end of the world by any means, just a bit frustrating some of the inconsistencies in the boilerplate provided. To me it just means I'll default to writing all my own data logic in my Page.Razor vs relying on any of the data source methods that way I can be confident in how the data will be handled.