Sorting adds reordering abilities to GORM models and sorts collections.
Sorting utilises GORM callbacks to log data, so you will need to register callbacks first:
import (
"github.com/jinzhu/gorm"
"github.com/qor/sorting"
)
func main() {
db, err := gorm.Open("sqlite3", "demo_db")
sorting.RegisterCallbacks(db)
}
Sorting two modes which can be applied as anonymous fields in a model.
- Ascending mode:smallest first (
sorting.Sorting
) - Descending mode: smallest last (
sorting.SortingDESC
)
They can be used as follows:
// Ascending mode
type Category struct {
gorm.Model
sorting.Sorting // this will register a `position` column to model Category, used to save record's order
}
db.Find(&categories)
// SELECT * FROM categories ORDER BY position;
// Descending mode
type Product struct {
gorm.Model
sorting.SortingDESC // this will register a `position` column to model Product, used to save record's order
}
db.Find(&products)
// SELECT * FROM products ORDER BY position DESC;
// Move Up
sorting.MoveUp(&db, &product, 1)
// If a record is in positon 5, it will be brought to 4
// Move Down
sorting.MoveDown(&db, &product, 1)
// If a record is in positon 5, it will be brought to 6
// Move To
sorting.MoveTo(&db, &product, 1)
// If a record is in positon 5, it will be brought to 1
Sorts a slice of data:
sorter := sorting.SortableCollection{
PrimaryKeys: []string{"5", "3", "1", "2"}
}
products := []Product{
{Model: gorm.Model{ID: 1}, Code: "1"},
{Model: gorm.Model{ID: 2}, Code: "2"},
{Model: gorm.Model{ID: 3}, Code: "3"},
{Model: gorm.Model{ID: 3}, Code: "4"},
{Model: gorm.Model{ID: 3}, Code: "5"},
}
sorter.Sort(products)
products // => []Product{
// {Model: gorm.Model{ID: 3}, Code: "5"},
// {Model: gorm.Model{ID: 3}, Code: "3"},
// {Model: gorm.Model{ID: 1}, Code: "1"},
// {Model: gorm.Model{ID: 2}, Code: "2"},
// {Model: gorm.Model{ID: 3}, Code: "4"},
// }
After enabling sorting modes for GORM models, QOR Admin will automatically enable the sorting feature for the resource.
If you want to make a sortable select_many, collection_edit field, You could add a sorting.SortableCollection
field with name: Field's name + 'Sorter'; which is used to save above field's data order. That Field will also be identified as sortable in QOR Admin.
// For model relations
type Product struct {
gorm.Model
l10n.Locale
Collections []Collection
CollectionsSorter sorting.SortableCollection
ColorVariations []ColorVariation `l10n:"sync"`
ColorVariationsSorter sorting.SortableCollection
}
// For virtual arguments
type selectedProductsArgument struct {
Products []string
ProductsSorter sorting.SortableCollection
}
selectedProductsResource := Admin.NewResource(&selectedProductsArgument{})
selectedProductsResource.Meta(&admin.Meta{Name: "Products", Type: "select_many", Collection: func(value interface{}, context *qor.Context) [][]string {
var collectionValues [][]string
var products []*models.Product
db.DB.Find(&products)
for _, product := range products {
collectionValues = append(collectionValues, []string{fmt.Sprint(product.ID), product.Name})
}
return collectionValues
}})
Widgets.RegisterWidget(&widget.Widget{
Name: "Products",
Templates: []string{"products"},
Setting: selectedProductsResource,
}
It do support sorting records with composite primary key. However there is a exception, the version_name
is a "reserved" primary key for the qor/publish2 support. So DO NOT use version_name
as a part of the composite primary key unless you are using qor/publish2.
Released under the MIT License.