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

时间:2019-10-21 17:00:48

标签: javascript typescript nativescript nativescript-plugin

我正在创建一个简单的Nativescript应用,该应用具有基于数组的项目的列表视图。我在掌握Observable模块/ MVVM模式时遇到了麻烦。我正在使用nativescript-drop-down提供一个排序列表,以便对listview中的数据进行排序。在页面首次呈现时,数据已正确排序,但是在更改索引时不会更新。

如何确保下拉列表的“ selectedIndex”值正确传递给viewmodel并相应地更新listview?

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

main-page.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);
        });
    }
}

main-view-model.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>

如果逻辑在视图模型中,则排序在初始页面加载时起作用,但如果选择其他索引,则排序不会改变。另外,如果我尝试通过“ dropDownSelectedIndexChanged”函数更改“ selectedIndex”值,则列表视图不会立即排序,仅在导航并返回主页后才更新。

1 个答案:

答案 0 :(得分:1)

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();
}