aldair
aldair

Reputation: 3

Mudblazor MudSelect MultiSelection="true" does not initialize selected

I am trying to initialize MudSelect with selected items, to illustrate, I leave an example.

example guide https://mudblazor.com/components/select#multiselect

example not working https://try.mudblazor.com/snippet/QaQwbawCGPETQEEL

the selected is not initialized, I made it short and similar to what is in the documentation but with T="string", my goal is to have it OnInitializedAsync with T="MyClass"

example working https://try.mudblazor.com/snippet/wYwPbGvKRlGThZsa

EntityFramework automatically generates and updates "MyClass", I saw examples where they added functions in "MyClass", but I didn't understand the functionality, is there a way to separate it from "MyClass"?

public override bool Equals(object o) {
   var other = o as MultiSelectItem;
   return other?.Id==Id;
}
public override int GetHashCode() => Id.GetHashCode();

These additions are the ones I don't understand and would like to separate them from the Class or find another way to display the selected ones.

Upvotes: 0

Views: 1207

Answers (1)

Dimitris Maragkos
Dimitris Maragkos

Reputation: 11322

Do not use your entity framework Models directly inside the UI layer, use ViewModels instead. Then use a tool like AutoMapper to map your Models to ViewModels and vice versa.

For example let's say you have a Student entity model:

public class Student
{
    public int ID { get; set; }
    public string LastName { get; set; }
    public string FirstMidName { get; set; }
    public DateTime EnrollmentDate { get; set; }

    public ICollection<Enrollment> Enrollments { get; set; }
}

You want to create a select control to allow the user to select a student. The select control only needs ID, FirstMidName, LastName properties and the methods MudSelect requires. So you could create a new StudentViewModel class which looks like this:

public class StudentViewModel
{
    public int ID { get; set; }
    public string LastName { get; set; }
    public string FirstMidName { get; set; }
    
    public string FullName => $"{FirstMidName} {LastName}";

    // Note: this is important so the MudSelect can compare students
    public override bool Equals(object o)
    {
        var other = o as StudentViewModel;
        return other?.FullName == FullName;
    }

    // Note: this is important too!
    public override int GetHashCode() => FullName?.GetHashCode() ?? 0;

    // Implement this for the StudentViewModel to display correctly in MudSelect
    public override string ToString() => FullName;
}

Now you have this new class that you can use with MudSelect and you haven't polluted your entity model.

<MudSelect T="StudentViewModel" Label="Student" Variant="Variant.Filled" AnchorOrigin="Origin.BottomCenter">
    @foreach (var student in _students)
    {
        <MudSelectItem Value="student" />
    }
</MudSelect>

@code {
    private List<StudentViewModel> _students;
    ...
}

And your ef core query can look like this:

_context.Students
    .Select(x => new StudentViewModel
    {
        ID = x.ID,
        FirstName = x.FirstName,
        FirstMidName = x.FirstMidName
    })
    .ToList();

or if you use AutoMapper:

_context.Students.ProjectTo<StudentViewModel>().ToList()

These queries will only select ID, FirstMidName, and LastName columns so we optimized our data access too.

Upvotes: 1

Related Questions