2013-12-09 94 views
3

如何使用KnockoutJS創建函數,我可以調用它來對視圖模型進行一些操作?使用knockoutjs操作視圖模型

型號:

public class ViewModel 
{ 
    public int User { get; set; } 
    public string Address { get; set; } 
    public string ZipCode { get; set; } 
    public List<Product> Products { get; set; } 

} 

public class Product 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

的Javascript:

<script type="text/javascript"> 
     var Product = function (Id, Name) { 
      self = this; 
      self.Id = Id; 
      self.Name = Name; 
     } 

     function Add() { 
      viewModel.products.push(new Product(2, "bread")); 
     } 

     function Remove(product) { 
      viewModel.products.remove(product); 
     } 

     var viewModel = ko.mapping.fromJS(@Html.Raw(Json.Encode(Model))); 
     viewModel.products = ko.observableArray(); 

     ko.applyBindings(viewModel); 

     Add(); 
     console.log(viewModel.products().length); 

     var t = new Product(2, "bread"); 

     Remove(t); 
     console.log(viewModel.products().length); 
</script> 

這裏添加這樣的作品,但function Remove(product)不從array取出產品。我沒有得到錯誤,console只打印出1(在viewModel.products().length調用中)。

那麼,如何爲KnockoutJS創建適當的功能,以便能夠在頁面上的任何位置調用它們?

回答

3

我看不出任何明顯的代碼,它不是像你的模型中返回的對象,你的刪除實際上正在工作,但剩下的對象是從模型返回的對象?

我更喜歡當他們讀從模型回對象映射,以避免這樣創建的匿名對象:

var mapping = { 
    'Products': { 
     create: function(options) { 
      return new Product(options.data.Id, options.data.Name); 
     } 
    } 
} 

這可以確保你的產品是實際的產品對象。

你也可以檢查JSON從你的模型返回的是這樣的:

{ "User": "a", "Address": "b", "ZipCode": "zip", "Products":[{"Id":1,"Name":"jam"}]}; 

以下是完整的代碼中的jsfiddle工作(檢查輸出控制檯):

http://jsfiddle.net/6qsjz/15/

這顯示,從模型返回的一個,然後刪除一個,集合中的一個產品。

更新

您可以通過改變模型的這個初始化集合服務器端:

public class ViewModel 
{ 
    public ViewModel() 
    { 
     Products = new List<Product>(); 
    } 
    public int User { get; set; } 
    public string Address { get; set; } 
    public string ZipCode { get; set; } 
    public List<Product> Products { get; set; } 

} 

這意味着,如果你把上面的方法,你將不需要做viewModel.products = ko.observableArray();

更新

然後,您可以重構它,使其給它更好的結構(多模):

var Product = function (Id, Name) { 
     self = this; 
     self.Id = Id; 
     self.Name = Name; 
    } 

    var mapping = { 
     'Products': { 
      create: function(options) { 
       return new Product(options.data.Id, options.data.Name); 
      } 
     } 
    } 


function ProductsViewModel(data) { 
    var self = this; 
    ko.mapping.fromJS(data, mapping, self); 

    self.Add = function Add(product) { 
     self.Products.push(product); 
    } 

    self.Remove = function Remove(product) { 
     self.Products.remove(product); 
    } 
} 


var data = { "User": "a", "Address": "b", "ZipCode": "zip", "Products":[{"Id":1,"Name":"jam"}]}; 

    var viewModel = new ProductsViewModel(data); 
    ko.applyBindings(viewModel); 

    // add 
    var product = new Product(2, "bread"); 
    viewModel.Add(product); 
    console.log(viewModel.Products()); 

    // remove 
    viewModel.Remove(product); 
    console.log(viewModel.Products()); 

更新小提琴(再次查看輸出控制檯):

http://jsfiddle.net/6qsjz/16/

+0

嗨,如果我不使用'viewModel.products = ko.observableArray();'當使用'var mapping = ....時,我得到一個關於'push'不是'viewModel'的方法的錯誤。 '。另外,產品在'viewModel.Products'中是未定義的。 – Quoter

+0

嗨,你看過工作小提琴嗎?你是否包括映射庫:http://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js – hutchonoid

+0

我也會檢查我用來對付你的淘汰賽版本。你可以拿小提琴的代碼並按原樣使用它。讓我知道你是怎麼辦的。 – hutchonoid

2
var t = new Product(2, "bread"); 

這創建了一個全新的對象。

Remove(t); 

由於t是全新的,它不是在(即使具有相同的部件完全不同的目的是)存在,並且因此沒有被去除,因爲一個observableArrayremove方法,如果它傳遞的對象使用對象標識。

你可以重寫Remove作爲

function Remove(product) { 
     viewModel.products.remove(function(item) { 
      return item.Id==product.Id; 
     }); 
    } 

因爲傳遞一個函數到remove方法使其去除任何物品,其功能是真實的。

還有你Product構造了一個問題:

var Product = function (Id, Name) { 
     self = this; 

self是一個全球性的在這裏,和有點棘手的原因實際上是一個別名window。用var作爲前綴。

+0

感謝您的詳細解釋! +1 – Quoter

相關問題