2017-06-22 27 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

はい、私は 'api.ajax.get'の外側に' vm.waiting(false) 'を置くと気付きました。 – Vitaliy

+1

@Vitaliy更新された回答を参照してください。 – Tomalak

答えて

2

サブスクリプションによる自動読み込み機能を備えたビューモデルにいくつか変更を加えることをお勧めします。

ロードが成功したかどうかに関係なく、ロード後に常に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]); 
}); 

より厳密に言えば、あなたは私が「ロード」の指標としてtrueまたはfalseに対してアドバイスをしたいです。技術的には複数の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(); 

とあなたのviewmodelで:

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); 
    }); 
}); 
関連する問題