filtering - NativeScript - 如何使用 SearchBar 过滤可观察数组?

标签 filtering observablecollection nativescript

您好,我正在尝试过滤通过按下 SearchBar 按键时的 HTTP 请求获取的可观察数据数组。

我设法使 SearchBar 属性更改生效,但我似乎无法弄清楚我在过滤逻辑中做错了什么。

理想情况下,我希望在 SearchBar 中输入搜索词时更新列表。我在 Telerik 网站上搜索了 API,但没有找到任何示例。

XML

<Page loaded="pageLoaded">
    <ActivityIndicator busy="{{ isLoading }}" />
    <ActionBar title="People">
    </ActionBar>
    <GridLayout>
        <StackLayout>
            <SearchBar id="searchBar" hint="Search for someone"></SearchBar>
            <ListView items="{{ peopleList }}" itemTap="showDetail">
                <ListView.itemTemplate>
                    <StackLayout>
                        <Label text="{{ fullName }}" horiztonalAlignment="left" verticalAlignment="center"></Label>
                        <Label text="{{ company }}" class="info"></Label>
                    </StackLayout>
                </ListView.itemTemplate>
            </ListView>
        </StackLayout>
    </GridLayout>
</Page>

JS

var frames = require("ui/frame");
var Observable = require("data/observable").Observable;
var PeopleListViewModel = require("../../shared/people-viewModel");
var activityIndicatorModule = require("ui/activity-indicator");

var page;
var userkey;

var peopleList = new PeopleListViewModel([]);
var pageData = new Observable({ peopleList: peopleList });

exports.pageLoaded = function(args) {
    page = args.object;
    page.bindingContext = pageData;
    userkey = userkey || page.navigationContext.userkey;

    peopleList.load(userkey); // fetch data from the backend

    var searchBar = page.getViewById("searchBar");
    searchBar.on("propertyChange", function (args) {
        var searchText = args.object.text;
        if (searchText === "") {
            // NOT SURE WHAT TO DO HERE.
        } else {
            peopleList.filter(function (element, index, array) {
                // DOESN"T WORK PROPERLY
                console.log("element: ", JSON.stringify(element));
                return element.fullName == searchText;
            });
            console.log("Text types: ", searchText);
        }
    });
};

exports.showDetail = function(args) {
    var person = peopleList.getItem(args.index);
    var navigateEntry = {
        moduleName: "views/people/people-detail",
        context: { person: person },
        animated: false
    };
    frames.topmost().navigate(navigateEntry);
};

PeopleListViewModel.js

var config = require("./config");
var fetchModule = require("fetch");
var ObservableArray = require("data/observable-array").ObservableArray;

function PeopleListViewModel(people) {
    var viewModel = new ObservableArray(people);

    viewModel.load = function (userKey) {

        return fetchModule.fetch(config.baseUrl + "/api/people/all/" + userKey)
            .then(function (response) {
                return response.json();
            })
            .then(function (data) {
                data.forEach(function (person) {
                    viewModel.push(person);
                });
            }, function (error) {
                console.log("Error: ", error);
            });
    };

    viewModel.empty = function () {
        while (viewModel.length) {
            viewModel.pop();
        }
    };

    return viewModel;
}

function handleErrors(response) {
    if (!response.ok) {
        console.log("Error occurred");
    }
}

module.exports = PeopleListViewModel;

更新人员列表

var frames = require("ui/frame");
var Observable = require("data/observable").Observable;
var ObservableArray = require("data/observable-array").ObservableArray;
var PeopleListViewModel = require("../../shared/people-viewModel");
var activityIndicatorModule = require("ui/activity-indicator");

var page;
var userkey;

var peopleList = new PeopleListViewModel([]);
var pageData = new Observable({ peopleList: peopleList });
var resultList = new ObservableArray([]);

exports.pageLoaded = function(args) {
    page = args.object;
    page.bindingContext = pageData;
    userkey = userkey || page.navigationContext.userkey;

    peopleList.load(userkey);

    var searchBar = page.getViewById("searchBar");
    searchBar.on("propertyChange", function (args) {
        var searchText = args.object.text;

        if (searchText === "") {

        } else {

            while (resultList.length > 0) {
                resultList.pop();
            }   

            peopleList.forEach(function (element) {
                if (element.fullName === searchText) {
                    resultList.push(element);
                }
            });
        }   
    });

};

最佳答案

我也遇到了同样的问题。如果您想在搜索栏中的每个字符更改后过滤数据,您可以尝试我的解决方案。

定义 我的玩家列表是你的人员列表。这是来自 View 模型的数据。 resultList 是一个数组,数据将被推送到其中。

var observableArrayModule = require("data/observable-array").ObservableArray;
var playerList = new PlayerListViewModel([]);
var resultList = new observableArrayModule([]);

var pageData = new observableModule.Observable({
  resultList: resultList,
  player: ""
});

expors.loaded()内部

  page = args.object;
  searchBar = page.getViewById("search-bar");
  page.bindingContext = pageData;

加载初始数据 - 在 expors.loaded() 内

当用户第一次导航到屏幕时,我们正在加载初始数据。由于我们在 xml 中使用 {{resultList}},因此我们还将相同的数据推送到 resultList。您可以在填充列表时添加loadingIndicator。

playerList
.load()
.then(function() {
  setTimeout(function() {
    playerList.forEach(function (element) {
      pageData.resultList.push(element);
    });
  }, 1000);
})
.catch(function(error) {
  dialogsModule.alert({
    message: "An error occurred while loading players.",
    okButtonText: "OK"
  });
});

清除自动对焦 - 在 expors.loaded() 内

这是为了防止键盘在初始屏幕导航时打开。

  if (searchBar.ios) {
    searchBar.ios.endEditing(true);
  } else if (searchBar.android) {
      searchBar.android.clearFocus();
  }

字符更改时搜索数据 - 在 expors.loaded() 内

我正在调用过滤器功能。 Lodash _.debounce 函数用于延迟 resultList 数组的循环。如果没有它,每次输入字母时应用程序都会循环。现在我们正在等待用户停止输入以开始循环。

searchBar.on('propertyChange', _.debounce(searchList, 500));

搜索列表函数

这是实际的循环。您可以根据需要更改 element.name。

function searchList(args) {
  var searchText = args.object.text;
  while(resultList.length > 0) {
    resultList.pop();
  }
  playerList.forEach(function (element) {
    if (element.name.toLowerCase().indexOf(searchText) >= 0) {
      resultList.push(element);
    }
  });
}

如果搜索栏被清除则隐藏键盘 - 在exports.loaded()内

最后,如果用户清除搜索栏,我们希望隐藏键盘。

searchBar.on(searchBarModule.SearchBar.clearEvent, function (args) {
  setTimeout(function() {
    searchBar.dismissSoftInput();
  }, 10);
});

附注

您可能解决了您的问题,但这可能会在将来帮助其他人。

关于filtering - NativeScript - 如何使用 SearchBar 过滤可观察数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36005172/

相关文章:

java和nlp提取信息(恶意软件名称)和过滤

javascript - 如何使用多个选择按钮显示和隐藏行

c# - 保持 ObservableCollection 和 ObjectContext 同步的最佳方法?

c# - WPF ObservableCollection : How to add a blank line in one form's combobox, 但实际上不影响ObservableCollection?

c# 当达到收集容量或发生超时时触发事件

ios - 如何允许应用程序在 ios 上访问互联网?

nativescript - 如何隐藏布局和包含的 View

audio - 我可以使用 DirectSound 轻松地进行频带过滤吗?如果没有,我该怎么做?

conditional - 过滤器中的 taskwarrior 条件

google-login - Nativescript Google 登录插件