ManyToOne-Relation in AutoGrid

Hi everyone :wave:,
let’s say I have two simple Entities called Order and Customer. An Order has exactly one Customer (and a Customer can have 0 or more Orders). The entities are defined like this:

@Entity
@Table(name = "orders")
public class Order {

    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    Long id;

    @NotNull
    private LocalDate created;

    @NotNull
    @ManyToOne(targetEntity = Customer.class, optional = false)
    private Customer customer;

   // Getters and Setters omitted

}
@Entity
@Table(name = "customers")
public class Customer {

    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    Long id;

    @NotBlank
    String name;

    @NotBlank
    @Email
    String mail;

   // Getters and Setters omitted   
}

I would like to use AutoGrid to display all orders. The corresponding OrderService is implemented like this:

@BrowserCallable
@AnonymousAllowed
public class OrderService extends CrudRepositoryService<Order, Long, OrderRepository> {}

If I use AutoGrid like this:

<AutoGrid model={OrderModel} service={OrderService} />

I see the following result:

I would like to configure AutoGrid to display only the name property of the Customer. I tried to set the columnOptions property like this:

<AutoGrid 
    model={OrderModel} 
    service={OrderService}
    columnOptions={{
      customer: {
        path: 'name'
      }
    }} 
/>

Unfortunately the result remains the same:

Another thing I tried, was to use the renderer property like this:

<AutoGrid 
    model={OrderModel} 
    service={OrderService}
    columnOptions={{
      customer: {
        renderer: ({ item }: {item: Customer}) => <span>{item.name}</span>
      }
    }} 
/>

Unfortunately the result looks like this:

How can I configure AutoGrid to display only the name property of the Customer?

I’m using Hilla 24.4.0.alpha21.

Paths and renderers are always based on the root entity, which in your case is Order. So the path would be customer.name, and the renderer would be: ({ item }: {item: Order}) => <span>{item.customer.name}</span>.

Thank you @sissbruecker. Using renderer with ({ item }: {item: Order}) => <span>{item.customer?.name}</span> works as you said:
image

Using path with customer.name seems to work not as intended:
image

1 Like

I was giving it a quick try with columnOptions yesterday which looked something like this:

columnsOptions={{ customer: { path: "customer.name"} }}

Unfortunately, it didn’t work this way in my example. You are welcome to try it out. You can find my example on GitHub: GitHub - rbrki07/hilla-24-4-file-router-demo: Hilla 24.4 File-Router Demo. It’s the file src/main/frontend/views/orders/@index.tsx.

Right, so the default column configuration in AutoGrid for an object property sets a renderer in order to display the JSON representation you’re seeing by default. The problem with that is that a renderer always overrides what you set as path. So if you want to make path work, you explicitly have to remove the renderer:

                columnOptions={{
                    customer: {
                        path: "customer.name",
                        renderer: null,

That’s a bug IMO. If you set a custom path, AutoGrid should automatically remove the default renderer.

Thank you for the additional investigation. Should I create a GitHub issue for that?

Sure, couldn’t hurt.

Here is the issue: AutoGrid uses the default renderer, if a custom path is set. · Issue #2322 · vaadin/hilla · GitHub

If adding a renderer: null feels wrong, a workaround based on the documentation here is to define a custom column with the renderer you want. However, resolving issue #2322 could be a better solution, that leaves the customColumns only for adding more complex columns.

1 Like

Yes, I absolutely agree with you @soroosh.2 and with @anton.platonov.

I just wanted to leave a notice, that I wrote a little blog post about 1:n relationships in Hilla with AutoGrid and AutoForm: https://www.rene-wilby.de/en/blog/one-to-many-relations-with-hilla-autogrid-and-autoform/. The blog post covers some of the aspect discussed here.

2 Likes