Javascript 动态生成单选按钮视图,使用ko.observable检查绑定不起作用
这是我的第一个问题,请原谅我在发帖时的错误 我的问题可能看起来与 根据我的研究,上述问题与我的问题非常接近,但仍然无法解决 在我的要求中,每个问题都有多个单选按钮可供选择,还有上一个和下一个导航按钮。 问题和选项是动态生成的,用户对问题所做的选择不会在viewmodel属性self.current_question.response中捕获 下面是我的观点的片段Javascript 动态生成单选按钮视图,使用ko.observable检查绑定不起作用,javascript,jquery-mobile,knockout.js,radio-button,Javascript,Jquery Mobile,Knockout.js,Radio Button,这是我的第一个问题,请原谅我在发帖时的错误 我的问题可能看起来与 根据我的研究,上述问题与我的问题非常接近,但仍然无法解决 在我的要求中,每个问题都有多个单选按钮可供选择,还有上一个和下一个导航按钮。 问题和选项是动态生成的,用户对问题所做的选择不会在viewmodel属性self.current_question.response中捕获 下面是我的观点的片段 <div id="questionpage" data-role="page" data-theme="c">
<div id="questionpage" data-role="page" data-theme="c">
<div data-role="header" data-theme="c">
<h1>Question <span data-bind="text: current_question().queNo"></span></h1>
</div><!-- /header -->
<!-- inputs -->
<div id="inputs" data-role="content" data-theme="c">
<a id="prevbtn" href="#question" data-icon="arrow-l" data-bind="click: $root.prev, visible: hasPrev()" data-role="button" data-inline="true">Prev</a>
<a id="nextbtn" href="#question" data-icon="arrow-r" data-bind="click: $root.next, visible: hasNext()" data-role="button" data-inline="true">Next</a>
<a id="completebtn" href="#question" data-icon="check" data-bind="click: $root.submit, visible: !hasNext()" data-role="button" data-inline="true">Submit</a>
<p data-bind="text: current_question().queText"></p>
<div id="inputdiv">
</div>
</div><!-- /content -->
</div><!-- /page -->
问题:
下面是我的Viewmodel的片段
// Question response object
function QuestionResponse(stuId, examQueId,selAns)
{
var self=this;
self.Student__c=stuId;
self.Exam_Question__c=examQueId;
self.Selected_Answer__c=selAns;
}
// Question object
function Question()
{
var self=this;
self.response=ko.observable('');
self.options=ko.observableArray();
}
function Question(id, queNo, queText, response, queChA, queChB, queChC, queChD, queChE)
{
var self=this;
self.id=id;
self.queNo=queNo;
self.queText=queText;
self.response=ko.observable(response);
self.options=ko.observableArray();
//self.checked=ko.observableArray();
// helper function to add an option
self.addOption = function(option)
{
if (null!=option)
{
self.options().push(option);
}
}
self.addOption(queChA);
self.addOption(queChB);
self.addOption(queChC);
self.addOption(queChD);
self.addOption(queChE);
}
function ExamViewModel()
{
var self=this;
// initialise variables to default observables
// self.question_response=ko.observable(new QuestionResponse());
self.current_question=ko.observable(new Question());
self.current_question_no=0;
self.email=ko.observable('Your email id');
self.questions=ko.observableArray();
self.studentId;
self.errorMsg=ko.observable('');
self.completeMsg=ko.observable('');
self.hasPrevious=ko.observable();
self.hasNext=ko.observable(false);
self.hasPrev=ko.observable(false);
// function executed when the user clicks the 'next' button
self.next=function()
{
$.mobile.loading( 'show', { theme: "a", text: "Loading", textVisible: true });
// advance to the next question
self.current_question_no++;
self.current_question(self.questions()[self.current_question_no]());
// setup previous/next buttons
self.hasPrev(true);
self.hasNext(self.current_question_no<self.questions().length-1);
// add the input markup
self.addInput();
$.mobile.loading('hide');
}
// function executed when the user clicks the 'prev' button - could refactor
// some of this and the next function into a common helper
self.prev=function()
{
$.mobile.loading( 'show', { theme: "a", text: "Loading", textVisible: true });
//alert('in prev '+self.current_question().response);
self.current_question_no--;
self.current_question(self.questions()[self.current_question_no]());
self.hasPrev(self.current_question_no!=0);
self.hasNext(true);
self.addInput();
$.mobile.loading('hide');
}
// callback for the JavaScript remoting call
self.responseCB=function(record, event)
{
if ( (!event) || (event.status) )
{
$.each(record,
function()
{
var question=new ko.observable(new Question(
this.Id, this.Exam_Question_Number__c, this.Question__r.Question_Text__c,'',
this.Question__r.ChoiceA__c, this.Question__r.ChoiceB__c, this.Question__r.ChoiceC__c,
this.Question__r.ChoiceD__c,this.Question__r.ChoiceE__c));
self.questions.push(question);
// if the current question is empty, set it to this question
if (typeof self.current_question().queText === 'undefined')
{
self.current_question(question());
}
});
// setup whether to display the next button
if (self.questions().length>1)
{
self.hasNext(true);
}
// add the input markup
self.addInput();
}
else if (event.type === 'exception')
{
self.error(event.message);
}
}
// add the appropriate input markup
self.addInput=function()
{
self.addRadioInput();
}
self.addRadioInput=function()
{
$('#inputdiv').html(
'<div id="radio" data-bind="value: $root.current_question.response">' +
' <fieldset id="radiocontrol" data-role="controlgroup">' +
' <' + // Visualforce will break the comment that encloses the containerless element, so split over two lines
'!-- ko foreach: current_question().options --> ' +
' <input name="radio-options" type="radio" data-bind="value: $data, checked: $root.current_question.response, attr: {id:\'rb_\' + $index() }"></input> ' +
' <label data-bind="attr:{for : \'rb_\' + $index() }, text: $data"></label> ' +
' <' +
'!-- /ko --> ' +
' </fieldset> ' +
'</div> ');
// bind the new markup to the viewmodel
ko.applyBindings(viewModel, $('#radio')[0]);
// trigger JQM to enhance the newly created radio button div
$('#radio').trigger('create');
}
}
//问题响应对象
函数问题响应(stuId、examQueId、selAns)
{
var self=这个;
self.Student\uuu c=stuId;
self.Exam\u Question\u c=examQueId;
self.Selected_uAnswer_uuC=selAns;
}
//问题对象
函数问题()
{
var self=这个;
自我反应=可观察(“”);
self.options=ko.observearray();
}
功能问题(id、queNo、queText、response、queChA、queChB、queChC、queChD、queChE)
{
var self=这个;
self.id=id;
self.queNo=queNo;
self.queText=queText;
自我反应=可观察(反应);
self.options=ko.observearray();
//self.checked=ko.observearray();
//用于添加选项的帮助器函数
self.addOption=函数(选项)
{
如果(null!=选项)
{
self.options().push(选项);
}
}
self.addOption(queChA);
self.addOption(queChB);
self.addOption(queChC);
self.addOption(queChD);
self.addOption(queChE);
}
函数ExamViewModel()
{
var self=这个;
//将变量初始化为默认观察值
//self.question_response=ko.observable(新的QuestionResponse());
self.current_question=ko.observable(新问题());
自身当前问题编号=0;
self.email=ko.observable(“您的电子邮件id”);
self.questions=ko.observearray();
自学成才;
self.errorMsg=ko.可观察(“”);
自我完成SG=可观察到的ko(“”);
self.hasPrevious=ko.observable();
self.hasNext=ko.可观察(假);
self.hasPrev=ko.可观察(假);
//用户单击“下一步”按钮时执行的函数
self.next=函数()
{
$.mobile.loading('show',{theme:“a”,text:“loading”,textVisible:true});
//进入下一个问题
self.current_question_no++;
self.current_-question(self.questions()[self.current_-question_-no]());
//设置上一个/下一个按钮
self.hasprov(真);
self.hasNext(self.current\u问题1)
{
self.hasNext(true);
}
//添加输入标记
self.addInput();
}
else if(event.type==='exception')
{
self.error(事件消息);
}
}
//添加适当的输入标记
self.addInput=函数()
{
self.addRadioInput();
}
self.addRadioInput=函数()
{
$('#inputdiv').html(
'' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ');
//将新标记绑定到viewmodel
ko.applyBindings(viewModel,$(#radio')[0]);
//触发JQM以增强新创建的单选按钮div
$('#radio')。触发器('create');
}
}
已经尝试了多个选项,但无法找到我的代码的错误。非常感谢您的帮助。您的div#inputdiv
应该是这样的,它可以适当地显示单选按钮,这样您就不必借助jQuery注入DOM元素。我的逻辑可能不完全符合您的要求,但您可以根据需要进行调整
带有绑定的仅在填充其变量时才会呈现其内容。div中的变量将引用变量的成员。
jqm
绑定是您需要编写(或查找)的自定义绑定处理程序
那至少值得一试。还可以查看一下,或者在谷歌上搜索jqm和knockout。问题是您在viewmodel中使用了jQuery,这意味着您没有正确地建模视图。如果没有看到您的radiobutton HTML和绑定,我们就看不出您为什么没有获得所选的值集。radiobutton HTML是在viewmodel函数self.addRadioInput中动态构建的,插入该单选按钮的HTML div标记是
。如果我遗漏了什么,请告诉我。通过jQuery插入代码是错误的做法。敲除可以处理动态创建元素。单选按钮上的绑定似乎适合设置response
。为什么在div#radio
上有值
绑定?是的,没有必要在div#radio
上绑定值,但我正在尝试您建议的方法。谢谢您的回答,您刚刚解决了我的问题。对于您提出的第一个问题,您问我为什么要使用jQuery构建视图,这是因为我从研究中了解到,一旦加载页面,JQM增强将无法工作。现在,尽管人们的回答越来越多,但问题和选择却越来越多
<div id="inputdiv" data-bind="with:$root.current_question">
<div id="radio" data-bind="jqm: true">
<fieldset id="radiocontrol" data-role="controlgroup" data-bind="foreach:options">
<input name="radio-options" type="radio" data-bind="value: $data, checked: response, attr: {id:'rb_' + $index() }" />
<label data-bind="attr:{for: 'rb_' + $index() }, text: $data"></label>
</fieldset>
</div>
</div>
ko.bindingHandlers.jqm = {
init: function (el) {
$(el).create();
}
};