2016-06-01 13 views
2

私が観察可能な配列をフィルタリングしようとしていますが、私はすべての私のモデルのフィールド名を変更ko.utils.arrayFilter方法であると信じて何に起因問題に実行しています小文字。このプロジェクトでTypescriptが使用されていることに注意してください。私はfilterInchesを呼び出すプログラムの別の部分で指定された配列をフィルタリングするための()メソッドをQ.PromiseとKO.mappingは適切な型にオブジェクトの配列を変換しない

inches = ko.observableArray<Models.MyListModel>([]); 

:私は次のフィールドを持っている私のViewModelに

export class MyListModel { 
    constructor(jsObject?: {}) { 
     if (jsObject) { 
      ko.mapping.fromJS(jsObject, {}, this); 
     } 
    } 
    Text = ko.observable<string>(); 
    Value = ko.observable<string>(); 
} 

この

は私のモデルでありますいくつかの基準。 valueパラメーターは、ドロップダウンで現在選択されている値です。

filterInches(value) { 

     if (value == 6) { 
      var filtered = ko.utils.arrayFilter(this.inches(), 
       function (item) { 

        if (parseInt(item.Text()) <= 8) 
         return true; 
       }); 

      this.filteredInches(filtered); 
     } else { 
      this.filteredInches(this.inches()); 
     } 
    } 

エラーはコンパイル時にスローされませんが、私は、ブラウザでアプリケーションを実行するとき、私は「item.Textは関数ではありません」というエラーを取得します。 Chromeのコードをステップ実行すると、項目がテキストフィールドと値フィールドを持つ匿名オブジェクトに変換されたように見えます。フィールドが小文字になっているので、私が問題になっていると思います。この現象の原因は何ですか?

編集: 私はこのコードの別の部分に取り組んでいますが、私はなぜそれが動作していないのか見始めていると思います。私はそれがQ Promiseライブラリと関係があると信じていますが、なぜこのライブラリがうまくいかないのか理解できていません。私は、このコードを書いた開発者は、自分が行っていると思っていることをしていないことに気づいていないと思います。

私は何かが間違っていることを確認するために試してみた最初のことは、我々のモデルのプロパティ名を変更することです:今

export class MyListModel { 
constructor(jsObject?: {}) { 
    if (jsObject) { 
     ko.mapping.fromJS(jsObject, {}, this); 
    } 
} 
    Cat = ko.observable<string>(); 
    Chicken = ko.observable<string>(); 
} 

、我々は戻って改訂filterInches()メソッドは、我々に行けばそのitem.Catはコンパイル時に動作しますが、Chromeのコードをステップ実行すると、実際にはItemオブジェクトにCatというプロパティはありません(定義されていません)。その性質はまだテキストと値です:

filterInches(value) { 

    if (value == 6) { 
     var filtered = ko.utils.arrayFilter(this.inches(), 
      function (item) { 

       if (parseInt(item.Cat()) <= 8) 
        return true; 
      }); 

     this.filteredInches(filtered); 
    } else { 
     this.filteredInches(this.inches()); 
    } 
} 

これは、我々はJSONから取得しているオブジェクトはMyListModelオブジェクトにマッピングされて取得されていないことを私に伝えます。私は、MyListModelクラス自体は問題ないと思う。

私が最初の場所でインチを取得するコードに起因すると思われる問題:

refreshInches() { 
     this.DataService.getInches().done(entities => { 
      this.inches(entities); 
     }); 
    } 

、その後getInches()メソッドは次の通りである:

getInches(): Q.Promise<Array<Models.MyListModel>> { 
     return Q($.getJSON(this._baseUrl + 'GetInches')); 
    } 

私は思いますこのコードの本来の目的は、インチデータをエンドポイントから非同期的に取得し、jsonデータをMyListModelオブジェクトに変換することでした。前述のように、私はQ.Promiseに慣れていないので、getInches()メソッドで何が間違っているのか知ることはできません。ただ、JSONデータから匿名オブジェクトの配列を返すだけであることは明らかです。

エンドポイントから返されるJSONオブジェクトは、次のようになり参考:getInches()メソッドは、行うことになっているものを行うに改善することができる方法を誰もが知っている

[{"text":"0","value":"0"},{"text":"1","value":"1"},...] 

+3

KnockoutJSはオープンソースで、[arrayFilter'ソースコード](https://github.com/knockout/knockout/blob/master/src/utils.js#L149)をチェックしましたが、どんなlowercasingもしないでください。いずれにしても、(完全なコードを含めるか、有益な/可能なコンパイル済みのJavaScriptか、完全なTSコードを使用しないなどで)作成しようとする可能性がある場合は、[mcve]が必要です。 "item.Textが" として定義されている場合 – Jeroen

+1

"のparseInt(item.Text)" はNaNを返し、 "本文= ko.observable ();" – TSV

+2

その行はおそらく 'parseInt(item.Text()、10)'でなければなりません。 – Jeroen

答えて

2

あなたのコードによると、getInchesはQ.Promise<Array<Models.MyListModel>>、すなわちMyListModelオブジェクトの配列の約束を返します。

しかし、現在の形で:

getInches(): Q.Promise<Array<Models.MyListModel>> { 
    return Q($.getJSON(this._baseUrl + 'GetInches')); 
} 

それはそれをしません。上記の結果は、<whatever the server gives you>の約束を返します。この場合は明らかに単純なオブジェクトの配列です。それは仮定の種類と一致するように、我々は

getInches(): Q.Promise<Array<Models.MyListModel>> { 
    var jqXhr = $.getJSON(this._baseUrl + 'GetInches'); 

    return Q(jqXhr).then(data => { 
     return data.map(item => { 
      return new Models.MyListModel(item); 
     }); 
    }); 

    // or, if you must 
    return Q(jqXhr).then(data => data.map(item => new Models.MyListModel(item))); 
} 

を行うことができ、それを変更するには

だから今、私たちは、観察中に新規に作成MyListModelインスタンス保存することができます:this.inchesであることを

refreshInches() { 
    this.DataService.getInches().done(this.inches); 
} 

注意をobservable、observablesは関数であり、コールバックとして直接使用することができます。

約束ハンドラとして使用されている機能は、最初の引数として約束した値を受け取ります。 observableは、あなたがそれを呼び出す最初の引数の値を格納するので、これはうまくいきます。


さらに、filteredInchesアプローチは複雑すぎます。あなたが呼び出す必要のある関数にするのではなく、あなたのビューモデルで観測可能なものに依存する計算にします。このようにして、残りの部分と決して矛盾することはありません。あなたのviewmodelの作成を見てみると

this.filteredInches = ko.pureComputed(() => { 
    var value = this.value(); 

    return ko.utils.arrayFilter(this.inches(), item => { 
     value != 6 || +item.Text() <= 8; 
    }); 
}); 

、あなたはおそらく、数値観察できる(または計算)を持っているしたいと思うどこかに次のように入力し、変換することTextプロパティを計算に覚えて行う必要はありませんように。

+0

ちょっと@Tomalakは非常に詳細な応答をありがとうございました。非常に役に立ちました。私はその道の99%だと思う!私はgetInches()とrefreshInches()にあなたの変更を適用しています.Jsonは私のモデルにマッピングされています。 Cat:observable()、Chicken:observable()、text:observable()、value:observable()、MyModelオブジェクトの配列に次の小道具が設定されています。 'this.inches()[0] .Cat()'は "undefined"を返しますが、this.inches()[0] .text()は必要な値である "0"を返します。 – Bruno

+1

はい、これがマッピングプラグインの仕組みです。追加のオプションがない場合(この場合)、入力オブジェクトのすべてのプロパティをターゲットビューモデル上のオブザーバブルにマップします。入力オブジェクト '{text:" bla "}'はオブジェクト '{text:ko}に変換されます。observable( "bla")} '。あなたのターゲットviewmodelがすでに持っているオブザーバブル( 'Cat')は(名前が一致する場合)移入されるか、放置されます。入力オブジェクトに 'Cat'がないので、ビューモデル内の' Cat'は定義されません。どうやら入力に 'text'がありますが、あなたのviewmodelにマップされるので、これはあなたが見るものです。 – Tomalak

+0

あなたは最高です、ありがとう! – Bruno

関連する問題