mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
feat(ios): ListView showSearch for built-in search behavior
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { Observable, Dialogs, DialogStrings, View, EventData } from '@nativescript/core';
|
||||
|
||||
import { Observable, Dialogs, DialogStrings, View, EventData, SearchEventData } from '@nativescript/core';
|
||||
type CountryListType = Array<{ title: string; items: Array<{ name: string; code: string; flag: string; isVisible?: boolean }> }>;
|
||||
export class ListPageModel extends Observable {
|
||||
components: Array<any> = [
|
||||
countries: CountryListType = [
|
||||
{
|
||||
title: 'A',
|
||||
items: [
|
||||
@@ -1373,9 +1373,10 @@ export class ListPageModel extends Observable {
|
||||
],
|
||||
},
|
||||
];
|
||||
private _originalCountries: CountryListType;
|
||||
|
||||
selectItemTemplate(item: any, index: number, items: Array<any>) {
|
||||
return index == items.length - 1 ? 'last' : 'not-last';
|
||||
return 'main'; // index == items.length - 1 ? 'last' : 'not-last';
|
||||
}
|
||||
|
||||
componentsItemTap(args): void {
|
||||
@@ -1389,4 +1390,40 @@ export class ListPageModel extends Observable {
|
||||
itemLoading(args: EventData): void {
|
||||
(args.object as View).backgroundColor = 'transparent';
|
||||
}
|
||||
|
||||
onSearchTextChange(evt: SearchEventData): void {
|
||||
if (!this._originalCountries) {
|
||||
this._originalCountries = this.countries;
|
||||
}
|
||||
const searchText = evt.text.toLowerCase();
|
||||
console.log('Search text:', searchText);
|
||||
if (searchText) {
|
||||
this.countries = this.filterCountryGroups(this._originalCountries, searchText);
|
||||
} else {
|
||||
this.countries = this._originalCountries; // reset to original if no search text
|
||||
}
|
||||
this.notifyPropertyChange('countries', this.countries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter a grouped array of countries by search query.
|
||||
* @param {Array<{ title: string; items: { name: string; code: string; flag: string; }[] }>} groups
|
||||
* @param {string} query
|
||||
* @returns Filtered groups with the same shape, omitting any with no matches.
|
||||
*/
|
||||
filterCountryGroups(groups: CountryListType, query: string): CountryListType {
|
||||
const q = query.trim().toLowerCase();
|
||||
if (!q) return groups; // no query → all groups
|
||||
|
||||
return (
|
||||
groups
|
||||
.map((group) => {
|
||||
// keep only items whose name includes the query
|
||||
const items = group.items.filter((item) => item.name.toLowerCase().includes(q));
|
||||
return { ...group, items };
|
||||
})
|
||||
// drop any group that ended up with 0 items
|
||||
.filter((group) => group.items.length > 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,13 @@
|
||||
</Page.actionBar>
|
||||
|
||||
<GridLayout backgroundColor="#efefef">
|
||||
<ListView class="list-group" items="{{ components }}" itemTap="{{ componentsItemTap }} " separatorColor="#00000000" itemTemplateSelector="{{ selectItemTemplate }}" stickyHeader="true" sectioned="true" stickyHeaderTopPadding="false" stickyHeaderTemplate="<GridLayout><Label text='{{ title }}' fontSize='18' fontWeight='bold' color='#009bff' padding='2 0 2 12' borderBottomWidth='1' borderBottomColor='#ccc' borderTopWidth='1' borderTopColor='#ccc' backgroundColor='#fff' /></GridLayout>" stickyHeaderHeight="45" itemLoading="{{ itemLoading }}">
|
||||
<ListView class="list-group" items="{{ countries }}" itemTap="{{ componentsItemTap }} " separatorColor="#00000000" itemTemplateSelector="{{ selectItemTemplate }}" stickyHeader="true" sectioned="true" stickyHeaderTopPadding="false" stickyHeaderTemplate="<GridLayout><Label text='{{ title }}' fontSize='18' fontWeight='bold' color='#009bff' padding='8 0 8 12' borderBottomWidth='1' borderBottomColor='#ccc' borderTopWidth='1' borderTopColor='#ccc' backgroundColor='#fff' /></GridLayout>" stickyHeaderHeight="45" itemLoading="{{ itemLoading }}"
|
||||
showSearch="true"
|
||||
searchChange="{{ onSearchTextChange }}">
|
||||
<ListView.itemTemplates>
|
||||
<template key="not-last">
|
||||
<template key="main">
|
||||
<!-- <StackLayout class="list-row-item"> -->
|
||||
<GridLayout columns="auto,auto,*" padding="12" margin="4 6 4 6" borderRadius="4" backgroundColor="#fff">
|
||||
<GridLayout columns="auto,auto,*" padding="14 12 14 12" margin="2 6 2 6" borderRadius="10" backgroundColor="#fff" boxShadow="0px 1px 2px rgba(0,0,0,0.2)">
|
||||
<!-- <FlexboxLayout flexDirection="row" class="list-view-row" verticalAlignment="center"> -->
|
||||
<!-- <visionos>
|
||||
<Label text="{{ iconText }}" class="icon-around icon-label"/>
|
||||
@@ -24,8 +26,8 @@
|
||||
</StackLayout>
|
||||
</android> -->
|
||||
<!-- <StackLayout class="va-middle"> -->
|
||||
<Label class="component-select component-select-fix" text="{{ flag }}" marginLeft="4"></Label>
|
||||
<Label col="1" text="{{ name }}" marginLeft="6"></Label>
|
||||
<Label color="black" text="{{ flag }}" marginLeft="4"></Label>
|
||||
<Label col="1" text="{{ name }}" marginLeft="6" color="black"></Label>
|
||||
<Label col="2" text="{{ code }}" marginLeft="4" color="#999"></Label>
|
||||
<!-- </StackLayout> -->
|
||||
<!-- </FlexboxLayout> -->
|
||||
@@ -34,31 +36,6 @@
|
||||
<!-- <StackLayout class="listview-separator"/> -->
|
||||
<!-- </StackLayout> -->
|
||||
</template>
|
||||
<template key="last">
|
||||
<!-- <StackLayout class="list-row-item"> -->
|
||||
<GridLayout columns="auto,auto,*" padding="12" margin="4 6 4 6" borderRadius="4" backgroundColor="#fff">
|
||||
<!-- <FlexboxLayout flexDirection="row" class="list-view-row" verticalAlignment="center"> -->
|
||||
<!-- <visionos>
|
||||
<Label text="{{ iconText }}" class="icon-around icon-label"/>
|
||||
</visionos>
|
||||
<ios>
|
||||
<Label text="{{ iconText }}" class="icon-around icon-label"/>
|
||||
</ios>
|
||||
<android>
|
||||
<StackLayout class="icon-around">
|
||||
<Label text="{{ iconText }}" class="icon-label"/>
|
||||
</StackLayout>
|
||||
</android> -->
|
||||
<!-- <StackLayout class="va-middle"> -->
|
||||
<Label class="component-select component-select-fix" text="{{ flag }}" marginLeft="4"></Label>
|
||||
<Label col="1" text="{{ name }}" marginLeft="6"></Label>
|
||||
<Label col="2" text="{{ code }}" marginLeft="4" color="#999"></Label>
|
||||
<!-- </StackLayout>
|
||||
</FlexboxLayout> -->
|
||||
|
||||
</GridLayout>
|
||||
<!-- </StackLayout> -->
|
||||
</template>
|
||||
</ListView.itemTemplates>
|
||||
</ListView>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user