TableView row sort not working on non-english characters?

It seems like I’m encountering a bug or something. I have a TableView with sortable columns. If row has only english characters it sorts rows fine, but if row has non-english characters sorting doesn’t work. Maybe it fails because string comparison fails too: Try Haxe! - but how do I make a workaround? Implement a custom sorting method for all TableViews? How do I do that?

Hi! :wave:

Thats interesting about normal haxe not working. You can certainly custom sort tables (or any datasource). For TableView its a little different since there are multiple columns, but you can listen for a SortEvent.SORT_CHANGED event (the target will be the column that was being sorted). Then you can sort that datasource any what you want, the default (internal) sorting looks like this (in tableview):

    private function onSortChanged(e:SortEvent) {
        _tableview.dispatch(e);
        if (e.canceled == false) {
            var column = cast(e.target, Column);
            var field = column.id;
            if (column.sortField != null) {
                field = column.sortField;
            }
            _tableview.dataSource.sort(field, e.direction);
        }
    }

and the “sort” in the datasouce is simply:

    public function sort(field:String = null, direction:SortDirection = null) {
        sortCustom(sortByFn.bind(_, _, _, field), direction);
    }

So for a custom sort, you would linkup the sort event, cancel it in your handler (to stop the default sort) - then apply a myTableView.dataSource.sortCustom(...) to apply your sort.

That said, id be interested in your solution to this, sounds like it might be useful to fix haxeui-core also if the default haxe comparison has issues.

Hope that helps,

Cheers,
Ian

Sorry for delay. Forget what I’ve said about the comparison operator, it seem to work fine and I was halusinating a bit. But anyway, I’ve traced the sortByFn function and the problem is with regexAlpha. You are removing all non [a-zA-Z] characters from the string, so if the f1 string contains only localized characters for example “Привет” the alpha1 variable will be an empty string. So when both of strings contain only localized characters both alpha1 and alpha2 will be empty strings and will be equal, so they will be treated as integers inside the if block. For now I’ve just commented those lines and it worked fine. As far as I understood from the code, you are using this algorithm to properly sort integer fields, knowing that you’ve converted them to strings before. Don’t really know in what way this should be fixed, as I have very little experience with Haxe in general. Here is my temporary fix:

private static var regexAlpha = new EReg("[^a-zA-Z]", "g");
private static var regexNumeric = new EReg("[^0-9]", "g");
private function sortByFn(o1:T, o2:T, direction:SortDirection, field:String):Int {
    var f1:Dynamic = o1;
    var f2:Dynamic = o2;

    if (field != null) {
        f1 = Reflect.field(o1, field);
        f2 = Reflect.field(o2, field);
    }

    if (f1 == null || f2 == null) {
        return 0;
    }

    f1 = Std.string(f1);
    f2 = Std.string(f2);

    if (direction == null) {
        direction = SortDirection.ASCENDING;
    }

    var high = 1;
    var low = -1;
    if (direction == SortDirection.DESCENDING) {
        high = -1;
        low = 1;
    }
    
    // var alpha1 = regexAlpha.replace(f1, "");
    // var alpha2 = regexAlpha.replace(f2, "");
    // if (alpha1 == alpha2) {
    //     var numeric1 = Std.parseInt(regexNumeric.replace(f1, ""));
    //     var numeric2 = Std.parseInt(regexNumeric.replace(f2, ""));
    //     return numeric1 == numeric2 ? 0 : numeric1 > numeric2 ? high : low;
    // }

    //return alpha1 > alpha2 ? high : low;

    return f1 > f2 ? high : low;
}
1 Like