Я пытаюсь использовать генератор KnockoutJS SPA Yeoman для создания приложения SPA и использования плагина ko.mapping. Я скорректировал require.config.js
, чтобы включить ko-mapping.Использование ko.mapping с компонентами нокаута в SPA
В автономном приложении я могу заставить плагин сопоставления работать нормально, но когда я пытаюсь использовать его в построенной функции компонента, привязки никогда не будут доступны в шаблоне html. Любые идеи о том, что я могу сделать неправильно, чтобы получить плагин отображения для воспроизведения в компоненте KO?
var require = {
baseUrl: ".",
paths: {
"bootstrap": "bower_modules/components-bootstrap/js/bootstrap.min",
"crossroads": "bower_modules/crossroads/dist/crossroads.min",
"hasher": "bower_modules/hasher/dist/js/hasher.min",
"jquery": "bower_modules/jquery/dist/jquery",
"knockout": "bower_modules/knockout/dist/knockout",
"komapping": "bower_modules/knockout-mapping/knockout.mapping",
"knockout-projections": "bower_modules/knockout-projections/dist/knockout-projections",
"signals": "bower_modules/js-signals/dist/signals.min",
"text": "bower_modules/requirejs-text/text"
},
shim: {
"bootstrap": { deps: ["jquery"] },
"komapping": { deps: ["knockout"], exports: 'komapping'}
}
};
define(['jquery', 'knockout', './router', 'bootstrap', 'knockout-projections'], function($, ko, router) {
// Components can be packaged as AMD modules, such as the following:
ko.components.register('nav-bar', { require: 'components/nav-bar/nav-bar' });
ko.components.register('home-page', { require: 'components/home-page/home' });
// ... or for template-only components, you can just point to a .html file directly:
ko.components.register('about-page', {
template: { require: 'text!components/about-page/about.html' }
});
ko.components.register('bems', { require: 'components/bems/bems' });
ko.components.register('user-page', { require: 'components/user-page/user' });
ko.components.register('team-page', { require: 'components/team-page/team' });
ko.components.register('exec-page', { require: 'components/exec-page/exec' });
// [Scaffolded component registrations will be inserted here. To retain this feature, don't remove this comment.]
// Start the application
ko.applyBindings({ route: router.currentRoute });
});
define(['knockout', 'text!./bems.html','komapping'], function(ko, templateMarkup, komapping) {
function Bems(params) {
ko.mapping = komapping;
var self = this;
self.response = ko.observable();
if (typeof params[0] != 'undefined') {
// Suppress search while loading
document.getElementById("bems-input").style.visibility = "hidden";
self.bemsId = String(params[0]);
$.ajaxSetup({
cache: false,
"error":function() {
document.getElementById("bems-input").style.visibility = "visible";
window.location = ("#/bems/");
}
});
$.getJSON('/app/skyline/api/bems/' + self.bemsId, function(ajax_response) {
document.getElementById("bems-input").align = "right";
document.getElementById("bems-input").style.visibility = "visible";
document.getElementById("bems-container").style.visibility = "visible";
ko.mapping.fromJS(ajax_response, {}, self.response);
});
}
// Nothing to do without bemsId parameter
}
return { viewModel: Bems, template: templateMarkup };
});
Я также протестирована со следующими изменениями:
self.response = ko.observable();
self.message = ko.observable("It works");
$.getJSON('/app/skyline/api/bems/' + self.bemsId, function(ajax_response) {
self.response = ko.mapping.fromJS(ajax_response);
В выше self.message
связывает должным образом, и могут быть доступны в шаблоне. Однако сопоставленные атрибуты в self.response
не связаны.
Ключевое различие между моей рабочей установкой и сломанным случаем находится в рабочем примере. Я установил результат ko.mapping во всю переменную модели представления, где здесь функция Bems - это модель представления, и это переменная под Vm.
Я еще раз взглянул на это сегодня и приблизился к проблеме. Похоже, что основной проблемой является порядок операций между обработкой обратного вызова AJAX и привязкой, происходящей через инфраструктуру приложения компонента Yoeman. Если я сделаю следующее и поставлю 2-секундную задержку в главном ViewModel, ему удастся загрузить содержимое привязки для первого атрибута привязки в представлении, но затем все равно будет умирать с помощью TypeError, даже если данные загрузились для атрибута. Это останавливает скрипт, и никакие другие атрибуты не загружаются.
require.js:900 TypeError: Unable to process binding "text: function(){return response().engagement_list()[0].CASE_TITLE }"(…)
function BemsViewModel(params) {
self.response = ko.observable();
$.getJSON('/app/skyline/api/bems/' + self.bemsId(), function(ajax_response) {
$("#bems-input").attr("align","right");
$("#bems-input").attr("style", "visibility: visible")
$("#bems-container").attr("style", "visibility: visible")
var foobar = {};
ko.mapping.fromJS(ajax_response, {}, foobar);
self.response(foobar);
Есть ли лучшая практика/шаблон для обеспечения связывания происходит только после того, как все биты модели представления загружаются с помощью этого шаблона KO компонент SSA? Любая помощь/идеи будут оценены. Я действительно не хочу вручную определять всю модель представления ...