Можно ли в Knockout.js использовать значение динамической привязки?

Можно ли в Knockout.js сделать правую часть привязки (значение привязки) динамической? Например,

<input data-bind="value: dynamicBinding()"/>
<script type="text/javascript">
var vm = {
   dynamicBinding : function() {
       return "foo().bar";
   },
   foo : ko.observable({
       bar : ko.observable("hi");
   }
};
ko.applyBindings(vm);
</script>

результатом должно быть то, что функция dynamicBinding выполняется при применении привязок, и результирующая строка используется в качестве привязки. Элемент ввода должен быть привязан к foo().bar, который является наблюдаемым со значением «привет».

Если вам интересно, зачем мне это нужно, я пытаюсь отобразить динамическую таблицу с нокаутом, где и строки, и столбцы являются наблюдаемыми массивами, и я хочу, чтобы определения столбцов содержали выражение привязки для этого столбца. I.e., я хочу иметь возможность сделать это:

<table data-bind="foreach: data">
  <tr data-bind="foreach: $root.columns">
    <td data-bind="text: cellValueBinding()"></td>
  </tr>
</table>
<script type="text/javascript">
var vm = {
   data: ko.mapping.fromJS([
     {title: "Brave New World", author: { name : "Aldous Huxley" },
     {title: "1984", author: { name : "George Orwell" },
     {title: "Pale Fire", author: { name : "Vladimir Nabokov" }]),
   columns: ko.observableArray([
     {header: "Title", cellValueBinding: function () { return "$parent.title"; }}, 
     {header: "Author", cellValueBinding: function () { return "$parent.author().name"; }}
   ])
};
ko.applyBindings(vm);
</script>

Как видно из примера, определение столбца умеет извлекать значение из данных. Сама разметка таблицы является более или менее заполнителем. Но, насколько я могу судить, это не работает из-за того, как нокаут обрабатывает привязки. Есть ли другие доступные варианты?

Спасибо.


Решение. В итоге я воспользовался предложением Ильи: я могу позволить cellValueBinding быть функцией, которая принимает строку и столбец в качестве аргументов и возвращает наблюдаемое значение. Этот метод демонстрируется в этой скрипте.


person waxwing    schedule 12.12.2012    source источник
comment
Если вы абсолютно хотите выполнить это динамически, вам придется прибегнуть к использованию with/eval для этого. Нет ничего встроенного в нокаут, чтобы сделать это.   -  person Jeff Mercado    schedule 13.12.2012
comment
Что ж, альтернативы приветствуются. :) Я почти уверен, что мог бы легко добиться того же с помощью шаблонов (каждый столбец определяет свой собственный шаблон ячейки), но это кажется слишком тяжелым.   -  person waxwing    schedule 13.12.2012
comment
Возможно, вас заинтересует моя привязка к таблице: github.com/mbest/knockout-table   -  person Michael Best    schedule 13.12.2012
comment
@MichaelBest: Спасибо за совет! Похоже, вы решили проблему произвольных значений ячеек так же, как и я, — позволив dataItem быть функцией.   -  person waxwing    schedule 13.12.2012


Ответы (1)


Используйте для этого ko.computed.
Посмотрите на пример
JSFiddle
EDIT
Во втором примере вы можете передать $parent значение функции

<td data-bind="text: cellValueBinding($parent)"></td>  

и в модели

{header: "Title", cellValueBinding: function (parent) { return parent.title; }},
{header: "Author", cellValueBinding: function (parent) { return parent.author().name; }}

JSFiddle

person Ilya    schedule 12.12.2012
comment
Спасибо, но я не понимаю, как это будет работать во втором примере. Мне нужно, чтобы привязка была в определении столбца. Для того, чтобы вычисление работало, оно должно быть контекстно-зависимым. В частности, он должен иметь доступ к переменной контекста $parent. - person waxwing; 13.12.2012
comment
Это действительно может сработать. Я расширил вашу скрипку, так как ожидал, что она не будет работать с реальными наблюдаемыми (и двусторонними привязками, такими как значение), но, похоже, все в порядке: jsfiddle.net/7vCNt/2 . Я собираюсь проверить это завтра в своем реальном коде. Спасибо. - person waxwing; 13.12.2012