javascript - 如何通过nativescript-drop-down插件实现listview中数据的按需排序?

标签 javascript typescript nativescript nativescript-plugin

我正在创建一个简单的 Nativescript 应用程序,其中包含基于数组的项目 ListView 。我在掌握 Observable 模块/MVVM 模式时遇到困难。我使用 nativescript-drop-down 提供排序列表,以便对 ListView 中的数据进行排序。页面首次呈现时数据已正确排序,但索引更改时数据不会更新。

如何确保下拉列表的“selectedIndex”值正确传递到 View 模型并相应更新 ListView ?

我尝试根据模型中的 selectedIndex 以及“dropDownSelectedIndexChanged”函数进行排序。

主页.ts

const mainPageModel = new MainPageModel();

export function navigatingTo(args: EventData) {
    const page = <Page>args.object;
    page.bindingContext = mainPageModel;
}

我尝试在主页中设置此功能,但它不会更新列表,除非导航离开然后返回页面:

export function dropDownSelectedIndexChanged(args: SelectedIndexChangedEventData) {
    if (args.newIndex == 0) {
        mainPageModel.dataItems.sort(function (a, b) {
            return a.name.localeCompare(b.name);
        });
    } else if (args.newIndex == 1) {
        mainPageModel.dataItems.sort(function (a, b) {
            return b.name.localeCompare(a.name);
        });
    }
}

主视图模型.ts

export class MainPageModel extends Observable {
    // Dropdown populating
    @ObservableProperty() dropdownItems: ObservableArray<any>;
    @ObservableProperty() selectedIndex: number;

    // Recipe templating
    @ObservableProperty() isBusy: boolean = true;
    @ObservableProperty() dataItems: ObservableArray<any>;

    constructor() {
        super();
        this.isBusy = true;
        this.dataItems = new ObservableArray<any>();

        this.dropdownItems = new ObservableArray<any>();
        this.selectedIndex = 0;

        // Populate sort by dropdown
        const items = ["Name (A-Z)", "Name (Z-A)"];
        this.dropdownItems.push(items);

        // Populate recipes stored locally
        let storedRecipes = [];
        try {
            storedRecipes = appSettings.getAllKeys();
            storedRecipes.forEach(element => {
           this.dataItems.push(JSON.parse(appSettings.getString(element)))
            });
        } catch (e) {
            console.log("No stored recipes")
        }

        // Populate recipes from placeholder data
        getData().then((recipeData) => {
            this.dataItems.push(recipeData);
            this.isBusy = false;

            // Sort recipes by index
            // Done as an alternative to "dropDownSelectedIndexChanged"
            if (this.selectedIndex == 0) {
                this.dataItems.sort(function (a, b) {
                    return a.name.localeCompare(b.name);
                });
            } else if (this.selectedIndex == 1) {
                this.dataItems.sort(function (a, b) {
                    return b.name.localeCompare(a.name);
                });
            }
        });
    }
}

main-page.xml

    <GridLayout columns="*,auto,auto" rows="auto,5*" >
        <!-- Add &#xf2e7; back to button -->
        <Button horizontalAlignment="left" row="0" col="0" text="Add New Recipe" tap="addRecipe" class="add-button" />
        <Label horizontalAlignment="right" verticalAlignment="center" text="Sort by:" col="1" row="0" padding="10" fontWeight="bold" fontSize="18" />
        <dd:DropDown items="{{ dropdownItems }}" selectedIndex="{{ selectedIndex }}" 
                    opened="dropDownOpened" closed="dropDownClosed" 
                    selectedIndexChanged="dropDownSelectedIndexChanged"
                    row="0" col="2" itemsPadding="8" verticalAlignment="center" itemsTextAlignment="center" horizontalAlignment="right" />

        <ListView row="1" colSpan="3" class="list-group" items="{{ dataItems }}" separatorColor="transparent">
            <ListView.itemTemplate>
                <GridLayout recipeData="{{ $value }}" tap="recipeDetail" route="recipe-detail/recipe-detail" rows="*,auto,auto" columns="5*, *" class="list-group-item">
                    <Label row="0" col="0" text="{{ name }}" class="h2" />
                    <Image horizontalAlignment="center" row="0" rowSpan="2" col="2" src="{{ image }}" />
                </GridLayout>
            </ListView.itemTemplate>
        </ListView>
        <ActivityIndicator row="1" colSpan="3" busy="{{ isBusy }}" class="activity-indicator" />
    </GridLayout>

虽然如果逻辑位于 View 模型中,则排序在初始页面加载时起作用,但如果我选择另一个索引,它不会改变。或者,如果我尝试通过“dropDownSelectedIndexChanged”函数更改“selectedIndex”值, ListView 不会立即排序,只会在导航离开并返回主页后更新。

最佳答案

与其他方法(切片、弹出、推送)不同,

sort(...) 方法不会通知组件有关更改的信息。尝试排序后刷新ListView,

export function dropDownSelectedIndexChanged(args: SelectedIndexChangedEventData) {
    if (args.newIndex == 0) {
        mainPageModel.dataItems.sort(function (a, b) {
            return a.name.localeCompare(b.name);
        });
    } else if (args.newIndex == 1) {
        mainPageModel.dataItems.sort(function (a, b) {
            return b.name.localeCompare(a.name);
        });
    }
   (<any>event.object).page.getViewById('YourListViewId').refresh();
}

关于javascript - 如何通过nativescript-drop-down插件实现listview中数据的按需排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58490991/

相关文章:

javascript - Proxy() block 作用域 - Javascript

javascript - Bootstrap 词缀重置不起作用

javascript - vue.js 中设备离线时 Axios 不会失败

javascript - AWS S3 静态站点可以访问 VPC 中的 REST API 吗?

javascript - polymer 开关页面

import - 将 TypeScript 与 Dojo 结合使用 - 导入/导出问题

vue.js - 在 $navigateBack 中传递更改的 Prop

android - NativeScript Android : Command gradlew. bat 失败,退出代码 1

angular - 如何将 FormGroup 对象作为输出从子组件 n Angular 发送到父组件

javascript - ESLint 找不到插件 "eslint-plugin-@typescript-eslint"