Você pode chamar ko.applyBindings para vincular uma visualização parcial?

258

Estou usando o KnockoutJS e tenho uma visualização principal e um modelo de visualização. Eu quero que uma caixa de diálogo (a interface do usuário do jQuery) seja exibida com outra exibição à qual um modelo de exibição filho separado será vinculado.

O HTML para o conteúdo da caixa de diálogo é recuperado usando AJAX, portanto, desejo poder chamar ko.applyBindingsdepois que a solicitação for concluída e quero vincular o modelo de exibição filho apenas à parte do HTML carregada via ajax dentro da div da caixa de diálogo.

Isso é realmente possível ou preciso carregar TODAS as minhas visualizações e modelos de exibição quando a página é carregada inicialmente e depois ligar ko.applyBindingsuma vez?

Charlie
fonte

Respostas:

431

ko.applyBindings aceita um segundo parâmetro que é um elemento DOM para usar como raiz.

Isso permitiria que você fizesse algo como:

<div id="one">
  <input data-bind="value: name" />
</div>

<div id="two">
  <input data-bind="value: name" />
</div>

<script type="text/javascript">
  var viewModelA = {
     name: ko.observable("Bob")
  };

  var viewModelB = {
     name: ko.observable("Ted")
  };

  ko.applyBindings(viewModelA, document.getElementById("one"));
  ko.applyBindings(viewModelB, document.getElementById("two"));
</script>

Portanto, você pode usar esta técnica para vincular um viewModel ao conteúdo dinâmico carregado na sua caixa de diálogo. No geral, você só quer ter cuidado para não chamar applyBindingsvárias vezes nos mesmos elementos, pois terá vários manipuladores de eventos anexados.

RP Niemeyer
fonte
17
Se você também deseja remover as ligações em algum momento no caminho, pode ligar ko.cleanNode(document.getElementById("one")para limpar as coisas ou ko.removeNode(document.getElementById("one")limpar as coisas e remover o nó do DOM.
Michael Berkompas 15/10/12
7
Apenas observe que cleanNodee removeNodenão removerá os manipuladores de eventos, portanto, tenha cuidado. Em alguns casos, é preferível usar o templateou withbinding nessas áreas, para que você tenha novos elementos renderizados.
RP Niemeyer
7
Atualmente, é algo que está faltando no KO. Não pretendemos especificamente que as pessoas "religuem" seções. No entanto, o KO anexa eventos usando o jQuery, se for mencionado, para que você possa $(element).unbind();remover todos os manipuladores.
RP Niemeyer
5
Onde estão documentadas essas funções (applyBindings, cleanNode, removeNode)? Não consigo encontrar suas assinaturas de funções em knockoutjs.com.
EricP
2
Seria bom se este fosse um local facilmente localizável na documentação. Eu nem vi uma menção a isso.
Travis Kaufman
61

Embora a resposta de Niemeyer seja uma resposta mais correta para a pergunta, você também pode fazer o seguinte:

<div>
  <input data-bind="value: VMA.name" />
</div>

<div>
  <input data-bind="value: VMB.name" />
</div>

<script type="text/javascript">
  var viewModels = {
     VMA: {name: ko.observable("Bob")},
     VMB: {name: ko.observable("Ted")}
  };

  ko.applyBindings(viewModels);
</script>

Isso significa que você não precisa especificar o elemento DOM e pode vincular vários modelos ao mesmo elemento, assim:

<div>
  <input data-bind="value: VMA.name() + ' and ' + VMB.name()" />
</div>
mhu
fonte
4
você também pode usar "com" para alocar regiões da página para modelos individuais - dados-bind = "com: VMA"
lexicalscope
3
@flamingpenguin: Sim, mas withnão sai barato, veja: link
mhu
7

Eu consegui vincular um modelo personalizado a um elemento em tempo de execução. O código está aqui: http://jsfiddle.net/ZiglioNZ/tzD4T/457/

O interessante é que aplico o atributo data-bind a um elemento que não defini:

    var handle = slider.slider().find(".ui-slider-handle").first();
    $(handle).attr("data-bind", "tooltip: viewModel.value");
    ko.applyBindings(viewModel.value, $(handle)[0]);
ZiglioUK
fonte
tendo problemas com o ko 2.3, o código acima está em um manipulador de clientes chamado quando aplico o ko.applyBindings () global. Então agora recebo o erro "Você não pode aplicar ligações várias vezes ao mesmo elemento". Ainda estou tentando descobrir por que recebo o erro. Não podemos aplicar uma ligação à mesma variável várias vezes, cada uma para diferentes elementos?
ZiglioUK
Aqui está a versão com ko 2.3 que não funciona: jsfiddle.net/ZiglioNZ/tzD4T/458
ZiglioUK
Adicionar uma chamada a ko.cleanNode () antes de chamar applyBinding para a exibição parcial não parece ajudar: jsfiddle.net/ZiglioNZ/tzD4T/459
ZiglioUK
Resolvido: eu nem precisava chamar applyBindings!
ZiglioUK
Eu apenas editei o código-fonte do knockoutjs e comentou a parte em que a função twrows "Você não pode aplicar ligações várias vezes ao mesmo elemento.", agora tudo funciona ok ... eu sei que essa é uma solução suja, mas sou nova na biblioteca, então Eu não sei como não aplicá-lo várias vezes para o meu problema.
Geomorillo