javascript - 无法处理绑定(bind),国家/地区未定义

标签 javascript knockout.js typescript

我正在尝试绑定(bind) <select>到 ko.observableArray ,我收到此错误:

Uncaught ReferenceError: Unable to process binding "options: function (){return _countries }" Message: country is not defined

这是我的代码。

HTML:

<!-- This is the home page -->

<html>

<head>
    <title>The Vegan Repository</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- Load libraries -->



    <!-- System.js -->
    <script 
        src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.18.4/system-csp-production.js">
    </script>

    <!-- JQuery -->
    <script 
        src="bower_components/jquery/dist/jquery.min.js">
    </script>

    <!-- Bootstrap CSS -->
    <link 
        rel="stylesheet" 
        href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" 
        integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7"
        crossorigin="anonymous">

    <!-- Bootstrap JS -->
    <script 
        src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" 
        integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS"
        crossorigin="anonymous">
    </script>

    <!-- Knockout JS -->
    <script 
        src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js">
    </script>

    <!-- Styles -->
    <link rel="stylesheet" type="text/css" href="styles/image.css">
    <link rel="stylesheet" type="text/css" href="styles/text.css">
    <link rel="stylesheet" type="text/css" href="styles/header.css">
    <link rel="stylesheet" type="text/css" href="styles/form.css">
    <link rel="stylesheet" type="text/css" href="styles/select.css">

    <!-- Google Maps API -->
    <!-- <script src="http://maps.googleapis.com/maps/api/js"></script>
    <script src="scripts/map.js"></script> -->
    <script src="scripts/scroll_to_anchor.js"></script>
    <script src="scripts/xml2json.min.js"></script>
    <script src="scripts/country.js"></script>

</head>
<body >
    <div style="margin-bottom: 100px;" class="full_size dimmed">
        <div style="position:fixed; z-index: -1;">
        <video 
            style="position:fixed;" 
            autoplay loop muted
            poster="assets/images/home_page/polina.jpg" 
            id="bgvid">
            <!--<source src="polina.webm" type="video/webm">-->
            <source src="assets/videos/polina.mp4" type="video/mp4">
        </video>
        </div>

        <div class="header dim">
            <a href="http://www.w3schools.com" ><h5 id="app-name" class="nav-item clickable white-text medium-text left-text">THE VEGAN REPOSITORY</h5></a>
            <a href="http://www.w3schools.com" ><h5 (click)="clicked()" id="sign-in-button" class="nav-item clickable brand-colour-text medium-text right-text with-border">SIGN UP FREE</h5></a>
            <a href="http://www.w3schools.com" ><h5 class="nav-item clickable white-text medium-text right-text">LOGIN</h5></a>
            <a href="#home_page_footer" ><h5 class="nav-item clickable white-text medium-text right-text" >BLOG</h5></a>
            <a href="#home_page_footer" ><h5 class="nav-item clickable white-text medium-text right-text" >ABOUT</h5></a>

        </div>

        <div id="motto-text" class="vertical-center">
            <h5 class="white-text medium-text">THE VEGAN REPOSITORY</h5>
            <h1 id="main-text" class=" text-center white-text light-text extra-large-text">FIND VEGAN PRODUCTS NEAR YOU</h1>
            <a id="try-now-button" class="with-border clickable" href="#find-vegan-products-page" ><h5  class=" text-center medium-text">TRY NOW</h5></a>
        </div>
    </div>
    <!--[if lt IE 9]>
    <script>
        document.createElement('video');
    </script>
    <![endif]-->

    <?php
        $host = 'localhost';
        $port = 8889;
        $servername = "$host:$port";
        $username = "root";
        $password = "root";
        $db = "myDB";

        // Create connection
        $conn = new mysqli($servername, $username, $password, $db);
        // Check connection
        if ($conn->connect_error) {
            die("Connection failed: " . $conn->connect_error);
        } 

        // Create database
        /*$sql = "CREATE DATABASE myDB";*/

        // Create table
        /*$sql = "CREATE TABLE Persons
                (   PersonID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
                    LastName varchar(255),
                    FirstName varchar(255),
                    Address varchar(255),
                    City varchar(255)
                );";*/

        // Insert row into table
        $sql = "INSERT INTO Persons (Firstname, Lastname, Address, City)
                VALUES  ('John', 'Doe', '44 Vulcan Lane', 'Auckland'),
                        ('Jane', 'Doe', '44 Vulcan Lane', 'Auckland'),
                        ('Becky', 'Smith', '5 Freemans Lane', 'Kaitaia'),
                        ('Chris', 'Johnson', '18 Snow Drive', 'Christchurch');
                ";

        // Delete all rows
        /*$sql = "DELETE FROM Persons";*/


        /*if ($conn->query($sql) === TRUE) {
            echo "Database created successfully";
        } else {
            echo "Error creating database: " . $conn->error;
        }*/

        $conn->close();
    ?>

    <!-- <div id="googleMap" style="height:500px;"></div> -->

    <div id="find-vegan-products-page" style="height:900px;">
        <div class="form-background">
        <div class="container-fluid" style="padding: 40px;">
            <h1>Filter Your Search!</h1>
            <form role="form">
            <div class="row">
                <div class="form-group col-sm-6">
                   <!-- <select id="country-select" class="form-control input-control"></select>-->
                    <div class="select">
                        <span class="arr"></span>
                        <select data-bind=" options: _countries,
                                            optionsText: country.countryName,
                                            value: country.geonameId,
                                            optionsCaption: 'Choose...'">
                        </select>
                    </div>
                </div>
                <div class="form-group col-sm-6">
                    <div class="select">
                        <span class="arr"></span>
                        <select id="city-select">
                        </select>
                    </div>
                </div>
            </div>


            </form>
         </div>


</div>

        </div>
    </div>
</body>
</html>

typescript :

class HomeViewModel {
    _countries = ko.observableArray();
    _cities = ko.observableArray();

    constructor(allCountries) {
        for (var index = 0; index < allCountries.length; index++) {
            this._countries.push(allCountries[index]);
        }
    }
}

var _homeViewModel: HomeViewModel;

$(document).ready(function() {
    $("#city-select").append('<option selected>Any Region</option>');
    $.ajax({
        url: "http://api.geonames.org/countryInfo?username=elion"
    }).then(function(allCountriesXML) {
        var allCountriesJSON = xml2json(allCountriesXML);
        var allCountries = JSON.parse(allCountriesJSON);
        _homeViewModel = new HomeViewModel(allCountries.geonames);
        ko.applyBindings(_homeViewModel);
    }
);

这是 allCountries 的值(从控制台复制粘贴的一个小样本):

[0 … 99]
0: Object
country: Object
areaInSqKm: "468.0"
capital: "Andorra la Vella"
continent: "EU"
continentName: "Europe"
countryCode: "AD"
countryName: "Andorra"
currencyCode: "EUR"
east: "1.786..."

如果我将 html 更改为:

<select data-bind=" options: _countries">
                        </select>

它可以工作,但是 <select>在选择框中显示[对象][对象]。

如果我将 viewModel 的构造函数更改为:

constructor(allCountries) {
        for (var index = 0; index < allCountries.length; index++) {
            this._countries.push(allCountries[index].country.countryName);
        }
    }

并保持 html 如下:

<select data-bind=" options: _countries">
                        </select>

它有效,但我在 <select> 中没有任何值(value)因为我已经摆脱了 javascript 对象数组并使其成为字符串数组。

如何将 javascript 对象数组绑定(bind)到 <select>没有提示 _countries 未定义?发生这种情况是因为我在文档准备好后插入 _countries 数组,并且在 html 中我在加载文档之前绑定(bind) ko.observableArray 吗?如果是这样,我确实尝试用一个值初始化 ko.observableArray 但它没有解决问题。

最佳答案

使用 Rohith 的答案。进一步详细说明,导致错误的不是 _countries,而是这些 optionsText:country.countryName, value:country.geonameId,您的 View 模型不知道任何国家/地区,这些值都驻留在 _countries 可观察数组中。并且您错误地使用了 options 数据绑定(bind)参数。

检查docs有关此绑定(bind)的更多详细信息。

为了满足您的需要,首先您使用了 optionsText,该值应该是 'countryName'。然后对于value,这将是保存所选选项的可观察值。因此,在您的 View 模型中,您需要添加诸如 countryselectedCountry 或任何您喜欢的名称。

要将其写入代码,您的更改将如下所示。 更改 View 模型:

class HomeViewModel {
    _countries = ko.observableArray();
    _cities = ko.observableArray();
    selectedCountry = ko.observable();

    constructor(allCountries) {
        for (var index = 0; index < allCountries.length; index++) {
            this._countries.push(allCountries[index]);
        }
    }
}

然后在你的 html 数据绑定(bind)中它会是这样的。

<div class="select">
    <span class="arr"></span>
    <select data-bind="options: _countries,
                       optionsText: 'countryName',
                       value: selectedCountry,
                       optionsCaption: 'Choose...'">
    </select>
</div>

关于javascript - 无法处理绑定(bind),国家/地区未定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35220940/

相关文章:

javascript - yii2 PJAX 如何在 pjax 重新加载后显示模态?

javascript - 在 knockout.js 中为 applyBindings 实例化 View 模型时绑定(bind)中断

javascript - 为什么即使按下取消,onclick 事件仍然会转到 url?

在 .d.ts 文件中时无法识别 TypeScript 接口(interface)

javascript - xmlHttpRequest 不关闭连接

javascript - React - 如何将值传递给组件中的过滤函数?

javascript - 开发用于替换文本的 vscode 扩展

javascript - 让 Webpack 不捆绑文件

javascript - 数据表 AJAX 从连接表中获取字段

javascript - 编辑不适用于新添加的数据 - knockout