将声明性绑定与API数据一起使用

时间:2015-04-09 17:12:30

标签: javascript jquery google-maps knockout.js wikipedia-api

我正在创建一个工具,在地图上显示附近的兴趣点。单击标记时,地图应显示与该地标相关的WikiPedia文章列表。

我想知道是否有人可以指出我正确的方向,只要让ko.observables使用我的API返回。我想避免将所有内容添加到页面中,就像我现在一样,我也相信这会导致我的信息窗口在点击另一个标记时无法正常关闭时出现问题。

我尝试过的一些事情是将$ wikiData.append更改为observable,然后更改contentString变量以包含数据绑定,但是它没有用完。

我使用的API是WikiPedia API。这是代码:

function mapPin(name, lat, long, text) {

    this.name = ko.observable(name);
    this.lat = ko.observable(lat);
    this.long = ko.observable(long);
    this.text = ko.observable(text);


    var marker = new google.maps.Marker({
        position: new google.maps.LatLng(lat, long),
        map: mapView,
        animation: google.maps.Animation.DROP
    });



    function toggleBounce() {

        if (marker.getAnimation() != null) {
            marker.setAnimation(null);
        } else {
            marker.setAnimation(google.maps.Animation.BOUNCE);
        }
    }

    function article(content, url) {

        var self = this;
        self.content = content;
        self.url = url;

    }


    function apiData() {

        var wikipediaURL = 'http://en.wikipedia.org/w/api.php?action=opensearch&search=' + name + '&format=json&callback=wikiCallback';
        var wikiRequestTimeout = setTimeout(function () {
            $wikiData.text ("Failed to get Wikipedia resources");
        }, 5000);

        $.ajax({

            url: wikipediaURL,
            dataType: "jsonp",

            success: function (response) {

                viewModel.articleList.removeAll();

                var articleList = response[1];

                for (var i = 0; i < articleList.length; i++) {
                    articleStr = articleList[i];
                    var url = 'http://en.wikipedia.org/wiki/' + articleStr;
                    viewModel.articleList.push(new article(articleStr, url));
                }

                clearTimeout(wikiRequestTimeout);
            }
        });

    }

    var contentString = '<!-- ko foreach: articleList --><li><a data-bind="attr: {href: url}, text: content"></a></li>';
    var infowindow = new google.maps.InfoWindow({});

    google.maps.event.addListener(mapView, 'click', function () {
        infowindow.close();
    });

    google.maps.event.addListener(marker, 'click', function () {
        infowindow.close();
        toggleBounce();
        infowindow = new google.maps.InfoWindow({
            content: text + contentString
        });

        infowindow.open(mapView, marker);
        apiData();
    });

}

var mapView = new google.maps.Map(document.getElementById('map-canvas'), {
    zoom: 12,
    center: new google.maps.LatLng(61.196148, -149.885577),
});


var viewModel = {

    articleList: ko.observableArray([]),

    pins: ko.observableArray([
        new mapPin("Alaska Communications", 61.196148, -149.885577, "test11"),
        new mapPin("Moose's Tooth", 61.190491, -149.868937, "test2")
    ]),

    // TODO

    query: ko.observable(''),


    search: function (value) {
        viewModel.pins[0].removeAll();

        for (var i in pins) {
            if (pins[i].name.toLowerCase().indexOf(valkue.toLowerCase()) >= 0) {
                this.pins.push(pins[i])
            }
        }
    }
};


// Initiates the viewModel bindings.

ko.applyBindings(viewModel);

您可以在此处找到该网站的有效版本:

http://jamesiv.es/projects/map

1 个答案:

答案 0 :(得分:1)

您的articleList应该是视图模型中的observableArray,在视图中具有绑定。

var viewModel = {
    articleList: ko.observableArray([]),
    pins: ko.observableArray([
        new mapPin("Alaska Communications", 61.196148, -149.885577, "test11"),
        new mapPin("Moose's Tooth", 61.190491, -149.868937, "test2")
    ]),
};

首先做一点DTO:

function article(content, url) {
  var self = this;
  self.content = content;
  self.url = url;
}

当你从我们的ajax调用中获取数据时,首先要清除数组:

viewModel.articleList.removeAll();

然后循环执行并执行以下操作:

viewModel.articleList.push(new article(articleStr, url));

使用这样的绑定在视图中进行格式化:

<!-- ko foreach: articleList -->
<li><a data-bind="attr: {href: url}, text: content"></a></li>
<!-- /ko -->