使用 JSON data/object 获取的 Nativescript Core ListView

Nativescript Core ListView using fetch with JSON data/object

我花了一整天的大部分时间浏览这个网站和其他互联网网站,拼凑出一些东西,这对你们这些顶级狗来说可能是显而易见的。我发现没有什么是包罗万象的,而且总体而言,大多数样本都缺少一定程度的清晰度。

所以我想尝试并完成 MVVM 模式,只需从网络服务中获取 JSON 结果并填充列表视图:)

网络服务returns这个

[{"total_bulls":"651","GenericName":"Aripiprazole","brandName":"Abilify","drugCat":"Atypical Antipsychotic","bullID":2793,"fastURL":"http:\/\/got*****.com\/drug-bulletin\/abilify\/","litAlertLvl":"High"},{"total_bulls":"651","GenericName":"Zafirlukast","brandName":"Accolate","drugCat":"Leukotriene Antagonist","bullID":2794,"fastURL":"http:\/\/got****.com\/drug-bulletin\/accolate\/","litAlertLvl":"Withdrawn"},{"total_bulls":"651","GenericName":"Albuterol Sulfate Inhalation Solution","brandName":"AccuNeb","drugCat":"Bronchodilator","bullID":2855,"fastURL":"http:\/\/go***.com\/drug-bulletin\/accuneb\/","litAlertLvl":"Low"},{"total_bulls":"651","GenericName":"Quinapril Hydrochloride","brandName":"Accupril","drugCat":"ACE Inhibitor","bullID":2661,"fastURL":"http:\/\/go****.com\/drug-bulletin\/accupril\/","litAlertLvl":"Low"},{"total_bulls":"651","GenericName":"Quinapril HCl\/Hydrochlorothiazide","brandName":"Accuretic","drugCat":"ACE Inhibitor\/Thiazide Diuretic","bullID":2813,"fastURL":"http:\/\/got****.com\/drug-bulletin\/accuretic\/","litAlertLvl":"High"}]

我希望 ListView 显示正确的数据并触发点击操作。我 运行 遇到的问题是从调用网络服务获取结果以填充列表视图。

我可以像这样手动填充模型:

const viewModel = observableModule.fromObject({

    bulletins: []

    // Setting the listview binding source
    /*
    bulletins: [
        {
            "total_bulls": "651",
            "GenericName": "Aripiprazole",
            "brandName": "Abilify",
            "drugCat": "Atypical Antipsychotic",
            "bullID": 2793,
            "fastURL": "http://g****s.com/drug-bulletin/abilify/",
            "litAlertLvl": "High"
          }, {
            "total_bulls": "651",
            "GenericName": "Zafirlukast",
            "brandName": "Accolate",
            "drugCat": "Leukotriene Antagonist",
            "bullID": 2794,
            "fastURL": "http://g****.com/drug-bulletin/accolate/",
            "litAlertLvl": "Withdrawn"
          }, {
            "total_bulls": "651",
            "GenericName": "Albuterol Sulfate Inhalation Solution",
            "brandName": "AccuNeb",
            "drugCat": "Bronchodilator",
            "bullID": 2855,
            "fastURL": "http://go****.com/drug-bulletin/accuneb/",
            "litAlertLvl": "Low"
          }
    ]
    */

});

然而,尝试使用调用的 JSON 结果来执行此操作被证明具有挑战性。

经过几个小时的反复试验,我找到了这个工作模式。欢迎对此进行改进。

从 Sidekick 或这里 https://market.nativescript.org/plugins/tns-template-drawer-navigation 启动一个 vanilla JS Core Nativescript 'Drawer Navigation' 模板项目并添加这些脚本(我将前 3 个放在名为 "bulletins" 的文件夹中,然后最后一个在名为 "services").

的文件夹中

我还添加了 list-view 插件。

bulletins-page.xml

<Page class="page" navigatingTo="onNavigatingTo" 
    xmlns="http://schemas.nativescript.org/tns.xsd">

    <ActionBar class="action-bar">
        <!-- 
        Use the NavigationButton as a side-drawer button in Android
        because ActionItems are shown on the right side of the ActionBar
        -->
        <NavigationButton ios:visibility="collapsed" icon="res://menu" tap="onDrawerButtonTap"></NavigationButton>
        <!-- 
        Use the ActionItem for IOS with position set to left. Using the
        NavigationButton as a side-drawer button in iOS is not possible,
        because its function is to always navigate back in the application.
        -->
        <ActionItem icon="res://navigation/menu" android:visibility="collapsed" tap="onDrawerButtonTap" ios.position="left">
        </ActionItem>
        <Label class="action-bar-title" text="Bulletins"></Label>
    </ActionBar>

    <GridLayout class="page-content">
        <Label class="page-icon fa" text="&#xf005;"></Label>
        <Label class="page-placeholder" text="<!-- Page content goes here -->"></Label>
    </GridLayout>

    <ScrollView>
        <StackLayout>
            <ListView items="{{ bulletins }}" itemTap="onItemTap" loaded="{{ onListViewLoaded }}" 
            separatorColor="orangered" rowHeight="100" height="500" class="list-group" id="listView" row="2">
                <ListView.itemTemplate> 
                    <!-- The item template can only have a single root view container (e.g. GriLayout, StackLayout, etc.) -->
                    <StackLayout class="list-group-item">
                        <Label text="{{ GenericName || 'Downloading...' }}" textWrap="true" class="title" />
                        <Label text="{{ brandName || 'Downloading...' }}" textWrap="true" class="title" />
                    </StackLayout>
                </ListView.itemTemplate>
            </ListView>>
        </StackLayout>
    </ScrollView>
</Page>

bulletins-page.js

const app = require("tns-core-modules/application");
const BulletinsViewModel = require("./bulletins-view-model");
const listViewModule = require("tns-core-modules/ui/list-view");

function onNavigatingTo(args) {
    const page = args.object;
    //bind the page to this the viewModel Function
    page.bindingContext = new BulletinsViewModel();
    //now call the function that GETS the data from the API AFTER the model is declared
    BulletinsViewModel.showBulletins()
}
exports.onNavigatingTo = onNavigatingTo;

function onListViewLoaded(args) {
    const listView = args.object;
}
exports.onListViewLoaded = onListViewLoaded;

function onItemTap(args) {
    const index = args.index;
    console.log(`Second ListView item tap ${index}`);
}
exports.onItemTap = onItemTap;

function onDrawerButtonTap(args) {
    const sideDrawer = app.getRootView();
    sideDrawer.showDrawer();
}
exports.onDrawerButtonTap = onDrawerButtonTap;

bulletins-view-model.js

const observableModule = require("tns-core-modules/data/observable");
const SelectedPageService = require("../shared/selected-page-service");
const bulletinService = require("~/services/bulletin-service");

function BulletinsViewModel() {
    SelectedPageService.getInstance().updateSelectedPage("Bulletins");

    //declare the viewmodel
    const viewModel = observableModule.fromObject({
        //declare the properties of this viewmodel
        bulletins: []

    });

    //declare a function to be called LATER during the navigation to the view
    BulletinsViewModel.showBulletins = function () {
        //call the fetch function and pass it the users info
        bulletinService.allBulletins({
            user: 'admin',
            password: this.password
        }).then((r) => {
            console.log(r);
            //pass the response to the properties of the model
            viewModel.bulletins = r;
        })
            .catch((e) => {
                console.log(e);
                alert("Unfortunately we could not find any bulletins");
            });
    }

    return viewModel;
}

module.exports = BulletinsViewModel;

bulletin-service.js

exports.allBulletins = function () {
    return new Promise((resolve, reject) => {
        fetch("https://got****.com/wp-admin/admin-ajax.php?action=all-bulletins-paged")
            .then((response) => response.json())
            .then((r) => {
                if (r.total_bulls == 0) {
                    //console.log('No Bulletins Found' + r.total_bulls);
                    reject(r);
                }
                //console.log('JSON Bulletins Found' + JSON.stringify(r));
                resolve(r);
            }).catch((err) => {
                console.log(err);
                reject(err);
            });
    });
};