DEV Community

GoyesDev
GoyesDev

Posted on • Edited on

[SUI] Table

Los iPads y Macs pueden presentar más contenido en la pantalla, así que si se necesita presentar más de una columna, se puede usar el componente Table

  • init(_:selection:sortOrder:columns:): data es la información de la tabla. selection son los identificadores de las filas seleccionadas. sortOrder es un arreglo con los descriptores de orden de tipo SortComparator. columns con las vistas para crear las columnas.
  • init(of:selection:sortOrder:columns:rows:): data son los datos a mostrar. selection es un arreglo con los identificadores de las filas seleccionadas. sortOrder son los descriptores (arreglo) de orden de la tabla. columns son las vistas para crear las columnas. rows vistas para crear las filas.

El contenido se define con los componentes TableColumn y TableRow

  • TableColumn.init(_:value:content:): text es el título de la columna. value es el KeyPath de la propiedad que tiene los valores de la columna. content define la vista a mostrar en la columna.
  • TableRow.init(_:): value es el valor de una fila para cada columna de la tabla.

Por defecto, el ancho de las columnas es determinado por el número de columnas en la tabla y el espacio disponible. Para cambiarlo, se usa:

struct Person: Identifiable {
    let givenName: String
    let familyName: String
    let emailAddress: String
    let id = UUID()

    var fullName: String { givenName + " " + familyName }
}

let people = [
        Person(givenName: "Juan", familyName: "Chavez", emailAddress: "juanchavez@icloud.com"),
        Person(givenName: "Mei", familyName: "Chen", emailAddress: "meichen@icloud.com"),
        Person(givenName: "Tom", familyName: "Clark", emailAddress: "tomclark@icloud.com"),
        Person(givenName: "Gita", familyName: "Kumar", emailAddress: "gitakumar@icloud.com")
    ]

struct ContentView: View {
    var body: some View {
        Table(people) {
            TableColumn("Given Name", value: \.givenName)
            TableColumn("Family Name", value: \.familyName)
            TableColumn("E-Mail Address", value: \.emailAddress)
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Seleccionando filas de una tabla

Se puede seleccionar una fila usando un Binding

struct ContentView: View {
    @State private var selectedPeople = Set<Person.ID>()

    var body: some View {
        Table(people, selection: $selectedPeople) {
            TableColumn("Given Name", value: \.givenName)
            TableColumn("Family Name", value: \.familyName)
            TableColumn("E-Mail Address", value: \.emailAddress)
        }
        Text("\(selectedPeople.count) people selected")
    }
}
Enter fullscreen mode Exit fullscreen mode

Para seleccionar una sola entrada, no hay que hacer nada más. Sin embargo, para seleccionar varias entradas, es necesario tener editMode activado en el ambiente. Para ello, entonces, se va a poner un EditButton:

struct ContentView: View {
    @State private var selectedPeople = Set<Person.ID>()

    var body: some View {
        NavigationStack {
            VStack {
                Text("\(selectedPeople.count) people selected")
                Table(people, selection: $selectedPeople) {
                    TableColumn("Given Name", value: \.givenName)
                    TableColumn("Family Name", value: \.familyName)
                    TableColumn("E-Mail Address", value: \.emailAddress)
                }
            }.toolbar {
                EditButton()
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Tablas con contenido estático

init(of:columns:rows:) permite construir una tabla con celdas estáticas, al especificar el tipo de dato de las filas en valueType, y luego pasando las filas en rows, por medio de instancias de TableRow.

A continuación se muestra cómo pintar la tabla de los ejemplos anteriores de forma estática:

struct ContentView: View {
    var body: some View {
        Table(of: Person.self) {
            TableColumn("Given Name", value: \.givenName)
            TableColumn("Family Name", value: \.familyName)
            TableColumn("E-Mail Address", value: \.emailAddress)
        } rows: {
            TableRow(Person(givenName: "Juan", familyName: "Chavez", emailAddress: "juanchavez@icloud.com"))
            TableRow(Person(givenName: "Mei", familyName: "Chen", emailAddress: "meichen@icloud.com"))
             TableRow(Person(givenName: "Tom", familyName: "Clark", emailAddress: "tomclark@icloud.com"))
              TableRow(Person(givenName: "Gita", familyName: "Kumar", emailAddress: "gitakumar@icloud.com"))
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

En este caso conviene usar el componte ForEach para crear las filas de forma estática:

let people = [
    Person(givenName: "Juan", familyName: "Chavez", emailAddress: "juanchavez@icloud.com"),
    Person(givenName: "Mei", familyName: "Chen", emailAddress: "meichen@icloud.com"),
    Person(givenName: "Tom", familyName: "Clark", emailAddress: "tomclark@icloud.com"),
    Person(givenName: "Gita", familyName: "Kumar", emailAddress: "gitakumar@icloud.com")
]

struct ContentView: View {
    var body: some View {
        Table(of: Person.self) {
            TableColumn("Given Name", value: \.givenName)
            TableColumn("Family Name", value: \.familyName)
            TableColumn("E-Mail Address", value: \.emailAddress)
        } rows: {
            ForEach(people) {
                TableRow($0)
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Ordenar entradas de una tabla

Para hacer que las columnas de una tabla puedan servir como criterio de ordenamiento, se debe proveer un binding a un arreglo de instancias de tipo SortComparator con los keypaths para ordenar.

Cuando un sort descriptor cambia, se deben reordenar los datos manualmente, es decir: esta operación no la hace la tabla. Para ello, la documentación sugiere usar onChange(of:initial:_:) para detectar los cambios.

struct ContentView: View {
    @State private var sortOrder = [KeyPathComparator(\Person.givenName)]

    @State private var people = [
        Person(givenName: "Juan", familyName: "Chavez", emailAddress: "juanchavez@icloud.com"),
        Person(givenName: "Mei", familyName: "Chen", emailAddress: "meichen@icloud.com"),
        Person(givenName: "Tom", familyName: "Clark", emailAddress: "tomclark@icloud.com"),
        Person(givenName: "Gita", familyName: "Kumar", emailAddress: "gitakumar@icloud.com")
    ]


    var body: some View {
        Table(people, sortOrder: $sortOrder) {
            TableColumn("Given Name") { person in
                HStack {
                    Image(systemName: "person")
                    Text(person.givenName)
                }
            }
            .width(120)

            TableColumn("Family Name", value: \.familyName)
                .width(120)

            TableColumn("E-Mail address", value: \.emailAddress)
        }
        .onChange(of: sortOrder) {
            people.sort(using: sortOrder)
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Menú contextual

Top comments (0)