sando o mapeamento Knockout para JSON comple

A maioria dos Knockout parece muito intuitiva. Uma coisa que é estranha para mim é como o plug-in de mapeamento funciona. Eu estava esperando / esperando poder alimentá-lo JSON a partir de uma chamada ajax e ter uma espécie de modelo de exibição "dinâmico" disponível para referência no meu HTML.

O descrição do plug-in de mapeamento faz parecer que é assim que funciona:

"Se suas estruturas de dados se tornarem mais complexas (por exemplo, contêm filhos ou matrizes), isso será muito complicado de manipular manualmente. O que o plug-in de mapeamento permite é criar um mapeamento a partir do objeto JavaScript comum (ou estrutura JSON) para um modelo de vista observável. "

Mas parece que você realmente precisa definir o modelo de exibição primeiro no seu código e, em seguida, preenchê-lo usando o plug-in de mapeamento e alguns dados JSON. Isto está certo

Um exemplo concreto do que eu estava tentando fazer.

Estou tentando usar o Knockout com o Solr (um mecanismo de pesquisa que retorna resultados de pesquisa JSON). A estrutura do esqueleto dos dados JSON retornados pelo Solr é:

  {
      "responseHeader": {
          "status": 0,
          "QTime": 0,
          "params": {
              "facet": "true",
              "facet.field": "System",
              "q": "testphrase",
              "rows": "1",
              "version": "2.2"
          }
      },
      "response": {
          "numFound": 0,
          "start": 0,
          "maxScore": 0.0,
          "docs": []
      },
      "facet_counts": {
          "facet_queries": {},
          "facet_fields": {
              "System": []
          },
          "facet_dates": {},
          "facet_ranges": {}
      },
      "highlighting": {}
  }

a verdade, essa é a estrutura que estou inserindo no meu modelo de visualização mapeada quando o configure

Para que você entenda um pouco sobre como os dados JSON retornam do Solr: A matriz response.docs contém uma matriz de hashes, na qual os dados do hash são compostos de chaves / valores para os dados do documento indexado. Cada hash na matriz é um documento retornado nos resultados da pesquis

Essa parte parece mapear muito bem.

A parte "destacada" do JSON é o que me causa problemas. Quando tento fazer referência aos campos de destaque no meu HTML, recebo ReferenceErrors. Aqui está um exemplo de como o campo de destaque pode parecer no JSON:

"highlighting": {
    "2-33-200": {
        "Title": ["1992 <b>Toyota</b> Camry 2.2L CV Boots"]
    },
    "2-28-340": {
        "Title": ["2003 <b>Toyota</b> Matrix 2.0L Alignment"]
    },
    "2-31-2042": {
        "Title": ["1988 <b>Toyota</b> Pickup 2.4L Engine"]
    }
}

Eu tenho um foreach no meu HTML que tenta analisar cada elemento response.docs e, se a parte destacada do objeto contiver uma correspondência com o campo de ID do documento, desejo substituir o Título destacado em vez do Título padrão. (No código abaixo, "Resultados" é o nome do modelo de exibição para o qual estou mapeando o JSON.)

<div id="search-results" data-bind="foreach: Results.response.docs">
    <div data-bind="attr: { id: 'sr-' + Id }" class="search-result">
        <h3 class="title"><a data-bind="html: (($root.Results.highlighting[Id]['Title'] != undefined) ? $root.Results.highlighting[Id]['Title'] : Title), attr: {href: Link}"></a></h3>
        <span class="date" data-bind="text: DateCreated"></span>
        <span class="snippet" data-bind="html: Snippet"></span>
    </div>
</div>

Quando tento usar isso, sempre recebo este erro:

Uncaught Error: Unable to parse bindings.
Message: TypeError: Cannot read property 'Title' of undefined;
Bindings value: html: (($root.Results.highlighting[Id]['Title'] != undefined)  ? $root.Results.highlighting[Id]['Title'] : Title), attr: {href: Link}

Tentei variações de como estou referenciando os dados, mas não consigo acessá-lo

Edita Estou fazendo um pouco de progresso. Na minha definição de mapeamento, agora especifico "realce" como este:

"highlighting": ko.observable({})

Em vez de apenas definir o destaque para {}. Agora, pelo menos, sou capaz de examinar um pouco os dados de destaque quando faço meu mapeamento. Ainda estou vendo erros estranhos.

Simplifiquei meu código HTML de teste para cuspir os dados de destaque de cada resultado da pesquisa:

<div id="search-results" data-bind="foreach: Results.response.docs">
    <pre data-bind="text: JSON.stringify(ko.toJS($root.Results.highlighting()[Id()]), null, 2)"></pre>
</div>

Isto retorna vários<pre> tags agora parecidas com esta:

{
  "Title": [
    "1992 <b>Toyota</b> Camry 2.2L CV Boots"
  ]
}

No entanto, se eu alterar esse código HTML para este:

<pre data-bind="text: $root.Results.highlighting()[Id()]['Title']"></pre>

Continuo a receber erros como este:

Message: TypeError: Cannot read property 'Title' of undefined;
Bindings value: text: $root.Results.highlighting()[Id()]['Title']

Não faz sentido para mim! Meu teste anterior mostra que os dados disponíveis contêm uma chave "Título", por que não consigo acessar esses dados?

Edita Eu crieia jsfiddle, mas é claro ... funciona como esperado. Não consigo reproduzir meu problema no jsfiddle. : -

Edita OK Estou fazendo algum progresso aqui, mas ainda estou muito confuso com o que está acontecendo. Primeiro mudei meu HTML de depuração para este:

<div id="search-results" data-bind="foreach: Results.response.docs">
    <pre data-bind="text: console.log($root.Results.highlighting()[Id()])"></pre>
</div>

Enviei minha chamada ajax e notei no console do Chrome esta saída:

undefined
undefined
> Object

Então, por algum motivo, oforeach loop está repetindo mais de 3 Results.response.docs, e os dois primeiros não estão mapeando para nada no meu objeto highlights (), então eles estão retornando indefinidos - e é por isso que minha tentativa de puxar a propriedade .Title falhou.

Para confirmar isso, envolvi umko if: $root.Results.highlighting()[Id()] em torno desse bloco e finalmente conseguiu acessar a propriedade .Title durante o loop foreach sem um erro J

Isto ainda me deixa com a pergunta de por que / como existem 3 objetos Results.response.docs sendo repetidos. Talvez a ligação foreach esteja sendo executada três vezes e as duas primeiras vezes que o objeto de destaque esteja vazio e, na terceira vez, seja finalmente preenchido? Mas estou tendo dificuldade para descobrir por que isso seria.

Outra pista possível: se eu acionar a chamada ajax pela segunda vez, sem recarregar a página, posso ver que esses 3 "passes" retornam um objeto válido todas as vezes no log do console. Então, ao invés de doisundefineds e um Objeto, são três Objetos, todos seguido

Na minha saída HTML, porém, vejo apenas uma linha de dados. Então isso parece provar que não está repetindo três elementos, mas está sendo executado três vezes. A questão permanece ... POR QUE?

questionAnswers(2)

yourAnswerToTheQuestion