2010-12-01 4 views
17

knockout.jsの特定のフィールドオブザーバブルを、viewmodelでオブジェクト全体を定義することなくajax呼び出しから取得する方法を知りたいと思います。これは可能ですか?ここで私はこれまで持っているものです。knockout.jsでajaxを取得した後でフィールドを観察できるようにする

var viewModel = { 
    lines: new ko.observableArray([]) 
}; 
function refreshList(ionum) { 
    var data = {}; 
    data['IONum'] = ionum; 
    $.ajax({ 
    url: 'handlers/getlines.ashx', 
    data: data, 
    cache: false, 
    dataType: 'json', 
    success: function(msg) { 

     viewModel.lines(msg); 
     //here is where I am attempting to make the email address field observable 
     /*for (var i = 0; i < msg.length; i++) { 
      viewModel.lines()[i].emailAddress = new ko.observable(msg[i].emailAddress); 

     }*/ 

     //alert(viewModel.lines[0].emailAddress); 
     //ko.applyBindings(viewModel); 


    } 

}); 
} 
+2

+1:あなたが参考になるのCoffeeScriptを掲載思うなぜ私は理解していないノックアウト+ AJAX HOWTO –

答えて

3

私はここにある

for (var i=0;i<msg.lenth;i++){ 
msg[i].emailAddress=ko.observable(msg[i].emailAddress); 
} 
viewModel.lines(msg); 
1

のように、私の意見にそれを設定する前に、私のオブジェクトの観察可能なフィールドを宣言するために優れていたが判明、この問題を修正私CoffeeScriptRequireJS module私はKOのviewmodelsに "ビューデータ"(サーバー由来のJSON値)と呼ぶものに変換する:

define "infrastructure/viewModels", [], (viewModels) -> 
    exports = {} 

    isDate = (x) -> 
     typeof x is "string" and 
     x.startsWith "/Date(" 

    deserializeDate = (dateString) -> 
     new Date(parseInt(dateString.substr(6))) 

    isScalar = (x) -> 
     x is null or 
     typeof x is "string" or 
     typeof x is "number" or 
     typeof x is "boolean" 

    exports.fromViewData = (viewData) -> 
     if isDate viewData 
      return ko.observable deserializeDate viewData 
     if isScalar viewData 
      return ko.observable viewData 

     viewModel = {} 
     for own key, value of viewData 
      if key is "id" then continue 

      viewModel[key] = 
       if Array.isArray value 
        ko.observableArray (exports.fromViewData el for el in value) 
       else 
        exports.fromViewData value 

     return viewModel 

    return exports 

使用例:

もちろん、CoffeeScriptを使用しない場合は、リンクされたサイトで「CoffeeScriptを試してみる」をクリックするとJavaScriptに変換できます。また、RequireJSを使用しない場合、関連する関数をdefineにラップせずにモジュールから取得してください。 Ajax呼び出しから返されたあなたは、プレーンなJavaScriptオブジェクトから自分のビューモデルを定義することができthe mapping plugin for Knockout

+1

? – badsyntax

+0

lol ya、2011年3月にやるべきことでした:P – Domenic

8

var viewModel = ko.mapping.fromJS(data); 
// Every time data is received from the server: 
ko.mapping.updateFromJS(viewModel, data); 

は、私は私のオブジェクトはJavascriptクラスのインスタンスである、ほぼ似たような状況を、持っていました。クラスはKnockoutを意識せずに定義されているので、代わりにObservableを使用するようにクラスを修正したいと考えました。

通常のオブジェクトを観察可能なオブジェクトに変換する小さなヘルパーを作成しました。観測可能なフィールドを指定するか、オブジェクト(プロトタイプ)に設定することができます。 (私はこれを自動的に行うことを考えたが、私は変換しても安全だったフィールドとはなかったかを判断できませんでした。)

(function() { 
    ko.observableObject = function(object, ko_fields) { 
     ko_fields = ko_fields || object._ko_fields; 
     if (!ko_fields) { 
      return object; 
     } 
     for (var f_idx = 0; f_idx < ko_fields.length; f_idx++) { 
      var field_name = ko_fields[f_idx]; 
      if (object[field_name] && object[field_name].__ko_proto__ !== undefined) { 
       continue; 
      } 
      if (object[field_name] instanceof Array) { 
       var field_array = object[field_name]; 
       for (var a_idx = 0; a_idx < field_array.length; a_idx++) { 
        field_array[a_idx] = ko.observableObject(field_array[a_idx]); 
       } 
       object[field_name] = ko.observableArray(field_array); 
      } else { 
       object[field_name] = ko.observable(object[field_name]); 
      } 
     } 

     return object; 
    }; 
})(); 

あなたはクラスとオブジェクトまたはプレーンでそれを使用することができます。偉大な質問の

// With classes. We define the classes without Knockout-observables 
// User.subscriptions is an array of Subscription objects 
User = function(id, name) { 
    this.id = id; 
    this.name = name; 
    this.subscriptions = []; 
}; 

Subscription = function(type, comment) { 
    this.type = type; 
    this.comment = comment; 
}); 

// Create some objects 
var jan = new User(74619, "Jan Fabry"); 
jan.subscriptions.push(new Subscription("Stack Overflow", "The start")); 
jan.subscriptions.push(new Subscription("Wordpress Stack Exchange", "Blog knowledge")); 
var chris = new User(16891, "Chris Westbrook"); 

// We would like to convert fields in our objects to observables 
// Either define the fields directly: 
ko.observableObject(jan, ['id', 'name', 'subscriptions']); 
ko.observableObject(chris, ['id', 'name', 'subscriptions']); 
// This will only convert the User objects, not the embedded subscriptions 
// (since there is no mapping) 

// If you define it in the class prototype, it will work for embedded objects too 
User.prototype._ko_fields = ['id', 'name', 'subscriptions']; 
Subscription.prototype._ko_fields = ['type', 'comment']; 
ko.observableObject(jan); 
ko.observableObject(chris); 

// It also works with objects that are not created from a class, like your Ajax example 
var observable = ko.observableObject({'id': 74619, 'name':'Jan'}, ['id', 'name']); 
関連する問題