2017-06-22 70 views
0

我有一个下拉按钮,在ajax请求完成后应该可用。当可观察性发生变化时,淘汰赛绑定不会更新

<div class="form-input"> 
    <label class="">Sort by:</label> 
    <select name="orderby" class="selectpicker" data-bind="value: sortBy, optionsCaption: 'Default', disable: waiting"> 
     <option value="some_value">some_option</option> 
     <option value="some_value">some_option</option> 
    </select> 
</div> 

在页面请求,它最初加载数据

$(function() { 
    //Initialization 
    var vm = new ArticleViewModel(); 
    initialLoadArticles(vm); 
    ko.applyBindings(vm, $("#article-plugin")[0]); 
}); 

function ArticleViewModel() { 
    var self = this; 

    //options => 
    this.articles = ko.observableArray([]); 
    this.pageSize = 12; 

    this.sortBy = ko.observable('asc'); 

    this.currentPage = ko.observable(1); 
    this.waiting = ko.observable(true); 
    this.totalPages = 0; 
    this.initMode = true; 
    this.timerId = null; 
    this.viewTemplate = ko.observable('listview-template'); 
    if (this.viewTemplate() === "listview-template") { 
     this.pageSize = 4 
    } else { 
     this.pageSize = 12 
    }; 


    this.sortBy.subscribe(function(event) { 
     console.log(event); 
     self.optionChanged(); 
     loadArticles(self); 
    }); 

    this.optionChanged = function() { 
     this.currentPage(1); 
    } 


    this.setCardView = function() { 
     self.viewTemplate('cardview-template'); 
     loadArticles(self); 
    } 
    this.setListView = function() { 
     self.viewTemplate('listview-template'); 
     loadArticles(self); 
    } 

} 

function initialLoadArticles(vm) { 
    vm.waiting(true); 
    var params = { 
     page: vm.currentPage(), 
     size: vm.pageSize, 
     sortby: vm.sortBy() 
    }; 

    api.ajax.get(api.urls.article.getArticles, params, function(response) { 
     console.log('waiting: ' + vm.waiting()); 
     if (response.success) { 
      vm.articles(response.data.items); 
      vm.waiting(false); 
     } 
    }); 

} 

好了,页面上显示它的所有文章,但下拉按钮仍然受阻,我不究竟是什么可能是这个问题。

+0

你确定'response.success'是'true'吗?另外,我认为'initialLoadArticles'应该在你的视图模型里面。 –

+0

是的,我也注意到,如果我把'vm.waiting(false)'放在'api.ajax.get'之外,它就可以工作。 – Vitaliy

+1

@Vitaliy查看更新的答案。 – Tomalak

回答

2

我建议对您的viewmodel进行一些更改,通过订阅自动加载。

我想你总是想在加载后将waiting设置为false,而不管请求是否成功。还要考虑低级请求错误,您需要为这些错误添加处理程序。

function ArticleViewModel() { 
    var self = this; 

    self.articles = ko.observableArray(); 

    self.pageSize = ko.observable(); 
    self.sortBy = ko.observable('asc'); 
    self.currentPage = ko.observable(); 
    self.waiting = ko.observable(true); 
    self.viewTemplate = ko.observable(); 

    // API 
    self.setCardView = function() { 
     self.viewTemplate('cardview-template'); 
     self.pageSize(12); 
     self.currentPage(1); 
    }; 
    self.setListView = function() { 
     self.viewTemplate('listview-template'); 
     self.pageSize(4); 
     self.currentPage(1); 
    }; 

    // compute Ajax-relevant parameters 
    self.ajaxParams = ko.pureComputed(function() { 
     return { 
      page: self.currentPage(), 
      size: self.pageSize(), 
      sortby: self.sortBy() 
     }; 
    }).extend({ rateLimit: { timeout: 10, method: 'notifyWhenChangesStop' } }); 

    // auto-load when params change 
    self.ajaxParams.subscribe(function (params) { 
     self.waiting(true); 
     api.ajax.get(api.urls.article.getArticles, params, function (response) { 
      if (response.success) { 
       self.articles(response.data.items); 
      } 
      self.waiting(false); 
     }); 
    }); 

    // set inital view (also triggers load) 
    self.setListView(); 
} 

$(function() { 
    var vm = new ArticleViewModel(); 
    ko.applyBindings(vm, $('#article-plugin')[0]); 
}); 

更严格地说,你,我会建议对truefalse为“装入”指示符。技术上可能有多个Ajax请求正在运行,这将是一个竞争条件。第一个返回的请求重置“加载”状态,下一个仍然覆盖视图模型数据。要么使用计数器,要么在有待处理的请求时阻止新的请求。

rateLimit扩展程序确保对参数进行快速连续的更改(如调用setListView()时发生的情况)不会导致多个Ajax请求。


如果你的Ajax请求被jQuery的内部完成,我建议以下设置,以便能够利用donefailalways承诺处理程序:

function ApiWrapper() { 
    var self = this; 

    function unwrapApiResponse(response) { 
     if (response.success) { 
      return new $.Deferred().resolve(response.data).promise(); 
     } else { 
      return new $.Deferred().reject(response.error).promise(); 
     } 
    } 

    self.getArticles = function (params) { 
     return $.get('articleUrl', params).then(unwrapApiResponse); 
    }; 
    // more functions like this 
} 

var api = new ApiWrapper(); 

,并在您的视图模型:

self.ajaxParams.subscribe(function (params) { 
    self.waiting(true); 
    api.getArticles(params).done(function (data) { 
     self.articles(data.items); 
    }).fail(function (err) { 
     // show error 
    }).always(function() { 
     self.waiting(false); 
    }); 
});