0

I am creating a project in Angular 13 version. I have used the Angular Bootstrap library to create a list which is sortable and searchable. I have followed the below link to create the list: https://ng-bootstrap.github.io/#/components/table/examples#sortable The code is below:

Service

interface SearchResult {
    incomeHeadLists: IncomeHeadInfoModel[];
    total: number;
}

interface IncomeHeadListState {
    page: number;
    pageSize: number;
    searchTitle: string;
    searchType: string;
    searchAmount: number;
    searchTotalIncome: number;
    sortColumn: string;
    sortDirection: SortDirection;
}

const compare = (v1: string | number | boolean, v2: string | number | boolean) => v1 < v2 ? -1 : v1 > v2 ? 1 : 0;

function sort(headLists: IncomeHeadInfoModel[], column: string, direction: string): IncomeHeadInfoModel[] {
    if (direction === '' || column === '') {
        return headLists;
    }
    else {
        return [...headLists].sort((a: any, b: any) => {
            const res = compare(a[column], b[column]);
            return direction === 'asc' ? res : -res;
        });
    }
}


@Injectable({
    providedIn: 'root'
})
export class IncomeHeadListInfoService {

    private apiPATH = 'incomeHead/';
    public _search$ = new Subject<void>();
    private _incomeHeadLists$ = new BehaviorSubject<IncomeHeadInfoModel[]>([]);
    private _total$ = new BehaviorSubject<number>(0);

    private _state: IncomeHeadListState = {
        page: 1,
        pageSize: 5,
        searchTitle: '',
        searchType: '',
        searchAmount: null,
        searchTotalIncome: null,
        sortColumn: '',
        sortDirection: ''
    };

    constructor(private service: ApplicationService) {
        this._search$.pipe(
            debounceTime(200),
            switchMap(() => this._search()),
            delay(200)).subscribe(result => {
                this._incomeHeadLists$.next(result.incomeHeadLists);
                this._total$.next(result.total);
            });

        this._search$.next();
    }

    // getter functions
    get incomeHeadLists$() { return this._incomeHeadLists$.asObservable(); }
    get total$() { return this._total$.asObservable(); }
    get page() { return this._state.page; }
    get pageSize() { return this._state.pageSize; }
    get searchTitle() { return this._state.searchTitle; }
    get searchType() { return this._state.searchType; }
    get searchAmount() { return this._state.searchAmount; }
    get searchTotalIncome() { return this._state.searchTotalIncome; }

    // setter functions
    set page(page: number) { this._set({ page }); }
    set pageSize(pageSize: number) { this._set({ pageSize }); }
    set searchTitle(searchTitle: string) { this._set({ searchTitle }); }
    set searchType(searchType: string) { this._set({ searchType }); }
    set searchAmount(searchAmount: number) { this._set({ searchAmount }); }
    set searchTotalIncome(searchTotalIncome: number) { this._set({ searchTotalIncome }); }
    set sortColumn(sortColumn: string) { this._set({ sortColumn }); }
    set sortDirection(sortDirection: SortDirection) { this._set({ sortDirection }); }

    private _set(patch: Partial<IncomeHeadListState>) {
        Object.assign(this._state, patch);
        this._search$.next();
    }

    private _search(): Observable<SearchResult> {
        return this.service.get<IncomeHeadListInfoResultModel>(`${this.apiPATH}lists`).pipe(map(data => {
            const {
                sortColumn,
                sortDirection,
                pageSize,
                page,
                searchTitle,
                searchType,
                searchAmount,
                searchTotalIncome
            } = this._state;

            if (data) {
                let lists = data.IncomeHeads

                // 1. sort              
                let incomeHeadLists = sort(lists, sortColumn, sortDirection);

                // 2. filter
                if (searchTitle) {
                    incomeHeadLists = incomeHeadLists.filter(x => x.Title.toLowerCase().includes(searchTitle.toLowerCase()))
                }

                if (searchType) {
                    incomeHeadLists = incomeHeadLists.filter(x => x.Type.toLowerCase().includes(searchType.toLowerCase()))
                }

                if (searchAmount) {
                    incomeHeadLists = incomeHeadLists.filter(x => x.Amount === searchAmount)
                }

                if (searchTotalIncome) {
                    incomeHeadLists = incomeHeadLists.filter(x => x.TotalIncome === searchTotalIncome)
                }

                const total = incomeHeadLists.length;

                // 3. paginate
                incomeHeadLists = incomeHeadLists.slice((page - 1) * pageSize, (page - 1) * pageSize + pageSize);

                return { incomeHeadLists, total };
            }
            else {
                return null;
            }
        }));
    }
}

HTML Component:

<table class="table table-striped table-bordered">
    <thead>
        <tr>
            <th scope="col">#</th>
            <th scope="col" sortable="Title" (sort)="onSort($event)">Title</th>
            <th scope="col" sortable="Type" (sort)="onSort($event)">Type</th>
            <th scope="col" sortable="Amount" (sort)="onSort($event)">Amount</th>
            <th scope="col" sortable="TotalIncome" (sort)="onSort($event)">Total Bill</th>
            <th scope="col" colspan="2">Action</th>
        </tr>
        <tr>
            <th></th>
            <th><input class="form-control" type="text" name="searchTitle" [(ngModel)]="service.searchTitle" /></th>
            <th><input class="form-control" type="text" name="searchType" [(ngModel)]="service.searchType" /></th>
            <th><input class="form-control" type="text" name="searchAmount" [(ngModel)]="service.searchAmount" /></th>
            <th><input class="form-control" type="text" name="searchTotalIncome" [(ngModel)]="service.searchTotalIncome" /></th>
            <th></th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        <tr *ngFor="let incomeHead of incomeHeadLists$ | async; let i = index">
            <th scope="row">{{((service.page * service.pageSize) + (i + 1))-service.pageSize}}</th>
            <td><ngb-highlight [result]="incomeHead.Title" [term]="service.searchTitle"></ngb-highlight></td>
            <td><ngb-highlight [result]="incomeHead.Type" [term]="service.searchType"></ngb-highlight></td>
            <td><ngb-highlight [result]="incomeHead.Amount | number" [term]="service.searchAmount"></ngb-highlight></td>
            <td><ngb-highlight [result]="incomeHead.TotalIncome | number" [term]="service.searchTotalIncome"></ngb-highlight></td>
            <td>
                <toogle-button [selectedCheckStatus]="incomeHead.IsActive"
                    (onChangeCheckStatus)="activeOrInactiveIncomeHead($event, incomeHead, confirmContent)">
                </toogle-button>
            </td>
            <td>
                <button type="button" class="btn btn-outline-info"
                    (click)="editIncomeHead(incomeHead, incomeHeadModalContent)"><i class="fas fa-edit"></i>
                </button>
            </td>
        </tr>
    </tbody>
</table>

But I got the below errors:

ERROR

src/app/pages/setup/income-head-list/income-head-list.component.html:32:71

  • error TS2322: Type 'number' is not assignable to type 'string | readonly string[]'.

32 <ngb-highlight [result]="incomeHead.Amount | number" [term]="service.searchAmount"> ~~~~

src/app/pages/setup/income-head-list/income-head-list.component.ts:15:15 15 templateUrl: './income-head-list.component.html', ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Error occurs in the template of component IncomeHeadListComponent.

ERROR

src/app/pages/setup/income-head-list/income-head-list.component.html:33:76

  • error TS2322: Type 'number' is not assignable to type 'string | readonly string[]'.

33 <ngb-highlight [result]="incomeHead.TotalIncome | number" [term]="service.searchTotalIncome"> ~~~~

src/app/pages/setup/income-head-list/income-head-list.component.ts:15:15 15 templateUrl: './income-head-list.component.html', ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Error occurs in the template of component IncomeHeadListComponent.

enter image description here

1 Answer 1

2

The problem is in your "ngb-highlight" ((that need two strings). To convert a number to string simply add '' at first of the number. You need make it in the two [term] than mannage number

<td><ngb-highlight [result]="incomeHead.Amount | number" 
                   [term]="''+service.searchAmount">
    </ngb-highlight></td>
<td><ngb-highlight [result]="incomeHead.TotalIncome | number"
                   [term]="''+service.searchTotalIncome">
    </ngb-highlight></td>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.