Refaktor podobnych funkcji

0

Hej
Mam prostą tabelkę i jej nagłówki kolumn (na razie 3, ale będzie ich 12). Każdy nagłówek ma przycisk do sortowania danych po danej kolumnie.

<tr>
    <div>
        Name
        <button (onclick)="sort('name')">
            <span class="glyphicon glyphicon-sort"></span>
        </button>
    </div>
    <div>
        Surname
        <button (onclick)="sort('surname')">
            <span class="glyphicon glyphicon-sort"></span>
        </button>
    </div>
    <div>
        Company
        <button (onclick)="sort('company')">
            <span class="glyphicon glyphicon-sort"></span>
        </button>
    </div>
</tr>

Funkcje sortowania (komponent angulara, plik .ts):

sort(parameter: string): void {
    if (parameter == 'name') {
        this.employees.sort((a,b) => a.name.localCompare(b.name));
    } else if (parameter == 'surname') {
        this.employees.sort((a,b) => a.surname.localCompare(b.surname));
    } else if (parameter == 'company') {
        this.employees.sort((a,b) => a.company.localCompare(b.company));
    }
}

Wszystko działa, jednak problem jest taki, że tych nagłówków będzie 12 (czyli 12 różnych sortowań). Jeśli będę kontynuował moje podejście, to moja funkcja sort(param) będzie wtedy miała 12 if-elsów. Czy tak wygląda dobrej jakości kod? Alternatywą jest napisać 12 różnych funkcji (sortByName, sortBySurname...) bez parametru i dla każdego buttona podawać inną w (click).

Da się to jakoś ładnie wydzielić/ulepszyć/zrobić profesjonalniej? Jestem raczej początkujący i nie mam pomysłu...

4

w JS możesz się odwoływać po nazwie właściwości w stringu np. zamiast na sztywno dawać a.surname to możesz dać a["surname"] albo:

const foo = "surname";
console.log(a[foo]); // to samo co console.log(a.surname);

ponieważ funkcja przyjmuje stringa parameter to właśnie jego możesz wykorzystać jako nazwę właściwości

sort(parameter: string): void {
   this.employees.sort((a,b) => a[parameter].localCompare(b[parameter));
}

albo z dodatkowym sprawdzaniem czy na pewno parameter jest prawidłową nazwą właściwości, po której chcesz sortować:

sort(parameter: string): void {
   if(!['name', 'surname', 'company', /*tutaj pozostałe typy*/].includes(parameter)) return;
   this.employees.sort((a,b) => a[parameter].localCompare(b[parameter));
}

BTW tam nie powinno być localeCompare zamiast localCompare?
chodzi ci o to:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare
? Swoją drogą nie wiedziałem, że coś takiego istnieje w JS. Jak widać zawsze się można czegoś nauczyć.

3
LukeJL napisał(a):

albo z dodatkowym sprawdzaniem czy na pewno parameter jest prawidłową nazwą właściwości, po której chcesz sortować:

sort(parameter: string): void {
   if(!['name', 'surname', 'company', /*tutaj pozostałe typy*/].includes(parameter)) return;
   this.employees.sort((a,b) => a[parameter].localCompare(b[parameter));
}

Przy odpowiednich typach kompilator sam może sprawdzać, czy wszystko jest w porządku i nie zezwoli na inne właściwości z poza interface Employee

interface Employee {
    name: string;
    city: string;
}

class P4Net {
    employees: Employee[] = [
        { name: 'Michał', city: 'Warszawa' },
        { name: 'Kasia', city: 'Poznań' }
    ]

    sort(parameter: keyof Employee): Employee[] {
        return [...this.employees].sort((a, b) => a[parameter].localeCompare(b[parameter]))
    }
}

const p4net = new P4Net();

p4net.sort('name') // <-- jako argument możemy podać jedynie "name" i "city"

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html

1 użytkowników online, w tym zalogowanych: 0, gości: 1