我遇到了一个较旧的WebForms项目,我想知道我的方案是否有推荐的方法。
ko.applyBindings(vm, referenceToFeedbackDiv)
,它可以很好地连接反馈表。如何启用这两项内容 - 跨所有使用淘汰的页面和个别淘汰页面的模式对话框 - 协调工作?
请记住,问题是我希望能够有一个仅适用于客户端站点上的反馈div的反馈VM,并且我希望能够应用其他不需要知道任何内容的VM关于反馈vm。
这是在每一页上:
<div class="page">
<div class="main">
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
</div>
</div>
<div class="footer">
© <%=DateTime.Now.Year.ToString() %> Company, Inc. | <a href="/">Home</a> | <a
href="/about.aspx">About</a> |
<!-- begin feedback area -->
<span id="FeedbackArea">
<a data-bind="click: showModal">Feedback</a>
<div id="feedback-modal" title="What's on your mind?">
<div class="btn-group" id="feedbackButtonGroup">
<button class="btn" data-bind="click: UpdateFeedbackType" style="padding-top: 6px;">
<i class="fa fa-warning fa-2x fa-align-center"></i>
<br />
<span>Problem</span>
</button>
<button class="btn" data-bind="click: UpdateFeedbackType" style="padding-top: 6px;">
<i class="fa fa-question-circle fa-2x fa-align-center"></i>
<br />
<span>Question</span>
</button>
<button class="btn" data-bind="click: UpdateFeedbackType" style="padding-top: 6px;">
<i class="fa fa-lightbulb-o fa-2x fa-align-center"></i>
<br />
<span>Suggestion</span>
</button>
<button class="btn" data-bind="click: UpdateFeedbackType" style="padding-top: 6px;">
<i class="fa fa-thumbs-o-up fa-2x fa-align-center"></i>
<br />
<span>Praise</span>
</button>
<button class="btn" data-bind="click: UpdateFeedbackType" style="padding-top: 6px;">
<i class="fa fa-info-circle fa-2x fa-align-center"></i>
<br />
<span>General</span>
</button>
</div>
<br />
<br />
<textarea rows="5" placeholder="Enter feedback here" data-bind="value: feedbackText, valueUpdate: 'afterkeydown'"></textarea>
<br />
<br />
<button>Send Feedback</button>
<button data-bind="click: CancelFeedback">Cancel</button>
<h3>Other Information: </h3>
<ul>
<li><strong>Feedback Type:</strong> <span data-bind="text: feedbackType"></span></li>
<li><strong>Current URL:</strong> <span data-bind="text: pageUserIsOn"></span></li>
<li><strong>Current User: </strong><%=hdnLoggedInUsername.Value %></li>
<li><strong>Current Client: </strong>[Not yet captured]</li>
<li><strong>Current Tab: </strong>[Not yet captured]</li>
</ul>
</div>
</span>
<!-- End feedback area -->
</div>
......一个有点命名空间的FeedbackVM定义:
var FeedbackNamespace = FeedbackNamespace || {};
..命名空间本身的定义:
FeedbackNamespace = {
ViewModel: function () {
// etc. etc.
}
};
...并声明VM变量并在document.ready()
上连接它:
var FeedbackVM;
$(document).ready(function () {
FeedbackVM = new FeedbackNamespace.ViewModel();
ko.applyBindings(FeedbackVM, $('#FeedbackArea')[0]);
FeedbackVM.Start();
log('FeedbackVM started');
});
其他网页可能有也可能没有任何javascript,更不用说淘汰了。在这些页面上,FeedbackVM目前工作正常。
这些页面将有自己的命名空间JS文件,其中包含自己的document.ready()
事件,这会创建一个说invoiceUploaderVM = new InvoiceUploader.ViewModel()
的vm,然后调用ko.applyBindings(invoiceUploaderVM)
。
这是我们遇到麻烦的地方。
在Site.master页面中,我将整个页脚包装在“stopBindings:true”div中:
<div data-bind="stopBindings: true">
<div class="footer" id="footerDiv">
<!-- Feedback Viewmodel stuff in here -->
</div>
</div>
我已将stopBindings
定义为:
ko.bindingHandlers.stopBindings = {
init: function () {
return { controlsDescendantBindings: true };
}
};
My Feedback.js文件作为全局JS文件的一部分加载到每个页面上,具有:
var FeedbackNamespace = FeedbackNamespace || {};
FeedbackNamespace = {
// defines viewmodel, etc. etc.
};
var FeedbackVM;
$(document).ready(function () {
FeedbackVM = new FeedbackNamespace.ViewModel();
ko.applyBindings(FeedbackVM, $('#footerDiv')[0]);
FeedbackVM.Start();
log('FeedbackVM started');
});
这种方法非常有效 - 只要没有其他视图模型被绑定。在从我的母版页继承的页面上,我可能会有:
$(document).ready(function () {
'use strict';
vm = new invoiceUploader.ViewModel();
ko.applyBindings(vm);
});
我希望如此:
但是,我在加载子页面时遇到错误:
注释该行以应用反馈绑定使得这项工作再次正常。
我做错了什么?
答案 0 :(得分:0)
我想我会将你的模态的视图模型放在一个全局对象中,除了在共享脚本中应用绑定之外,还要做任何你需要做的事情:
window.feedbackModal = {
foo: ko.observable("Whatever you need to do here"),
bar: ko.observable("assuming it can be done the same on every page")
};
然后在Site.master
<div class="feedback-modal" data-bind="with: feedbackModal">
<p data-bind="text: foo"></p>
<p data-bind="text: bar"></p>
</div>
在每个页面的脚本中:
function ViewModel() {
this.individualProperty = ko.observable(true);
this.specificAction = function() { /* do something specific to this page */ };
this.feedbackModal = window.feedbackModal;
}
ko.applyBindings(new ViewModel());
所以window.feedbackModal可能是未定义的,它不会给你带来问题,但如果你ko.applyBindings
,你必须在视图模型中公开feedbackModal
属性,否则你会收到错误应用这些绑定。
当然,有更聪明的方法可以实现这个基本想法,以便最好地适应您的模式,但重要的是,如你所知,你不能两次应用绑定,所以你需要推迟对您最具体的代码执行任务,并将可重复使用的代码公开给它。
答案 1 :(得分:0)
以下是将常用模块与页面相关模块分离的另一种策略:
// An example of a module that runs on everypage
var modalDialog = function(){
this.name = "dialog1";
this.title = ko.observable("My Modal Title");
this.content = ko.observable("My Modal content is also something");
}
// An example of a module that runs on everypage
var modalDialog2 = function(){
this.name = "dialog2";
this.title = ko.observable("My Modal Title 2");
this.content = ko.observable("My Modal content is also something 2");
}
// Either generate it automatically or by hand
// to represent which modules are common
var commonModules = [modalDialog, modalDialog2];
// An example of a module only for this page
var pageModule = function(){
this.pageFunction = function(){
alert("Called page function");
}
}
// Composition is the final object you will actually bind to the page
var composition = {
pageMod: new pageModule()
}
// Let's add the common modules to the composition
ko.utils.arrayForEach(commonModules, function(item){
var module = new item();
composition[module.name] = module;
});
// Bind the composition
ko.applyBindings(composition);
示例HTML将是:
<div class="modalDialog">
<h2 data-bind="text: dialog1.title"><h2>
<h2 data-bind="text: dialog1.content"><h2>
</div>
<div class="modalDialog">
<h2 data-bind="text: dialog2.title"><h2>
<h2 data-bind="text: dialog2.content"><h2>
</div>
<div id="content">
<h2>Welcome to page</h2>
<div id="somePageStuff">
<a href="#" data-bind="click: pageMod.pageFunction">Click me</a>
</div>
</div>
答案 2 :(得分:0)
您可以使用一种技术来设置此功能,使您的绑定范围不受页面中特定区域的限制。
退房:How to stop knockout.js bindings evaluating on child elements
示例:强> http://jsfiddle.net/anAgent/RfM2R/
HTML
<div id="Main">
<label data-bind="text: ViewModel.Name">default</label>
<div data-bind="stopBindings: true">
<div id="ChildBinding">
<label data-bind="text: AnotherViewModel.Name">default</label>
</div>
</div>
</div>
<强>的JavaScript 强>
$(function () {
ko.bindingHandlers.stopBindings = {
init: function () {
return {
controlsDescendantBindings: true
};
}
};
var data = {
ViewModel: {
Name: "Testing"
}
};
var data2 = {
AnotherViewModel: {
Name: "More Testing"
}
};
ko.applyBindings(data, $("#Main")[0]);
ko.applyBindings(data2, $("#MyModalHtml")[0]);
});