2013-11-15 112 views
3

我们环境中的典型场景是允许用户选择由服务器(终端,产品,..)提供的选项列表,以及然后呈现所请求的数据。如何使用预定义的文本和值选项定义自定义挖空“选项绑定”

由服务器提供的选项是在名称,ID的格式,并因此以下敲除构建体中使用的所有经常:

<select data-bind="options: serverOptions, optionsText: 'Name', optionsValue: 'ID', value: selectedOption> 

这将是理想的是使自定义bindingHandler,叫做“NamedIdOptions”在allBindingsAccessor()上指定optionsText和optionsValue,然后重定向到标准选项绑定处理程序。

<select data-bind="NamedIdOptions: serverOptions, value: selectedOption"></select> 

此之前,我已经做自己的绑定填补了选项我自己的处理程序 - 但是,我更愿意使用由选项结合处理器提供了框架。

我试过不同的方法没有太多的成功 - 选项绑定使用allBindings ['optionsValue']和allBindings ['optionsText']来访问该值,似乎我没有办法设置这些。 (我想,以避免在使用applyBindingsToNode方法写的线沿线的东西:

ko.bindingHandlers.NamedIdOptions = { 
    init: function(element, valueAccessor, allBindingsAccessor, viewModel) 
    { 
     var allBindings = allBindingsAccessor(); 
     allBindings.*FORCESET*("optionsText", "Name"); 
     allBindings.*FORCESET*("optionsValue", "ID"); 

     retun ko.bindingHandlers.options.init.apply(this, arguments); 
    }, 
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) 
    { 
     retun ko.bindingHandlers.options.update.apply(this, arguments); 
    } 
} 

然而,好像我没有方法可行设置在allBindings任何

我不允许。使用

allBindings['_ko_property_writers']['optionsText']("Name"); 
allBindings['_ko_property_writers']['optionsValue']("ID"); 

我真的希望避免applyBindingsToNode在init构造为

Knockout - is it possible to combine standard select bindings with a custom binding?

有没有人现在就解决问题的简单方法?

+0

我不知道这是否准确回答你的问题,但是如果你正在创建一个可重用的控件,你总是可以使用computedOptions和computedName,并且它们是被设置为任何传入值的可观察值。 –

+0

在以前的Knockout版本中,您曾经能够获得与添加optionsText和optionsValue直接allBindings,它会工作。这就是我所做的与你所描述的完全相同的场景。 – BrandonLWhite

回答

2

好的结合起来 - 我结束了使用申请绑定反正到节点:

ko.bindingHandlers.NamedIdOptions = 
{ 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) 
    { 
     var allBindings = allBindingsAccessor(); 
     var newBindingOptions = { options: allBindings.NamedIdOptions, optionsText: "Name", optionsValue: "ID" }; 

     delete allBindings.NamedIdOptions; 
     ko.utils.extend(newBindingOptions, allBindings); 

     ko.applyBindingsToNode(element, newBindingOptions, viewModel); 
    } 
}; 

而且它似乎按预期工作 - 我有点不确定价值和selectedOptions - 哪些有“后”设置为选项。我想我在NamedIdOptions在值绑定之前铺平了是安全的吗?

+0

只有在删除NamedIdOptions时才会出现问题 - 实际上,所有已调用的操作都应该首先被删除 –

1

转发呼叫时,你不能只是假的allBindingsAccessor参数?

update: function (element, valueAccessor, allBindingsAccessor, viewModel) 
{ 
    var allBindings = allBindingsAccessor(), 
     fakeAllBindingsAccessor = function() { 
      // I've used jQuery.extend here, you could also manually add the properties to the allBindings object 
      return $.extend(true, allBindings, { 
       optionsValue: 'ID', 
       optionsText: 'Name' 
      }; 
     }; 
    return ko.bindingHandlers.options.init.call(this, element, valueAccessor, fakeAllBindingsAccessor, viewModel); 
} 

编辑:添加更多的代码到现有allBindingsAccessor与手动假绑定

+0

这绝对是值得一试的 –

+0

不幸的是,它似乎并没有工作。 可以在init函数中制作一个假的allbindings访问器。在它的工作原理 - 然而,假更改覆盖更新。 如果有人在更新方法中使用相同的技巧,则下列错误会得到以下错误: _'undefined'不是函数(评估'd.get(“optionsIncludeDestroyed”)')_ –

+0

您可以发布完整你的HTML标签的数据绑定?我会调试,看看我能否发现我的错误。 –

3

你可能会考虑使用ko.applyBindingAccessorsToNode。这就是我已经开始在KO 3.0做:

ko.bindingHandlers.NamedIdOptions = { 
    init: function(element, valueAccessor, allBindingsAccessor) 
    { 
     var injectedBindingValues = {   
      options: valueAccessor, 
      optionsValue: function() { return "ID" }, 
      optionsText: function() { return "Name" } 
     }; 

     ko.applyBindingAccessorsToNode(element, injectedBindingValues); 

     //tell Knockout that we have already handled binding the children of this element 
     // 
     return { controlsDescendantBindings: true };   
    } 
} 

你可以看到它在行动this fiddle

注意:我通常使用从服务器(C#,JSON.NET)发送的JSON模式自动从C#属性或数据库模式元数据中填充UI中的选项。我将我的代码进行了提炼,并将其更改为与OP针对问题的连续性所做的相匹配。但是如果对JSON模式技术有任何兴趣,请打我并发布。

+0

Thx很多 - 显然,它并没有在我们使用的KO 2.2中定义在我们的生产环境中。但是,解决方案比我的上面要干净得多。 –

+0

关于服务器连接 - 我们保持我们的C#视图模型尽可能小,并以Json格式自动序列化它们,并将它们转换为javasscript对象。因此,通常我们会沿着这样的方式写一些东西: '