O knockoutjs disponibiliza algumas variáveis de contexto, assim é possível acessar dados de um determinado contexto ou de outro. Vamos ver um exemplo prático, primeiro vamos criar uma classe “ViewModel” simples, para entender como funciona a variável “$data”:
http://jsfiddle.net/andrebtoe/ns32f7at
Exemplo com $data
function ViewModel(){ var self = this; self.clientes = ko.observableArray(["José", "Maria", "João"]); } ko.applyBindings(new ViewModel());
Acima estamos definindo a classe “ViewModel” com um array de clientes. Cada item do array é um dado primitivo.
E para o html, vamos definir:
<ul data-bind="foreach: clientes"> <li> <div data-bind="text: $data"></div> </li> </ul>
Acima temos uma tag “ul” utilizando “foreach” para listar os itens de “clientes”. Como não temos um objeto em cada item, podemos passar o “$data”, para o binding handler text. Se no lugar de uma string, tivesse um objeto, poderíamos, acessar sua propriedade como fazemos em javascript.
A variável “$rawData” é muita parecida com o “$data”, porem ela trabalha com o valor real, ou seja, ela utiliza a função do knockoutjs “ko.unwrap”, para obter um dado de uma propriedade “observable” ou não, ela encapsula a verificação, para facilitar a utilização.
Exemplo $parent
Neste próximo exemplo vamos adicionar um atributo no “viewModel” como segue:
http://jsfiddle.net/andrebtoe/5a0c3fgb
function ViewModel(){ var self = this; self.sufixo = "Nome: "; self.clientes = ko.observableArray(["José", "Maria", "João"]); } ko.applyBindings(new ViewModel());
Acima adicionamos o atributo “sufixo”, com valor fixo “Nome: “, e mudamos um pouco o html:
<ul data-bind="foreach: clientes"> <li> <div data-bind="text: $parent.sufixo + $data"></div> </li> </ul>
Acima tem um novo valor para mostrar, estamos concatenando o valor do “sufixo” com o nome do cliente (isso não é uma boa prática, já que deixa regra na view, isso pode se tornar uma verdadeira dor de cabeça, fiz isso apenas para fins didáticos), repare que estamos acessando “sufixo” com “$parent”, isso é necessário porque não temos essa propriedade dentro de cada item do array “clientes”. O “$parent” acessa um nível anterior, ao qual estamos no momento, caso você necessite acessar um maior nível utilize: “$parents[]”.
Exemplo com $parents[]
Neste exemplo vamos mudar um pouco a classe “ViewModel” e o html. http://jsfiddle.net/andrebtoe/djy55uj4/1.
function ViewModel(){ var self = this; self.sufixo = "Valor: "; self.clientes = ko.observableArray([ { nome: "Maria", pedidos: [ { id: 1, valor: 160.17 } ] } ]); } ko.applyBindings(new ViewModel());
Acima modificamos o array de “clientes”, agora ele possui uma lista de pedidos em cada item de “clientes”, e modificamos o html também:
<ul data-bind="foreach: clientes"> <li> <div> <span>Nome:</span> <span data-bind="text: nome"></span> <ul data-bind="foreach: pedidos"> <li> <span data-bind="text: $parents[1].sufixo"></span> <span data-bind="text: valor"></span> </li> </ul> </div> </li> </ul>
Acima temos a utilização do “$parents[1]” para acessar o segundo nível, a partir do contexto atual, podemos colocar o nível que necessitar.
Exemplo com $root
Neste exemplo vamos acessar um método na “raiz” do “ViewModel”, ou seja, utilizando a variável “$root”, vamos modificar o “ViewModel”:
http://jsfiddle.net/andrebtoe/3stm845p
function ViewModel(){ var self = this; self.clientes = ko.observableArray(["José", "Maria", "João"]); self.excluir = function(itemCliente){ self.clientes.remove(itemCliente); }; } ko.applyBindings(new ViewModel());
Acima adicionamos o método “excluir”, para remover o item passado por parâmetro, do array “clientes”. E mexemos no html novamente:
<ul data-bind="foreach: clientes"> <li> <div> <span data-bind="text: $data"></span> <a href="#" data-bind="click: $root.excluir">Excluir</a> </div> </li> </ul>
Acima adicionamos uma tag “a”, que chama o método excluir, repare que o método é precedido por “$root”, isso porque o método “excluir” não está presente em cada item do array “clientes”, e sim na “raiz” do “ViewModel”.
Exemplo com $index
A variável “$index” pode ser utilizada o binding handler “foreach”, se utilizamos o “ViewModel” do primeiro exemplo com o html:
http://jsfiddle.net/andrebtoe/r822s7cx
<ul data-bind="foreach: clientes"> <li> <span data-bind="text: $index"></span> <span data-bind="text: $data"></span> </li> </ul>
Acima adicionamos uma tag “span” com o valor da varável “$index”, para mostrar o índice do array.
Exemplo com $element
Neste exemplo vamos ver como utilizar a variável “$element”, antes de mais nada gostaria de comentar que essa variável deve ser utilizada com muito cuidado. O knockoutjs tenta deixar a manipulação do DOM transparente para quem utiliza. Eu vejo o pessoal colocando acesso a elementos dentro do “ViewModel”, isso não é uma boa ideia, já que isso pode ser tornar uma dor de cabeça, imagine que você se veja em um cenário que tem que atualizar os valores de elementos, que ficaram dessincronizados, ou não tiveram um comportamento insperado (acho que me estendi muito!).
Essa variável disponibiliza os dados do elemento como: id, style, src, etc. Veja o exemplo: http://jsfiddle.net/andrebtoe/zmzy0tjo/1/
<div style="display:block" data-bind="text: $element.style.display"></div>
Acima estamos mostrando o valor de “display” da propriedade “style” do próprio elemento.
Espero ter ajudado!
Até a próxima!