2015-01-09 3 views
0

У меня есть сам описывающий следующее определение:Уплотненных наблюдаемый в KnockoutJS

var my_data = { 
    types: { typeA: {fieldX: { type: "string"}}, 
      typeB: {fieldY: { type: "string"}} }, 
    entries: [{ type: "typeA", fieldX: "foo" }, 
      { type: "typeB", fieldY: "bar" }] 
    }; 

Идея заключается в том, что «типы» описывает данные, представленные для каждого индекса «записей». Эти данные используются для визуализации формы для редактирования данных JSON через интерфейс RESTful (вход для каждого описываемого типа типа с привязками к значению поля записи).

Я пытаюсь настроить форму в нокауте, которая позволяет редактировать «записи». Сначала я создаю HTML-код, который создает поле выбора для определения типа. Для этого я карту типы словаря в массив:

function mapDictionaryToArray(dictionary) { 
    var result = []; 
    for (var key in dictionary) { 
     if (dictionary.hasOwnProperty(key)) { 
      result.push({ key: key, value: dictionary[key] }); 
     } 
    } 

    return result; 
} 

Затем KnockoutJS код для отображения записей

<!-- ko foreach: entries --> 
      <select data-bind="options: editTestViewModel.types, 
           optionsText: 'key', 
           optionsValue: 'value', 
           value: type, 
           event: { change: editTestViewModel.drawType }"></select> 
      <div data-bind="attr: { id: $index() + 'typeFields' }" class="container"></div> 
<!-- /ko --> 

Вид модели:

function EditTestViewModel() { 
    var self = this; 

    self.entries = ko.observableArray(); 
    self.types = ko.observable(); 

    self.setTest = function(test) { 
     self.test = test; 
     self.types(mapDictionaryToArray(test.types())); 
     self.entries(ko.mapping.fromJS(test.entries(), self.stateMapping)()); 

    }; 

    self.editTest = function() { 
     $('#edit').modal('hide'); 
     testsViewModel.edit(self.test, { 
      entries: self.entries() , 
      types: self.types() 
     }); 
    }; 

    self.drawType = function(place) { 
     home = $('#typeFields'); 
     home.children().remove(); 
     for (var field in place.type) { 
      tag = $('<div class="input-group">').appendTo(home); 
      $('<span class="input-group-addon">' + field + '</span>').appendTo(tag); 
      $('<input type="text" class="form-control" data-bind="text: \'test\'">').appendTo(tag); 
     } 
    }; 

    self.stateMapping = { 
     'type': { 
      create: function(options) { 
       return options.data 
      } 
     } 
    } 
} 

var editTestViewModel = new EditTestViewModel(); 
ko.applyBindings(editTestViewModel, $('#edit')[0]); 

Проблема, которую я имею заключается в том, что вставленные данные не обрабатываются KockoutJS. Функции выбора типа и заполняют соответствующие поля, но значение поля не заполняется (статический «тест» пока). Является ли KnockoutJS даже поддерживаемым для динамически вставленного контента, и если я пытаюсь его правильно связать?

+1

Я бы сказал, что вы пытаетесь, конечно, возможно с нокаутом , Я не уверен, что попытка динамически вставить html таким образом - это правильный путь, хотя вы вообще не считаете, что используете [templates] (http://knockoutjs.com/documentation/template-binding.html)? –

+0

Что сказал Джеймс, вы считали шаблоны? У вас не должно быть HTML в вашем Javascript, если вы сделаете это правильно. Вы можете легко использовать foreach с нокаутом в своих html-шаблонах! Просто проверьте это! –

+1

OP: * Является ли KnockoutJS даже поддерживаемым для динамически вставленного содержимого, и если я пытаюсь его правильно связать? * -> KnockoutJS ** означает ** для этого и с помощью jQuery для выполнения манипуляций с DOM вы меняете вид вашей модели без знания нокаута. – Tyblitz

ответ

1

Спасибо всем за комментарии к OP.

Я переписал использовать шаблоны. По какой-то причине у меня создалось впечатление, что наблюдаемые не могут использоваться для хранилища option.value. Это, похоже, не так (https://stackoverflow.com/a/27873057/1440598). В конструкторе я теперь устанавливаю тип для наблюдаемого для каждой записи.

Изменение выбора инициирует обновление шаблона поля: http://fiddle.jshell.net/jhwpn6dy/3/

HTML:

<div data-bind="text: data.test"></div> 

<div data-bind="template: { name: 'entry-template', foreach: entries, as: 'entry' }"></div> 

<script type="text/html" id="entry-template"> 
    <h3 data-bind = "text: entry.type">I'm an entry</h3> 
    <select data-bind="options: $root.type_keys, 
         optionsText: 'key', 
         optionsValue: 'key', 
         value: entry.type"></select> 
    <div data-bind="template: { name: 'field-template', foreach: $root.fieldList(entry), as: 'field' }"></div> 
</script> 

<script type="text/html" id="field-template"> 
    <div class="input-group"> 
     <span class="input-group-addon" data-bind="text: field"></span> 
     <input type="text" class="form-control" data-bind="attr: { 'aria-label': field }, value: entry[field]"/> 
    </div> 
</script> 

JS:

var data = { 
    types: { 
     typeA: { 
      fieldX: { 
       type: "string" 
      } 
     }, 
     typeB: { 
      fieldY: { 
       type: "string" 
      } 
     } 
    }, 
    entries: [{ 
     type: "typeA", 
     fieldX: "foo" 
    }, { 
     type: "typeB", 
     fieldY: "bar" 
    }], 
    test: "Hello" 
}; 

function MainViewModel(data_obj) { 
    var self = this; 

    self.data = data_obj; 
    self.type_keys = mapDictionaryToArray(data_obj.types);  

    for (var entry in data_obj.entries) { 
     data_obj.entries[entry].type = ko.observable(data_obj.entries[entry].type); 
    } 
    self.entries = ko.observableArray(data_obj.entries); 
    console.log(self.entries()); 
} 

MainViewModel.prototype.fieldList = function (entry) { 
    var self = this; 
    var keys = []; 

    for (var key in self.data.types[entry.type()]) { 
     if (entry.hasOwnProperty(key)) { 
      keys.push(key); 
     } 
    } 

    <!-- console.log(entry.type); --> 
    return keys; 
}; 

function mapDictionaryToArray(dictionary) { 
    var result = []; 
    for (var key in dictionary) { 
     if (dictionary.hasOwnProperty(key)) { 
      result.push({ key: key, value: dictionary[key] }); 
     } 
    } 

    return result; 
} 

var dataViewModel = new MainViewModel(data); 

ko.applyBindings(dataViewModel); 
+0

Я рад, что ты понял :) – Tyblitz

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