2012-04-03 5 views
3

Большинство нокаутов кажется очень интуитивным. Одна вещь, которая мне странна, это то, как работает плагин сопоставления. Я ожидал/надеялся, что смогу накормить его JSON с помощью ajax-звонка и иметь своего рода «динамическую» модель представления, доступную для ссылки в моем HTML-коде.Использование отображения нокаутов для комплекса JSON

description of the mapping plugin даже делает его звук, как это, как это работает:

"If your data structures become more complex (e.g. they contain children or contain arrays) this becomes very cumbersome to handle manually. What the mapping plugin allows you to do is create a mapping from the regular JavaScript object (or JSON structure) to an observable view model."

Но, похоже, вы на самом деле нужно определить модель представления первого в своем коде, а затем вы можете заполнить его после факта использования плагин отображения и некоторые данные JSON. Это правильно?

Конкретный пример того, что я пытался сделать.

Я пытаюсь использовать нокаут с Solr (поисковая система, которая возвращает результаты поиска JSON). Остов структура данных JSON, возвращаемых 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": {} 
    } 

На самом деле, это структура я запитывания в моей отображенной модели представления, когда я первый поставил его.

Именно поэтому вы немного понимаете, как данные JSON возвращаются из Solr: массив response.docs содержит массив хэшей, где хэш-данные состоят из ключа/значений для ваших индексированных данных документа. Каждый хэш в массиве - это один документ, возвращаемый в результатах поиска.

Эта часть кажется на карте только отлично.

«Подсветка» части JSON - вот что вызывает у меня проблемы. Когда я пытаюсь ссылаться на поля подсветки в своем HTML, я получаю ReferenceErrors. Вот пример того, что поле подсветка может выглядеть в формате 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"] 
    } 
} 

У меня есть Еогеасп в моем HTML, который пытается разобрать через каждый элемент response.docs, и если выделение части объекта содержит соответствие для поля Id этого документа, я хочу заменить выделенный заголовок, а не заголовок по умолчанию. (В приведенном ниже коде, «Результаты» это имя ViewModel Я отображающей 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> 

Когда я пытаюсь использовать это, я всегда получаю эту ошибку:

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} 

Я пробовал варианты того, как я ссылаюсь на данные, но я просто не могу получить доступ к нему.

Редактировать Я немного продвигаюсь. В моем определении отображения я теперь указываю «подсветку» следующим образом:

"highlighting": ko.observable({}) 

Вместо того, чтобы просто указывать выделение на {}. Теперь я, по крайней мере, могу заглянуть в данные выделения, когда я сделаю свое сопоставление. Но я все еще вижу странные ошибки.

я упростил свой тест HTML код просто выплюнуть данные, освещающие для каждого результата поиска:

<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> 

Это возвращает несколько <pre> теги теперь выглядеть следующим образом:

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

Однако , если я изменю этот HTML-код на это:

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

Я продолжаю e, чтобы получить такие ошибки:

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

Не имеет смысла для меня! Мой предыдущий тест показывает, что имеющиеся данные содержат ключ «Заголовок», почему я не могу получить доступ к этим данным?

Редактировать Я создал a jsfiddle, но, разумеется, он работает должным образом. Я не могу воспроизвести свою проблему на jsfiddle. :-(

Редактировать OK Я делаю некоторые успехи здесь, но я все еще очень смущен относительно того, что происходит Сначала я изменил мою отладки HTML для этого:.

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

Затем я представил свой Ajax вызов, и я заметил, в консоли Chrome этого вывод:

undefined 
undefined 
> Object 

Так что для какой-то причины, петля foreach зацикливается на 3 Results.response.docs, а первые два не отображения ни к чему в моих основные моменты() obje ct, поэтому они возвращаются не определены - и поэтому моя попытка потянуть свойство .Title не удалась.

Чтобы подтвердить это, я завернул ko if: $root.Results.highlighting()[Id()] вокруг этого блока и, наконец, смог получить доступ к свойству .Title во время цикла foreach без ошибки JS.

Это все еще оставляет мне вопрос о том, почему/как есть 3 объекта Results.response.docs, которые зацикливаются. Возможно, привязка foreach запускается 3 раза, а первые 2 раза объект подсветки пуст, а в третий раз он заполняется? Но мне трудно понять, почему это было бы.

Еще одна возможная подсказка: если я вызову вызов ajax во второй раз, не перезагружая страницу, я вижу, что эти 3 «проходы» все возвращают действительный объект каждый раз в журнале консоли. Таким образом, вместо двух undefined s и объекта, это все три объекта подряд.

На моем выходе HTML, однако, я вижу только одну строку данных. Таким образом, это доказывает, что он не зацикливается на 3 элемента, но фактически запускается 3 раза. Вопрос остается ... ПОЧЕМУ?

+0

Возможно, вы можете взять эту скрипку: http://jsfiddle.net/rniemeyer/ZrY5R/ и получить ее до такой степени, чтобы она напоминала ваш код (обновить или развить его), чтобы мы могли лучше понять вашу структуру , –

+0

@Mason - Я не думаю, что ваш jsfiddle работает так, как вы думаете. Ссылка, которую вы указали выше, не работает для меня. Я проверил последнюю версию той же скрипки, и вы назначаете self.Results дважды, чтобы результат плагина сопоставления был перезаписан. – madcapnmckay

+0

@RPNiemeyer Спасибо за помощь. К сожалению, я сделал некоторые улучшения, как вы можете видеть в моих Редактивах выше, но, тем не менее, пока не можете проиллюстрировать эту проблему в jsfiddle. –

ответ

3

Плагин картографии работает так, как вы ожидаете. Ваша проблема в том, что вы ожидаете, что плагин создаст наблюдаемые на каждом уровне объекта. Это не то, как работает плагин. Это создаст только наблюдаемые свойства «листа». Поэтому в вашем случае $root.Results.highlighting не создается как наблюдаемый. Однако свойства id в документах создаются как наблюдаемые, поэтому решение есть.

$root.Results.highlighting[Id()] 

Я считаю, что вы, возможно, были смущены, потому что один из ваших скрипок была назначая self.Results дважды, который делал вид, работать в одну стороны, когда на самом деле проблема была маскируется.

Вот рабочая версия

http://jsfiddle.net/madcapnmckay/UaBKe/

Надеется, что это помогает.

+0

Эй, @madcapnmckay, спасибо за ответ! Возможно, вы упустили мои обновления (Edits) в нижней части моего вопроса. В конце концов я выяснил, что мне нужно определить выделение как ko.observable ({}). Мой jsfiddle был испорчен, но причина, по которой я назначил себя. Результаты дважды были я пытался проиллюстрировать начальную настройку, а затем второй вызов, который будет срабатывать с моим ajax. У меня есть более новый jsfiddle, который более правильно показывает это (я думаю). Конечно, это не иллюстрирует мою проблему, так как она отлично работает. http://jsfiddle.net/dWQfP/5/ –

+0

@ MasonG.Zhwiti - Я видел это редактирование, но я не думаю, что он нужен. Мое решение не требует, чтобы это работало. Простой коррекции разметки было достаточно. Если вы хотите повлиять на то, что создано для определенных свойств, вы должны использовать опцию сопоставления 'create'. Я немного потерял, что касается вашей проблемы. Все ли исправлено? – madcapnmckay

+0

Даже после реализации ваших исправлений у меня все еще были проблемы с использованием сопоставления данных JSON. Я никогда не смог заставить его работать правильно, в конечном итоге он, казалось, запускал несколько блоков if, но только на «конечном» триггере были все данные, заполненные отображаемым объектом. Теперь я отказался от сопоставления объекта с плагином и просто сделаю это сам, и это ОСОБЕННО упростило мой код javascript, а также ... фактически работает. :-) –

Смежные вопросы